11 #include "validation.h" 26 #include <boost/algorithm/string.hpp> 27 #include <boost/date_time/posix_time/posix_time.hpp> 32 std::string
static EncodeDumpTime(int64_t nTime) {
36 int64_t
static DecodeDumpTime(
const std::string &str) {
37 static const boost::posix_time::ptime epoch = boost::posix_time::from_time_t(0);
38 static const std::locale loc(std::locale::classic(),
39 new boost::posix_time::time_input_facet(
"%Y-%m-%dT%H:%M:%SZ"));
40 std::istringstream iss(str);
42 boost::posix_time::ptime ptime(boost::date_time::not_a_date_time);
44 if (ptime.is_not_a_date_time())
46 return (ptime - epoch).total_seconds();
49 std::string
static EncodeDumpString(
const std::string &str) {
50 std::stringstream ret;
51 for (
unsigned char c : str) {
52 if (c <= 32 || c >= 128 || c ==
'%') {
53 ret <<
'%' <<
HexStr(&c, &c + 1);
62 std::stringstream ret;
63 for (
unsigned int pos = 0; pos < str.length(); pos++) {
64 unsigned char c = str[pos];
65 if (c ==
'%' && pos+2 < str.length()) {
66 c = (((str[pos+1]>>6)*9+((str[pos+1]-
'0')&15)) << 4) |
67 ((str[pos+2]>>6)*9+((str[pos+2]-
'0')&15));
83 throw std::runtime_error(
84 "importprivkey \"privkey\" ( \"label\" ) ( rescan )\n" 85 "\nAdds a private key (as returned by dumpprivkey) to your wallet.\n" 87 "1. \"privkey\" (string, required) The private key (see dumpprivkey)\n" 88 "2. \"label\" (string, optional, default=\"\") An optional label\n" 89 "3. rescan (boolean, optional, default=true) Rescan the wallet for transactions\n" 90 "\nNote: This call can take minutes to complete if rescan is true.\n" 92 "\nDump a private key\n" 94 "\nImport the private key with rescan\n" 96 "\nImport using a label and without rescan\n" 98 "\nImport using default blank label and without rescan\n" 100 "\nAs a JSON-RPC call\n" 101 +
HelpExampleRpc(
"importprivkey",
"\"mykey\", \"testing\", false")
110 std::string strLabel =
"";
123 bool fGood = vchSecret.
SetString(strSecret);
138 if (pwallet->
HaveKey(vchAddress)) {
167 throw std::runtime_error(
169 "\nStops current wallet rescan triggered e.g. by an importprivkey call.\n" 171 "\nImport a private key\n" 173 "\nAbort the running wallet rescan\n" 175 "\nAs a JSON-RPC call\n" 198 if (isRedeemScript) {
228 throw std::runtime_error(
229 "importaddress \"address\" ( \"label\" rescan p2sh )\n" 230 "\nAdds a script (in hex) or address that can be watched as if it were in your wallet but cannot be used to spend.\n" 232 "1. \"script\" (string, required) The hex-encoded script (or address)\n" 233 "2. \"label\" (string, optional, default=\"\") An optional label\n" 234 "3. rescan (boolean, optional, default=true) Rescan the wallet for transactions\n" 235 "4. p2sh (boolean, optional, default=false) Add the P2SH version of the script as well\n" 236 "\nNote: This call can take minutes to complete if rescan is true.\n" 237 "If you have the full public key, you should call importpubkey instead of this.\n" 238 "\nNote: If you import a non-standard raw script in hex form, outputs sending to it will be treated\n" 239 "as change, and not show up in many RPCs.\n" 241 "\nImport a script with rescan\n" 243 "\nImport using a label without rescan\n" 244 +
HelpExampleCli(
"importaddress",
"\"myscript\" \"testing\" false") +
245 "\nAs a JSON-RPC call\n" 246 +
HelpExampleRpc(
"importaddress",
"\"myscript\", \"testing\", false")
250 std::string strLabel =
"";
299 throw std::runtime_error(
300 "importprunedfunds\n" 301 "\nImports funds without rescan. Corresponding address or script must previously be included in wallet. Aimed towards pruned wallets. The end-user is responsible to import additional transactions that subsequently spend the imported outputs or rescan after the point in the blockchain the transaction is included.\n" 303 "1. \"rawtransaction\" (string, required) A raw transaction in hex funding an already-existing address in wallet\n" 304 "2. \"txoutproof\" (string, required) The hex output from gettxoutproof that contains the transaction\n" 311 CWalletTx wtx(pwallet, MakeTransactionRef(std::move(tx)));
318 std::vector<uint256> vMatch;
319 std::vector<unsigned int> vIndex;
320 unsigned int txnIndex = 0;
321 if (merkleBlock.txn.ExtractMatches(vMatch, vIndex) == merkleBlock.header.hashMerkleRoot) {
328 std::vector<uint256>::const_iterator it;
329 if ((it = std::find(vMatch.begin(), vMatch.end(), hashTx))==vMatch.end()) {
333 txnIndex = vIndex[it - vMatch.begin()];
340 wtx.
hashBlock = merkleBlock.header.GetHash();
344 if (pwallet->
IsMine(wtx)) {
360 throw std::runtime_error(
361 "removeprunedfunds \"txid\"\n" 362 "\nDeletes the specified transaction from the wallet. Meant for use with pruned wallets and as a companion to importprunedfunds. This will affect wallet balances.\n" 364 "1. \"txid\" (string, required) The hex-encoded id of the transaction you are deleting\n" 366 +
HelpExampleCli(
"removeprunedfunds",
"\"a8d0c0184dde994a09ec054286f1ce581bebf46446a512166eae7628734ea0a5\"") +
367 "\nAs a JSON-RPC call\n" 368 +
HelpExampleRpc(
"removeprunedfunds",
"\"a8d0c0184dde994a09ec054286f1ce581bebf46446a512166eae7628734ea0a5\"")
375 std::vector<uint256> vHash;
376 vHash.push_back(hash);
377 std::vector<uint256> vHashOut;
383 if(vHashOut.empty()) {
398 throw std::runtime_error(
399 "importpubkey \"pubkey\" ( \"label\" rescan )\n" 400 "\nAdds a public key (in hex) that can be watched as if it were in your wallet but cannot be used to spend.\n" 402 "1. \"pubkey\" (string, required) The hex-encoded public key\n" 403 "2. \"label\" (string, optional, default=\"\") An optional label\n" 404 "3. rescan (boolean, optional, default=true) Rescan the wallet for transactions\n" 405 "\nNote: This call can take minutes to complete if rescan is true.\n" 407 "\nImport a public key with rescan\n" 409 "\nImport using a label without rescan\n" 410 +
HelpExampleCli(
"importpubkey",
"\"mypubkey\" \"testing\" false") +
411 "\nAs a JSON-RPC call\n" 412 +
HelpExampleRpc(
"importpubkey",
"\"mypubkey\", \"testing\", false")
416 std::string strLabel =
"";
431 CPubKey pubKey(data.begin(), data.end());
432 if (!pubKey.IsFullyValid())
458 throw std::runtime_error(
459 "importwallet \"filename\"\n" 460 "\nImports keys from a wallet dump file (see dumpwallet).\n" 462 "1. \"filename\" (string, required) The wallet file\n" 464 "\nDump the wallet\n" 466 "\nImport the wallet\n" 468 "\nImport using the json rpc call\n" 480 file.open(request.
params[0].
get_str().c_str(), std::ios::in | std::ios::ate);
488 int64_t nFilesize = std::max((int64_t)1, (int64_t)file.tellg());
489 file.seekg(0, file.beg);
492 while (file.good()) {
493 pwallet->
ShowProgress(
"", std::max(1, std::min(99, (
int)(((
double)file.tellg() / (double)nFilesize) * 100))));
495 std::getline(file, line);
496 if (line.empty() || line[0] ==
'#')
499 std::vector<std::string> vstr;
500 boost::split(vstr, line, boost::is_any_of(
" "));
514 int64_t nTime = DecodeDumpTime(vstr[1]);
515 std::string strLabel;
517 for (
unsigned int nStr = 2; nStr < vstr.size(); nStr++) {
518 if (boost::algorithm::starts_with(vstr[nStr],
"#"))
520 if (vstr[nStr] ==
"change=1")
522 if (vstr[nStr] ==
"reserve=1")
524 if (boost::algorithm::starts_with(vstr[nStr],
"label=")) {
537 nTimeBegin = std::min(nTimeBegin, nTime);
559 throw std::runtime_error(
560 "dumpprivkey \"address\"\n" 561 "\nReveals the private key corresponding to 'address'.\n" 562 "Then the importprivkey can be used with this output\n" 564 "1. \"address\" (string, required) The raven address for the private key\n" 566 "\"key\" (string) The private key\n" 582 const CKeyID *keyID = boost::get<CKeyID>(&dest);
587 if (!pwallet->
GetKey(*keyID, vchSecret)) {
602 throw std::runtime_error(
603 "dumpwallet \"filename\"\n" 604 "\nDumps all wallet keys in a human-readable format to a server-side file. This does not allow overwriting existing files.\n" 606 "1. \"filename\" (string, required) The filename with path (either absolute or relative to ravend)\n" 609 " \"filename\" : { (string) The filename with full absolute path\n" 620 boost::filesystem::path filepath = request.
params[0].
get_str();
621 filepath = boost::filesystem::absolute(filepath);
628 if (boost::filesystem::exists(filepath)) {
633 file.open(filepath.string().c_str());
637 std::map<CTxDestination, int64_t> mapKeyBirth;
642 std::vector<std::pair<int64_t, CKeyID> > vKeyBirth;
643 for (
const auto& entry : mapKeyBirth) {
644 if (
const CKeyID* keyID = boost::get<CKeyID>(&entry.first)) {
645 vKeyBirth.push_back(std::make_pair(entry.second, *keyID));
649 std::sort(vKeyBirth.begin(), vKeyBirth.end());
663 if (pwallet->
GetKey(seed_id, seed)) {
668 b58extkey.
SetKey(masterKey);
670 file <<
"# extended private masterkey: " << b58extkey.
ToString() <<
"\n\n";
673 for (std::vector<std::pair<int64_t, CKeyID> >::const_iterator it = vKeyBirth.begin(); it != vKeyBirth.end(); it++) {
674 const CKeyID &keyid = it->second;
675 std::string strTime = EncodeDumpTime(it->first);
678 if (pwallet->
GetKey(keyid, key)) {
682 }
else if (keyid == seed_id) {
684 }
else if (mapKeyPool.count(keyid)) {
687 file <<
"inactivehdseed=1";
695 file <<
"# End of dump\n";
699 reply.
push_back(Pair(
"filename", filepath.string()));
708 bool success =
false;
711 const UniValue& scriptPubKey = data[
"scriptPubKey"];
719 const std::string& strRedeemScript = data.
exists(
"redeemscript") ? data[
"redeemscript"].
get_str() :
"";
722 const bool&
internal = data.
exists(
"internal") ? data[
"internal"].
get_bool() :
false;
723 const bool& watchOnly = data.
exists(
"watchonly") ? data[
"watchonly"].
get_bool() :
false;
724 const std::string& label = data.
exists(
"label") && !
internal ? data[
"label"].
get_str() :
"";
727 bool isP2SH = strRedeemScript.length() > 0;
728 const std::string& output = isScript ? scriptPubKey.
get_str() : scriptPubKey[
"address"].
get_str();
741 if (!
IsHex(output)) {
745 std::vector<unsigned char> vData(
ParseHex(output));
746 script =
CScript(vData.begin(), vData.end());
750 if (watchOnly && keys.
size()) {
755 if (
internal && data.
exists(
"label")) {
760 if (!
internal && isScript) {
765 if (!isP2SH && (keys.
size() > 1 || pubKeys.
size() > 1)) {
770 if (isP2SH && !
IsHex(strRedeemScript)) {
779 std::vector<unsigned char> vData(
ParseHex(strRedeemScript));
806 if (!pwallet->
AddWatchOnly(redeemDestination, timestamp)) {
817 for (
size_t i = 0; i < keys.
size(); i++) {
818 const std::string& privkey = keys[i].
get_str();
821 bool fGood = vchSecret.
SetString(privkey);
840 if (pwallet->
HaveKey(vchAddress)) {
857 if (pubKeys.
size() && keys.
size() == 0) {
858 const std::string& strPubKey = pubKeys[0].
get_str();
860 if (!
IsHex(strPubKey)) {
864 std::vector<unsigned char> vData(
ParseHex(strPubKey));
865 CPubKey pubKey(vData.begin(), vData.end());
867 if (!pubKey.IsFullyValid()) {
874 if (!isScript && !(pubkey_dest == dest)) {
883 if (!(destination == pubkey_dest)) {
915 if (!pwallet->
AddWatchOnly(scriptRawPubKey, timestamp)) {
924 const std::string& strPrivkey = keys[0].
get_str();
928 bool fGood = vchSecret.
SetString(strPrivkey);
945 if (!isScript && !(pubkey_dest == dest)) {
954 if (!(destination == pubkey_dest)) {
964 if (pwallet->
HaveKey(vchAddress)) {
980 if (pubKeys.
size() == 0 && keys.
size() == 0) {
1008 result.
pushKV(
"error", e);
1020 if (data.
exists(
"timestamp")) {
1021 const UniValue& timestamp = data[
"timestamp"];
1022 if (timestamp.
isNum()) {
1024 }
else if (timestamp.
isStr() && timestamp.
get_str() ==
"now") {
1041 throw std::runtime_error(
1042 "importmulti \"requests\" ( \"options\" )\n\n" 1043 "Import addresses/scripts (with private or public keys, redeem script (P2SH)), rescanning all addresses in one-shot-only (rescan can be disabled via options).\n\n" 1045 "1. requests (array, required) Data to be imported\n" 1046 " [ (array of json objects)\n" 1048 " \"scriptPubKey\": \"<script>\" | { \"address\":\"<address>\" }, (string / json, required) Type of scriptPubKey (string for script, json for address)\n" 1049 " \"timestamp\": timestamp | \"now\" , (integer / string, required) Creation time of the key in seconds since epoch (Jan 1 1970 GMT),\n" 1050 " or the string \"now\" to substitute the current synced blockchain time. The timestamp of the oldest\n" 1051 " key will determine how far back blockchain rescans need to begin for missing wallet transactions.\n" 1052 " \"now\" can be specified to bypass scanning, for keys which are known to never have been used, and\n" 1053 " 0 can be specified to scan the entire blockchain. Blocks up to 2 hours before the earliest key\n" 1054 " creation time of all keys being imported by the importmulti call will be scanned.\n" 1055 " \"redeemscript\": \"<script>\" , (string, optional) Allowed only if the scriptPubKey is a P2SH address or a P2SH scriptPubKey\n" 1056 " \"pubkeys\": [\"<pubKey>\", ... ] , (array, optional) Array of strings giving pubkeys that must occur in the output or redeemscript\n" 1057 " \"keys\": [\"<key>\", ... ] , (array, optional) Array of strings giving private keys whose corresponding public keys must occur in the output or redeemscript\n" 1058 " \"internal\": <true> , (boolean, optional, default: false) Stating whether matching outputs should be treated as not incoming payments\n" 1059 " \"watchonly\": <true> , (boolean, optional, default: false) Stating whether matching outputs should be considered watched even when they're not spendable, only allowed if keys are empty\n" 1060 " \"label\": <label> , (string, optional, default: '') Label to assign to the address (aka account name, for now), only allowed with internal=false\n" 1064 "2. options (json, optional)\n" 1066 " \"rescan\": <false>, (boolean, optional, default: true) Stating if should rescan the blockchain after all imports\n" 1069 HelpExampleCli(
"importmulti",
"'[{ \"scriptPubKey\": { \"address\": \"<my address>\" }, \"timestamp\":1455191478 }, " 1070 "{ \"scriptPubKey\": { \"address\": \"<my 2nd address>\" }, \"label\": \"example 2\", \"timestamp\": 1455191480 }]'") +
1071 HelpExampleCli(
"importmulti",
"'[{ \"scriptPubKey\": { \"address\": \"<my address>\" }, \"timestamp\":1455191478 }]' '{ \"rescan\": false}'") +
1073 "\nResponse is an array with the same size as the input that has the execution result :\n" 1074 " [{ \"success\": true } , { \"success\": false, \"error\": { \"code\": -1, \"message\": \"Internal Server Error\"} }, ... ]\n");
1083 bool fRescan =
true;
1088 if (options.
exists(
"rescan")) {
1089 fRescan = options[
"rescan"].
get_bool();
1102 bool fRunScan =
false;
1103 const int64_t minimumTimestamp = 1;
1104 int64_t nLowestTimestamp = 0;
1124 if (result[
"success"].get_bool()) {
1129 if (timestamp < nLowestTimestamp) {
1130 nLowestTimestamp = timestamp;
1134 if (fRescan && fRunScan && requests.
size()) {
1135 int64_t scannedTime = pwallet->
RescanFromTime(nLowestTimestamp,
true );
1138 if (scannedTime > nLowestTimestamp) {
1139 std::vector<UniValue> results = response.
getValues();
1148 if (scannedTime <=
GetImportTimestamp(request, now) || results.at(i).exists(
"error")) {
1157 strprintf(
"Rescan failed for key with creation timestamp %d. There was an error reading a " 1158 "block from time %d, which is after or within %d seconds of key creation, and " 1159 "could contain transactions pertaining to the key. As a result, transactions " 1160 "and coins using this key may not appear in the wallet. This error could be " 1161 "caused by pruning or data corruption (see ravend log for details) and could " 1162 "be dealt with by downloading and rescanning the relevant blocks (see -reindex " 1163 "and -rescan options).",
1164 GetImportTimestamp(request, now), scannedTime - TIMESTAMP_WINDOW - 1, TIMESTAMP_WINDOW)));
std::string DecodeDumpString(const std::string &str)
UniValue abortrescan(const JSONRPCRequest &request)
void SetKey(const K &key)
boost::variant< CNoDestination, CKeyID, CScriptID > CTxDestination
A txout script template with a specific destination.
bool fPruneMode
True if we're running in -prune mode.
const std::vector< UniValue > & getValues() const
bool ExtractDestination(const CScript &scriptPubKey, CTxDestination &addressRet)
Parse a standard scriptPubKey for the destination address.
bool HaveKey(const CKeyID &address) const override
Check whether a key corresponding to a given address is present in the store.
int64_t GetBlockTime() const
void GetKeyBirthTimes(std::map< CTxDestination, int64_t > &mapKeyBirth) const
const std::map< CKeyID, int64_t > & GetAllReserveKeys() const
UniValue dumpprivkey(const JSONRPCRequest &request)
std::map< CTxDestination, CAddressBookData > mapAddressBook
CCriticalSection cs_wallet
bool IsPayToScriptHash() const
bool VerifyPubKey(const CPubKey &vchPubKey) const
Verify thoroughly whether a private key and a public key match.
UniValue importmulti(const JSONRPCRequest &mainRequest)
CPubKey GetPubKey() const
Compute the public key from a private key.
bool EnsureWalletIsAvailable(CWallet *const pwallet, bool avoidException)
bool HaveCScript(const CScriptID &hash) const override
std::string DateTimeStrFormat(const char *pszFormat, int64_t nTime)
bool AddKeyPubKey(const CKey &key, const CPubKey &pubkey) override
Adds a key to the store, and saves it to disk.
void ReacceptWalletTransactions()
int Height() const
Return the maximal height in the chain.
CCriticalSection cs_main
Global state.
bool IsValidDestination(const CTxDestination &dest)
Check whether a CTxDestination is a CNoDestination.
CTxDestination DecodeDestination(const std::string &str)
std::string HexStr(const T itbegin, const T itend, bool fSpaces=false)
CScript GetScriptForRawPubKey(const CPubKey &pubKey)
Generate a P2PK script for the given pubkey.
UniValue dumpwallet(const JSONRPCRequest &request)
isminetype IsMine(const CKeyStore &keystore, const CScript &scriptPubKey, SigVersion sigversion)
const std::string & get_str() const
enum VType getType() const
std::string HelpExampleRpc(const std::string &methodname, const std::string &args)
const UniValue & get_array() const
Double ended buffer combining vector and stream-like interfaces.
int64_t get_int64() const
std::map< CTxDestination, CKeyMetadata > mapKeyMetadata
const unsigned char * begin() const
CKeyID GetID() const
Get the KeyID of this public key (hash of its serialization)
bool AddWatchOnly(const CScript &dest) override
Private version of AddWatchOnly method which does not accept a timestamp, and which will reset the wa...
void RPCTypeCheck(const UniValue ¶ms, const std::list< UniValue::VType > &typesExpected, bool fAllowNull)
Type-check arguments; throws JSONRPCError if wrong type given.
Invalid, missing or duplicate parameter.
std::string ToString() const
uint256 GetBlockHash() const
bool SetAddressBook(const CTxDestination &address, const std::string &strName, const std::string &purpose)
const char * uvTypeName(UniValue::VType t)
Used to relay blocks as header + vector<merkle branch> to filtered nodes.
bool push_back(const UniValue &val)
bool AddCScript(const CScript &redeemScript) override
Support for BIP 0013 : see https://github.com/raven/bips/blob/master/bip-0013.mediawiki.
bool DecodeHexTx(CMutableTransaction &tx, const std::string &strHexTx, bool fTryNoWitness=false)
bool exists(const std::string &key) const
void ImportScript(CWallet *const pwallet, const CScript &script, const std::string &strLabel, bool isRedeemScript)
bool Contains(const CBlockIndex *pindex) const
Efficiently check whether a block is present in this chain.
UniValue removeprunedfunds(const JSONRPCRequest &request)
An encapsulated public key.
bool SetString(const char *pszSecret)
bool IsHex(const std::string &str)
Unexpected type was passed as parameter.
void UpdateTimeFirstKey(int64_t nCreateTime)
Update wallet first key creation time.
General application defined errors.
bool pushKV(const std::string &key, const UniValue &val)
UniValue ProcessImport(CWallet *const pwallet, const UniValue &data, const int64_t timestamp)
bool GetKey(const CKeyID &address, CKey &keyOut) const override
DBErrors ZapSelectTx(std::vector< uint256 > &vHashIn, std::vector< uint256 > &vHashOut)
unsigned int size() const
Simple read-only vector-like interface.
CChain chainActive
The currently-connected chain of blocks (protected by cs_main).
std::string ToString() const
CScript GetScriptForDestination(const CTxDestination &dest)
Generate a Raven scriptPubKey for the given CTxDestination.
std::string HelpExampleCli(const std::string &methodname, const std::string &args)
void SetSeed(const unsigned char *seed, unsigned int nSeedLen)
bool AddToWallet(const CWalletTx &wtxIn, bool fFlushOnClose=true)
int64_t GetMedianTimePast() const
A transaction with a bunch of additional info that only the owner cares about.
std::vector< unsigned char > ParseHexV(const UniValue &v, std::string strName)
int64_t RescanFromTime(int64_t startTime, bool update)
Scan active chain for relevant transactions after importing keys.
int64_t GetImportTimestamp(const UniValue &data, int64_t now)
uint256 GetHash() const
Compute the hash of this CMutableTransaction.
std::string EncodeDestination(const CTxDestination &dest)
A base58-encoded secret key.
Serialized script, used inside transaction inputs and outputs.
UniValue importpubkey(const JSONRPCRequest &request)
A reference to a CKey: the Hash160 of its serialized public key.
CBlockIndex * Tip() const
Returns the index entry for the tip of this chain, or nullptr if none.
A CWallet is an extension of a keystore, which also maintains a set of transactions and balances...
const UniValue NullUniValue
CWallet * GetWalletForJSONRPCRequest(const JSONRPCRequest &request)
Figures out what wallet, if any, to use for a JSONRPCRequest.
UniValue importprivkey(const JSONRPCRequest &request)
UniValue importwallet(const JSONRPCRequest &request)
boost::signals2::signal< void(const std::string &title, int nProgress)> ShowProgress
Show progress e.g.
A reference to a CScript: the Hash160 of its serialization (see script.h)
UniValue importaddress(const JSONRPCRequest &request)
A mutable version of CTransaction.
void ImportAddress(CWallet *, const CTxDestination &dest, const std::string &strLabel)
UniValue JSONRPCError(int code, const std::string &message)
int64_t GetTime()
GetTimeMicros() and GetTimeMillis() both return the system time, but in different units...
An encapsulated private key.
bool HaveWatchOnly(const CScript &dest) const override
isminetype IsMine(const CTxIn &txin) const
const CHDChain & GetHDChain() const
CKeyID seed_id
seed hash160
void SetHex(const char *psz)
const std::string CLIENT_BUILD
UniValue importprunedfunds(const JSONRPCRequest &request)
std::string _(const char *psz)
Translation function: Call Translate signal on UI interface, which returns a boost::optional result...
Error parsing or validating structure in raw format.
bool IsValid() const
Check whether this private key is valid.
void EnsureWalletIsUnlocked(CWallet *const pwallet)
std::vector< unsigned char > ParseHex(const char *psz)