Skip to content

Commit 49f7408

Browse files
Merge pull request #587 from aguycalled/createrawscriptaddress
Add support for raw script addresses
2 parents 6fe0683 + 0088e93 commit 49f7408

9 files changed

Lines changed: 106 additions & 1 deletion

File tree

‎qa/pull-tester/rpc-tests.py‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,7 @@
187187
'sendtoaddress.py',
188188
'stakeimmaturebalance.py',
189189
'rpc-help.py',
190+
'createrawscriptaddress.py'
190191
]
191192
#if ENABLE_ZMQ:
192193
# testScripts.append('zmq_test.py')
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
#!/usr/bin/env python3
2+
# Copyright (c) 2019 The Navcoin 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+
from test_framework.test_framework import NavCoinTestFramework
7+
from test_framework.util import *
8+
9+
class CreateRawScriptAddress(NavCoinTestFramework):
10+
"""Tests the creation of a raw script address."""
11+
12+
def __init__(self):
13+
super().__init__()
14+
self.setup_clean_chain = True
15+
self.num_nodes = 1
16+
17+
def setup_network(self, split=False):
18+
self.nodes = self.setup_nodes()
19+
self.is_network_split = split
20+
21+
def run_test(self):
22+
assert(self.nodes[0].createrawscriptaddress("6ac1") == "3HnzbJ4TR9")
23+
assert(self.nodes[0].validateaddress("3HnzbJ4TR9")["isvalid"] == True)
24+
assert(self.nodes[0].validateaddress("3HnzbJ4TR9")["scriptPubKey"] == "6ac1")
25+
26+
self.nodes[0].staking(False)
27+
self.nodes[0].generate(100)
28+
self.nodes[0].sendtoaddress("3HnzbJ4TR9", 100)
29+
self.nodes[0].generate(1)
30+
31+
assert(self.nodes[0].getinfo()["communityfund"]["available"] == 100)
32+
33+
if __name__ == '__main__':
34+
CreateRawScriptAddress().main()

‎src/base58.cpp‎

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,12 @@ bool CNavCoinAddress::Set(const CScriptID& id)
252252
return true;
253253
}
254254

255+
bool CNavCoinAddress::Set(const CScript& scriptIn)
256+
{
257+
SetData(Params().Base58Prefix(CChainParams::RAW_SCRIPT_ADDRESS), &scriptIn[0], scriptIn.size());
258+
return true;
259+
}
260+
255261
bool CNavCoinAddress::Set(const CTxDestination& dest)
256262
{
257263
return boost::apply_visitor(CNavCoinAddressVisitor(this), dest);
@@ -286,6 +292,8 @@ bool CNavCoinAddress::IsValid(const CChainParams& params) const
286292
{
287293
if (vchVersion == params.Base58Prefix(CChainParams::COLDSTAKING_ADDRESS))
288294
return vchData.size() == 40;
295+
if (vchVersion == params.Base58Prefix(CChainParams::RAW_SCRIPT_ADDRESS))
296+
return vchData.size() > 0;
289297
bool fCorrectSize = vchData.size() == 20;
290298
bool fKnownVersion = vchVersion == params.Base58Prefix(CChainParams::PUBKEY_ADDRESS) ||
291299
vchVersion == params.Base58Prefix(CChainParams::SCRIPT_ADDRESS);
@@ -311,6 +319,12 @@ CTxDestination CNavCoinAddress::Get() const
311319
return CKeyID(id);
312320
else if (vchVersion == Params().Base58Prefix(CChainParams::SCRIPT_ADDRESS))
313321
return CScriptID(id);
322+
else if (vchVersion == Params().Base58Prefix(CChainParams::RAW_SCRIPT_ADDRESS))
323+
{
324+
std::vector<unsigned char> vData(vchData.size());
325+
memcpy(&vData[0], &vchData[0], vchData.size());
326+
return CScript(vData.begin(), vData.end());
327+
}
314328
else
315329
return CNoDestination();
316330
}
@@ -371,6 +385,11 @@ bool CNavCoinAddress::IsScript() const
371385
return IsValid() && vchVersion == Params().Base58Prefix(CChainParams::SCRIPT_ADDRESS);
372386
}
373387

388+
bool CNavCoinAddress::IsRawScript() const
389+
{
390+
return IsValid() && vchVersion == Params().Base58Prefix(CChainParams::RAW_SCRIPT_ADDRESS);
391+
}
392+
374393
void CNavCoinSecret::SetKey(const CKey& vchSecret)
375394
{
376395
assert(vchSecret.IsValid());

‎src/base58.h‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,16 +109,19 @@ class CNavCoinAddress : public CBase58Data {
109109
bool Set(const CKeyID &id);
110110
bool Set(const CKeyID &id, const CKeyID &id2);
111111
bool Set(const CScriptID &id);
112+
bool Set(const CScript &scriptIn);
112113
bool Set(const CTxDestination &dest);
113114
bool IsValid() const;
114115
bool IsValid(const CChainParams &params) const;
115116
bool IsColdStakingAddress(const CChainParams& params) const;
117+
bool IsRawScript() const;
116118

117119
CNavCoinAddress() {}
118120
CNavCoinAddress(const CTxDestination &dest) { Set(dest); }
119121
CNavCoinAddress(const CKeyID &id, const CKeyID &id2) { Set(id, id2); }
120122
CNavCoinAddress(const std::string& strAddress) { SetString(strAddress); }
121123
CNavCoinAddress(const char* pszAddress) { SetString(pszAddress); }
124+
CNavCoinAddress(const CScript &scriptIn) { Set(scriptIn); }
122125

123126
CTxDestination Get() const;
124127
bool GetKeyID(CKeyID &keyID) const;

‎src/chainparams.cpp‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,7 @@ class CMainParams : public CChainParams {
222222
base58Prefixes[PUBKEY_ADDRESS] = std::vector<unsigned char>(1,53);
223223
base58Prefixes[COLDSTAKING_ADDRESS] = std::vector<unsigned char>(1,21); // cold staking addresses start with 'X'
224224
base58Prefixes[SCRIPT_ADDRESS] = std::vector<unsigned char>(1,85);
225+
base58Prefixes[RAW_SCRIPT_ADDRESS] = std::vector<unsigned char>(1,60);
225226
base58Prefixes[SECRET_KEY] = std::vector<unsigned char>(1,150);
226227
base58Prefixes[EXT_PUBLIC_KEY] = boost::assign::list_of(0x04)(0x88)(0xB2)(0x1E).convert_to_container<std::vector<unsigned char> >();
227228
base58Prefixes[EXT_SECRET_KEY] = boost::assign::list_of(0x04)(0x88)(0xAD)(0xE4).convert_to_container<std::vector<unsigned char> >();
@@ -428,6 +429,7 @@ class CTestNetParams : public CChainParams {
428429
base58Prefixes[PUBKEY_ADDRESS] = std::vector<unsigned char>(1,111);
429430
base58Prefixes[COLDSTAKING_ADDRESS] = std::vector<unsigned char>(1,8); // cold staking addresses start with 'C/D'
430431
base58Prefixes[SCRIPT_ADDRESS] = std::vector<unsigned char>(1,196);
432+
base58Prefixes[RAW_SCRIPT_ADDRESS] = std::vector<unsigned char>(1,60);
431433
base58Prefixes[SECRET_KEY] = std::vector<unsigned char>(1,239);
432434
base58Prefixes[EXT_PUBLIC_KEY] = boost::assign::list_of(0x40)(0x88)(0x2B)(0xE1).convert_to_container<std::vector<unsigned char> >();
433435
base58Prefixes[EXT_SECRET_KEY] = boost::assign::list_of(0x40)(0x88)(0xDA)(0x4E).convert_to_container<std::vector<unsigned char> >();
@@ -618,6 +620,7 @@ class CDevNetParams : public CChainParams {
618620
base58Prefixes[PUBKEY_ADDRESS] = std::vector<unsigned char>(1,111);
619621
base58Prefixes[COLDSTAKING_ADDRESS] = std::vector<unsigned char>(1,63); // cold staking addresses start with 'S'
620622
base58Prefixes[SCRIPT_ADDRESS] = std::vector<unsigned char>(1,196);
623+
base58Prefixes[RAW_SCRIPT_ADDRESS] = std::vector<unsigned char>(1,60);
621624
base58Prefixes[SECRET_KEY] = std::vector<unsigned char>(1,239);
622625
base58Prefixes[EXT_PUBLIC_KEY] = boost::assign::list_of(0x40)(0x88)(0x2B)(0xE1).convert_to_container<std::vector<unsigned char> >();
623626
base58Prefixes[EXT_SECRET_KEY] = boost::assign::list_of(0x40)(0x88)(0xDA)(0x4E).convert_to_container<std::vector<unsigned char> >();
@@ -798,6 +801,7 @@ class CRegTestParams : public CChainParams {
798801
base58Prefixes[PUBKEY_ADDRESS] = std::vector<unsigned char>(1,111);
799802
base58Prefixes[COLDSTAKING_ADDRESS] = std::vector<unsigned char>(1,63); // cold staking addresses start with 'S'
800803
base58Prefixes[SCRIPT_ADDRESS] = std::vector<unsigned char>(1,196);
804+
base58Prefixes[RAW_SCRIPT_ADDRESS] = std::vector<unsigned char>(1,60);
801805
base58Prefixes[SECRET_KEY] = std::vector<unsigned char>(1,239);
802806
base58Prefixes[EXT_PUBLIC_KEY] = boost::assign::list_of(0x40)(0x88)(0x2B)(0xE1).convert_to_container<std::vector<unsigned char> >();
803807
base58Prefixes[EXT_SECRET_KEY] = boost::assign::list_of(0x40)(0x88)(0xDA)(0x4E).convert_to_container<std::vector<unsigned char> >();

‎src/chainparams.h‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ class CChainParams
4747
enum Base58Type {
4848
PUBKEY_ADDRESS,
4949
SCRIPT_ADDRESS,
50+
RAW_SCRIPT_ADDRESS,
5051
SECRET_KEY,
5152
EXT_PUBLIC_KEY,
5253
EXT_SECRET_KEY,

‎src/script/standard.cpp‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -368,6 +368,12 @@ class CScriptVisitor : public boost::static_visitor<bool>
368368
*script << OP_HASH160 << ToByteVector(scriptID) << OP_EQUAL;
369369
return true;
370370
}
371+
372+
bool operator()(const CScript &scriptIn) const {
373+
script->clear();
374+
*script += scriptIn;
375+
return true;
376+
}
371377
};
372378
}
373379

‎src/script/standard.h‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ class CNoDestination {
7676
* * Pair of two CKeyID: TX_COLDSTAKING destination
7777
* A CTxDestination is the internal data type encoded in a CNavCoinAddress
7878
*/
79-
typedef boost::variant<CNoDestination, CKeyID, CScriptID, pair<CKeyID, CKeyID>> CTxDestination;
79+
typedef boost::variant<CNoDestination, CKeyID, CScriptID, pair<CKeyID, CKeyID>, CScript> CTxDestination;
8080

8181
const char* GetTxnOutputType(txnouttype t);
8282

‎src/wallet/rpcwallet.cpp‎

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,42 @@ string AccountFromValue(const UniValue& value)
115115
return strAccount;
116116
}
117117

118+
UniValue createrawscriptaddress(const UniValue& params, bool fHelp)
119+
{
120+
if (fHelp || params.size() != 1)
121+
throw runtime_error(
122+
"createrawscriptaddress \"hex script\"\n"
123+
"\nReturns the NavCoin address for the specified raw hex script.\n"
124+
"\nArguments:\n"
125+
"1. \"hex script\" (string) The hex script to encode in the address.\n"
126+
"\nResult:\n"
127+
"\"navcoinaddress\" (string) The navcoin address\n"
128+
"\nExamples:\n"
129+
+ HelpExampleCli("createrawscriptaddress", "6ac4c5")
130+
);
131+
132+
std::string data = params[0].get_str();
133+
134+
if (!IsHex(data))
135+
throw JSONRPCError(RPC_MISC_ERROR, "the script is not expressed in hexadecimal");
136+
137+
std::vector<unsigned char> vData = ParseHex(data);
138+
139+
CScript script(vData.begin(), vData.end());
140+
141+
std::string strAsm = ScriptToAsmStr(script);
142+
143+
if (strAsm.find("[error]") != std::string::npos || strAsm.find("OP_UNKNOWN") != std::string::npos)
144+
throw JSONRPCError(RPC_MISC_ERROR, "the script includes invalid or unknown op codes");
145+
146+
CNavCoinAddress address(script);
147+
148+
if (!address.IsValid())
149+
throw JSONRPCError(RPC_MISC_ERROR, "the generated address is not valid");
150+
151+
return address.ToString();
152+
}
153+
118154
UniValue getnewaddress(const UniValue& params, bool fHelp)
119155
{
120156
if (!EnsureWalletIsAvailable(fHelp))
@@ -3683,6 +3719,7 @@ static const CRPCCommand commands[] =
36833719
{ "wallet", "addmultisigaddress", &addmultisigaddress, true },
36843720
{ "wallet", "addwitnessaddress", &addwitnessaddress, true },
36853721
{ "wallet", "backupwallet", &backupwallet, true },
3722+
{ "wallet", "createrawscriptaddress", &createrawscriptaddress, true },
36863723
{ "wallet", "dumpprivkey", &dumpprivkey, true },
36873724
{ "wallet", "dumpmasterprivkey", &dumpmasterprivkey, true },
36883725
{ "wallet", "dumpmnemonic", &dumpmnemonic, true },

0 commit comments

Comments
 (0)