bool CMasternodeBroadcast::Create(const COutPoint& outpoint, const CService& service, const CKey& keyCollateralAddressNew, const CPubKey& pubKeyCollateralAddressNew, const CKey& keyMasternodeNew, const CPubKey& pubKeyMasternodeNew, std::string& strErrorRet, CMasternodeBroadcast& mnbRet) { // wait for reindex and/or import to finish if (fImporting || fReindex) return false; LogPrint(MCLog::MN, "CMasternodeBroadcast::Create -- pubKeyCollateralAddressNew = %s, pubKeyMasternodeNew.GetID() = %s\n", EncodeDestination(CScriptID(GetScriptForDestination(WitnessV0KeyHash(pubKeyCollateralAddressNew.GetID())))), EncodeDestination(CScriptID(GetScriptForDestination(WitnessV0KeyHash(pubKeyMasternodeNew.GetID()))))); auto Log = [&strErrorRet, &mnbRet](std::string sErr) -> bool { strErrorRet = sErr; mnbRet = CMasternodeBroadcast(); return false; }; CMasternodePing mnp(outpoint); if (!mnp.Sign(keyMasternodeNew, pubKeyMasternodeNew)) return Log(strprintf("Failed to sign ping, masternode=%s", outpoint.ToStringShort())); mnbRet = CMasternodeBroadcast(service, outpoint, pubKeyCollateralAddressNew, pubKeyMasternodeNew, PROTOCOL_VERSION); if (!mnbRet.IsValidNetAddr()) return Log(strprintf("Invalid IP address, masternode=%s", outpoint.ToStringShort())); mnbRet.lastPing = mnp; if (!mnbRet.Sign(keyCollateralAddressNew)) return Log(strprintf("Failed to sign broadcast, masternode=%s", outpoint.ToStringShort())); return true; }
void Bip38ToolDialog::on_importAddressButton_DEC_clicked() { WalletModel::UnlockContext ctx(model->requestUnlock(true)); if (!ctx.isValid()) { ui->statusLabel_DEC->setStyleSheet("QLabel { color: red; }"); ui->statusLabel_DEC->setText(tr("Wallet unlock was cancelled.")); return; } CPubKey pubkey = key.GetPubKey(); if (!IsValidDestinationString(ui->addressOut_DEC->text().toStdString())) { ui->statusLabel_DEC->setStyleSheet("QLabel { color: red; }"); ui->statusLabel_DEC->setText(tr("Data Not Valid.") + QString(" ") + tr("Please try again.")); return; } CTxDestination address = DecodeDestination(ui->addressOut_DEC->text().toStdString()); if (!key.IsValid() || EncodeDestination(pubkey.GetID()) != EncodeDestination(address)) { CKeyID vchAddress = pubkey.GetID(); ui->statusLabel_DEC->setStyleSheet("QLabel { color: red; }"); ui->statusLabel_DEC->setText(tr("Please wait while key is imported")); pwalletMain->MarkDirty(); pwalletMain->SetAddressBook(vchAddress, "", "receive"); // Don't throw error in case a key is already there if (pwalletMain->HaveKey(vchAddress)) { ui->statusLabel_DEC->setStyleSheet("QLabel { color: red; }"); ui->statusLabel_DEC->setText(tr("Key Already Held By Wallet")); return; } pwalletMain->mapKeyMetadata[vchAddress].nCreateTime = 1; if (!pwalletMain->AddKeyPubKey(key, pubkey)) { ui->statusLabel_DEC->setStyleSheet("QLabel { color: red; }"); ui->statusLabel_DEC->setText(tr("Error Adding Key To Wallet")); return; } // whenever a key is imported, we need to scan the whole chain pwalletMain->nTimeFirstKey = 1; // 0 would be considered 'no value' pwalletMain->ScanForWalletTransactions(chainActive.Genesis(), true); } ui->statusLabel_DEC->setStyleSheet("QLabel { color: green; }"); ui->statusLabel_DEC->setText(tr("Successfully Added Private Key To Wallet")); }
static std::string ScriptToString(const CScript& script, bool l = false, bool highlight = false) { if (script.empty()) return "unknown"; CTxDestination dest; if (ExtractDestination(script, dest)) { if (highlight) return "<span class=\"addr\">" + EncodeDestination(dest) + "</span>"; else return makeHRef(EncodeDestination(dest)); } else return l ? "<pre>" + FormatScript(script) + "</pre>" : _("Non-standard script"); }
void ScriptPubKeyToUniv(const CScript& scriptPubKey, UniValue& out, bool fIncludeHex) { txnouttype type; std::vector<CTxDestination> addresses; int nRequired; out.pushKV("asm", ScriptToAsmStr(scriptPubKey)); if (fIncludeHex) out.pushKV("hex", HexStr(scriptPubKey.begin(), scriptPubKey.end())); if (!ExtractDestinations(scriptPubKey, type, addresses, nRequired)) { out.pushKV("type", GetTxnOutputType(type)); return; } out.pushKV("reqSigs", nRequired); out.pushKV("type", GetTxnOutputType(type)); UniValue a(UniValue::VARR); for (const CTxDestination& addr : addresses) { a.push_back(EncodeDestination(addr)); } out.pushKV("addresses", a); }
QString AddressTableModel::addRow(const QString &type, const QString &label, const QString &address, const OutputType address_type) { std::string strLabel = label.toStdString(); std::string strAddress = address.toStdString(); editStatus = OK; if(type == Send) { if(!walletModel->validateAddress(address)) { editStatus = INVALID_ADDRESS; return QString(); } // Check for duplicate addresses { LOCK(wallet->cs_wallet); if(wallet->mapAddressBook.count(DecodeDestination(strAddress))) { editStatus = DUPLICATE_ADDRESS; return QString(); } } } else if(type == Receive) { // Generate a new address to associate with given label CPubKey newKey; if(!wallet->GetKeyFromPool(newKey)) { WalletModel::UnlockContext ctx(walletModel->requestUnlock()); if(!ctx.isValid()) { // Unlock wallet failed or was cancelled editStatus = WALLET_UNLOCK_FAILURE; return QString(); } if(!wallet->GetKeyFromPool(newKey)) { editStatus = KEY_GENERATION_FAILURE; return QString(); } } wallet->LearnRelatedScripts(newKey, address_type); strAddress = EncodeDestination(GetDestinationForKey(newKey, address_type)); } else { return QString(); } // Add entry { LOCK(wallet->cs_wallet); wallet->SetAddressBook(DecodeDestination(strAddress), strLabel, (type == Send ? "send" : "receive")); } return QString::fromStdString(strAddress); }
QString AddressTableModel::addRow(const QString &type, const QString &label, const QString &address, const OutputType address_type) { std::string strLabel = label.toStdString(); std::string strAddress = address.toStdString(); editStatus = OK; if(type == Send) { if(!walletModel->validateAddress(address)) { editStatus = INVALID_ADDRESS; return QString(); } // Check for duplicate addresses { if (walletModel->wallet().getAddress( DecodeDestination(strAddress), /* name= */ nullptr, /* is_mine= */ nullptr, /* purpose= */ nullptr)) { editStatus = DUPLICATE_ADDRESS; return QString(); } } } else if(type == Receive) { // Generate a new address to associate with given label CPubKey newKey; if(!walletModel->wallet().getKeyFromPool(false /* internal */, newKey)) { WalletModel::UnlockContext ctx(walletModel->requestUnlock()); if(!ctx.isValid()) { // Unlock wallet failed or was cancelled editStatus = WALLET_UNLOCK_FAILURE; return QString(); } if(!walletModel->wallet().getKeyFromPool(false /* internal */, newKey)) { editStatus = KEY_GENERATION_FAILURE; return QString(); } } walletModel->wallet().learnRelatedScripts(newKey, address_type); CPubKey blinding_pubkey = walletModel->wallet().getBlindingPubKey(GetScriptForDestination(GetDestinationForKey(newKey, address_type))); strAddress = EncodeDestination(GetDestinationForKey(newKey, address_type, blinding_pubkey)); } else { return QString(); } // Add entry walletModel->wallet().setAddressBook(DecodeDestination(strAddress), strLabel, (type == Send ? "send" : "receive")); return QString::fromStdString(strAddress); }
UniValue createmultisig(const JSONRPCRequest& request) { if (request.fHelp || request.params.size() < 2 || request.params.size() > 2) { std::string msg = "createmultisig nrequired [\"key\",...]\n" "\nCreates a multi-signature address with n signature of m keys required.\n" "It returns a json object with the address and redeemScript.\n" "\nArguments:\n" "1. nrequired (numeric, required) The number of required signatures out of the n keys.\n" "2. \"keys\" (string, required) A json array of hex-encoded public keys\n" " [\n" " \"key\" (string) The hex-encoded public key\n" " ,...\n" " ]\n" "\nResult:\n" "{\n" " \"address\":\"multisigaddress\", (string) The value of the new multisig address.\n" " \"redeemScript\":\"script\" (string) The string value of the hex-encoded redemption script.\n" "}\n" "\nExamples:\n" "\nCreate a multisig address from 2 public keys\n" + HelpExampleCli("createmultisig", "2 \"[\\\"03789ed0bb717d88f7d321a368d905e7430207ebbd82bd342cf11ae157a7ace5fd\\\",\\\"03dbc6764b8884a92e871274b87583e6d5c2a58819473e17e107ef3f6aa5a61626\\\"]\"") + "\nAs a json rpc call\n" + HelpExampleRpc("createmultisig", "2, \"[\\\"03789ed0bb717d88f7d321a368d905e7430207ebbd82bd342cf11ae157a7ace5fd\\\",\\\"03dbc6764b8884a92e871274b87583e6d5c2a58819473e17e107ef3f6aa5a61626\\\"]\"") ; throw std::runtime_error(msg); } int required = request.params[0].get_int(); // Get the public keys const UniValue& keys = request.params[1].get_array(); std::vector<CPubKey> pubkeys; for (unsigned int i = 0; i < keys.size(); ++i) { if (IsHex(keys[i].get_str()) && (keys[i].get_str().length() == 66 || keys[i].get_str().length() == 130)) { pubkeys.push_back(HexToPubKey(keys[i].get_str())); } else { throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("Invalid public key: %s\nNote that from v0.16, createmultisig no longer accepts addresses." " Users must use addmultisigaddress to create multisig addresses with addresses known to the wallet.", keys[i].get_str())); } } // Construct using pay-to-script-hash: CScript inner = CreateMultisigRedeemscript(required, pubkeys); CScriptID innerID(inner); UniValue result(UniValue::VOBJ); result.pushKV("address", EncodeDestination(innerID)); result.pushKV("redeemScript", HexStr(inner.begin(), inner.end())); return result; }
UniValue validateaddress(const JSONRPCRequest& request) { if (request.fHelp || request.params.size() != 1) throw std::runtime_error( "validateaddress \"address\"\n" "\nReturn information about the given bitcoin address.\n" "DEPRECATION WARNING: Parts of this command have been deprecated and moved to getaddressinfo. Clients must\n" "transition to using getaddressinfo to access this information before upgrading to v0.18. The following deprecated\n" "fields have moved to getaddressinfo and will only be shown here with -deprecatedrpc=validateaddress: ismine, iswatchonly,\n" "script, hex, pubkeys, sigsrequired, pubkey, addresses, embedded, iscompressed, account, timestamp, hdkeypath, kdmasterkeyid.\n" "\nArguments:\n" "1. \"address\" (string, required) The bitcoin address to validate\n" "\nResult:\n" "{\n" " \"isvalid\" : true|false, (boolean) If the address is valid or not. If not, this is the only property returned.\n" " \"address\" : \"address\", (string) The bitcoin address validated\n" " \"scriptPubKey\" : \"hex\", (string) The hex encoded scriptPubKey generated by the address\n" " \"isscript\" : true|false, (boolean) If the key is a script\n" " \"iswitness\" : true|false, (boolean) If the address is a witness address\n" " \"witness_version\" : version (numeric, optional) The version number of the witness program\n" " \"witness_program\" : \"hex\" (string, optional) The hex value of the witness program\n" "}\n" "\nExamples:\n" + HelpExampleCli("validateaddress", "\"1PSSGeFHDnKNxiEyFrD1wcEaHr9hrQDDWc\"") + HelpExampleRpc("validateaddress", "\"1PSSGeFHDnKNxiEyFrD1wcEaHr9hrQDDWc\"") ); CTxDestination dest = DecodeDestination(request.params[0].get_str()); bool isValid = IsValidDestination(dest); UniValue ret(UniValue::VOBJ); ret.pushKV("isvalid", isValid); if (isValid) { #ifdef ENABLE_WALLET if (HasWallets() && IsDeprecatedRPCEnabled("validateaddress")) { ret.pushKVs(getaddressinfo(request)); } #endif if (ret["address"].isNull()) { std::string currentAddress = EncodeDestination(dest); ret.pushKV("address", currentAddress); CScript scriptPubKey = GetScriptForDestination(dest); ret.pushKV("scriptPubKey", HexStr(scriptPubKey.begin(), scriptPubKey.end()));; UniValue detail = DescribeAddress(dest); ret.pushKVs(detail); } } return ret; }
std::string AddressToString(const CTxDestination& dest) { std::string txLabels[] = { _("Date"), _("Hash"), _("From"), _("Amount"), _("To"), _("Amount"), _("Delta"), _("Balance")}; std::string txContent = table + makeHTMLTableRow(txLabels, sizeof(txLabels) / sizeof(std::string)); std::set<COutPoint> prevOuts; /* CScript AddressScript; AddressScript.SetDestination(Address.Get()); CAmount Sum = 0; bool fAddrIndex = false; if (!fAddrIndex) return ""; // it will take too long to find transactions by address else { std::vector<CDiskTxPos> Txs; paddressmap->GetTxs(Txs, AddressScript.GetID()); BOOST_FOREACH (const CDiskTxPos& pos, Txs) { CTransaction tx; CBlock block; uint256 bhash = block.GetHash(); GetTransaction(pos.nTxOffset, tx, bhash); std::map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(block.GetHash()); if (mi == mapBlockIndex.end()) continue; CBlockIndex* pindex = (*mi).second; if (!pindex || !chainActive.Contains(pindex)) continue; std::string Prepend = "<a href=\"" + itostr(pindex->nHeight) + "\">" + TimeToString(pindex->nTime) + "</a>"; TxContent += TxToRow(tx, AddressScript, Prepend, &Sum); } } */ txContent += "</table>"; std::string content; content += "<h1>" + _("Transactions to/from") + " <span>" + EncodeDestination(dest) + "</span></h1>"; content += txContent; return content; }
void ScriptToUniv(const CScript& script, UniValue& out, bool include_address) { out.pushKV("asm", ScriptToAsmStr(script)); out.pushKV("hex", HexStr(script.begin(), script.end())); std::vector<std::vector<unsigned char>> solns; txnouttype type; Solver(script, type, solns); out.pushKV("type", GetTxnOutputType(type)); CTxDestination address; if (include_address && ExtractDestination(script, address)) { out.pushKV("address", EncodeDestination(address)); } }
UniValue decodescript(const JSONRPCRequest& request) { if (request.fHelp || request.params.size() != 1) throw std::runtime_error( "decodescript \"hexstring\"\n" "\nDecode a hex-encoded script.\n" "\nArguments:\n" "1. \"hexstring\" (string) the hex encoded script\n" "\nResult:\n" "{\n" " \"asm\":\"asm\", (string) Script public key\n" " \"hex\":\"hex\", (string) hex encoded public key\n" " \"type\":\"type\", (string) The output type\n" " \"reqSigs\": n, (numeric) The required signatures\n" " \"addresses\": [ (json array of string)\n" " \"address\" (string) bitcoin address\n" " ,...\n" " ],\n" " \"p2sh\",\"address\" (string) address of P2SH script wrapping this redeem script (not returned if the script is already a P2SH).\n" "}\n" "\nExamples:\n" + HelpExampleCli("decodescript", "\"hexstring\"") + HelpExampleRpc("decodescript", "\"hexstring\"") ); RPCTypeCheck(request.params, {UniValue::VSTR}); UniValue r(UniValue::VOBJ); CScript script; if (request.params[0].get_str().size() > 0){ std::vector<unsigned char> scriptData(ParseHexV(request.params[0], "argument")); script = CScript(scriptData.begin(), scriptData.end()); } else { // Empty scripts are valid } ScriptPubKeyToUniv(script, r, false); UniValue type; type = find_value(r, "type"); if (type.isStr() && type.get_str() != "scripthash") { // P2SH cannot be wrapped in a P2SH. If this script is already a P2SH, // don't return the address for a P2SH of the P2SH. r.push_back(Pair("p2sh", EncodeDestination(CScriptID(script)))); } return r; }
static void NotifyAddressBookChanged(WalletModel *walletmodel, const CTxDestination &address, const std::string &label, bool isMine, const std::string &purpose, ChangeType status) { QString strAddress = QString::fromStdString(EncodeDestination(address)); QString strLabel = QString::fromStdString(label); QString strPurpose = QString::fromStdString(purpose); qDebug() << "NotifyAddressBookChanged: " + strAddress + " " + strLabel + " isMine=" + QString::number(isMine) + " purpose=" + strPurpose + " status=" + QString::number(status); QMetaObject::invokeMethod(walletmodel, "updateAddressBook", Qt::QueuedConnection, Q_ARG(QString, strAddress), Q_ARG(QString, strLabel), Q_ARG(bool, isMine), Q_ARG(QString, strPurpose), Q_ARG(int, status)); }
UniValue createmultisig(const JSONRPCRequest& request) { #ifdef ENABLE_WALLET CWallet * const pwallet = GetWalletForJSONRPCRequest(request); #else CWallet * const pwallet = nullptr; #endif if (request.fHelp || request.params.size() < 2 || request.params.size() > 2) { std::string msg = "createmultisig nrequired [\"key\",...]\n" "\nCreates a multi-signature address with n signature of m keys required.\n" "It returns a json object with the address and redeemScript.\n" "\nArguments:\n" "1. nrequired (numeric, required) The number of required signatures out of the n keys or addresses.\n" "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" "\nResult:\n" "{\n" " \"address\":\"multisigaddress\", (string) The value of the new multisig address.\n" " \"redeemScript\":\"script\" (string) The string value of the hex-encoded redemption script.\n" "}\n" "\nExamples:\n" "\nCreate a multisig address from 2 addresses\n" + HelpExampleCli("createmultisig", "2 \"[\\\"16sSauSf5pF2UkUwvKGq4qjNRzBZYqgEL5\\\",\\\"171sgjn4YtPu27adkKGrdDwzRTxnRkBfKV\\\"]\"") + "\nAs a json rpc call\n" + HelpExampleRpc("createmultisig", "2, \"[\\\"16sSauSf5pF2UkUwvKGq4qjNRzBZYqgEL5\\\",\\\"171sgjn4YtPu27adkKGrdDwzRTxnRkBfKV\\\"]\"") ; throw std::runtime_error(msg); } // Construct using pay-to-script-hash: CScript inner = _createmultisig_redeemScript(pwallet, request.params); CScriptID innerID(inner); UniValue result(UniValue::VOBJ); result.push_back(Pair("address", EncodeDestination(innerID))); result.push_back(Pair("redeemScript", HexStr(inner.begin(), inner.end()))); return result; }
void Bip38ToolDialog::on_encryptKeyButton_ENC_clicked() { if (!model) return; QString qstrPassTNXase = ui->passTNXaseIn_ENC->text(); QString strInvalid; if (!isValidPassTNXase(qstrPassTNXase, strInvalid)) { ui->statusLabel_ENC->setStyleSheet("QLabel { color: red; }"); ui->statusLabel_ENC->setText(tr("The entered passTNXase is invalid. ") + strInvalid + QString(" is not valid") + QString(" ") + tr("Allowed: 0-9,a-z,A-Z,") + specialChar); return; } if (!IsValidDestinationString(ui->addressIn_ENC->text().toStdString())) { ui->statusLabel_ENC->setStyleSheet("QLabel { color: red; }"); ui->statusLabel_ENC->setText(tr("The entered address is invalid.") + QString(" ") + tr("Please check the address and try again.")); return; } CTxDestination addr = DecodeDestination(ui->addressIn_ENC->text().toStdString()); CKeyID keyID = GetKeyForDestination(*pwalletMain, addr); if (keyID.IsNull()) { ui->addressIn_ENC->setValid(false); ui->statusLabel_ENC->setStyleSheet("QLabel { color: red; }"); ui->statusLabel_ENC->setText(tr("The entered address does not refer to a key.") + QString(" ") + tr("Please check the address and try again.")); return; } WalletModel::UnlockContext ctx(model->requestUnlock(true)); if (!ctx.isValid()) { ui->statusLabel_ENC->setStyleSheet("QLabel { color: red; }"); ui->statusLabel_ENC->setText(tr("Wallet unlock was cancelled.")); return; } CKey key; if (!pwalletMain->GetKey(keyID, key)) { ui->statusLabel_ENC->setStyleSheet("QLabel { color: red; }"); ui->statusLabel_ENC->setText(tr("Private key for the entered address is not available.")); return; } std::string encryptedKey = BIP38_Encrypt(EncodeDestination(addr), qstrPassTNXase.toStdString(), key.GetPrivKey_256(), key.IsCompressed()); ui->encryptedKeyOut_ENC->setText(QString::fromStdString(encryptedKey)); }
bool BlockExplorer::switchTo(const QString& query) { bool IsOk; int64_t AsInt = query.toInt(&IsOk); // If query is integer, get hash from height if (IsOk && AsInt >= 0 && AsInt <= chainActive.Tip()->nHeight) { std::string hex = getexplorerBlockHash(AsInt); uint256 hash = uint256S(hex); CBlockIndex* pIndex = mapBlockIndex[hash]; if (pIndex) { setBlock(pIndex); return true; } } // If the query is not an integer, assume it is a block hash uint256 hash = uint256S(query.toUtf8().constData()); // std::map<uint256, CBlockIndex*>::iterator iter = mapBlockIndex.find(hash); BlockMap::iterator iter = mapBlockIndex.find(hash); if (iter != mapBlockIndex.end()) { setBlock(iter->second); return true; } // If the query is neither an integer nor a block hash, assume a transaction hash CTransaction tx; uint256 hashBlock = 0; if (GetTransaction(hash, tx, hashBlock, true)) { setContent(TxToString(hashBlock, tx)); return true; } // If the query is not an integer, nor a block hash, nor a transaction hash, assume an address if (IsValidDestinationString(query.toUtf8().constData())) { CTxDestination dest = DecodeDestination(query.toUtf8().constData()); std::string content = EncodeDestination(dest); if (content.empty()) return false; setContent(content); return true; } return false; }
void refreshAddressTable(interfaces::Wallet& wallet) { cachedAddressTable.clear(); { for (const auto& address : wallet.getAddresses()) { AddressTableEntry::Type addressType = translateTransactionType( QString::fromStdString(address.purpose), address.is_mine); cachedAddressTable.append(AddressTableEntry(addressType, QString::fromStdString(address.name), QString::fromStdString(EncodeDestination(address.dest)))); } } // qLowerBound() and qUpperBound() require our cachedAddressTable list to be sorted in asc order // Even though the map is already sorted this re-sorting step is needed because the originating map // is sorted by binary address, not by base58() address. qSort(cachedAddressTable.begin(), cachedAddressTable.end(), AddressTableEntryLessThan()); }
static UniValue validateaddress(const JSONRPCRequest& request) { if (request.fHelp || request.params.size() != 1) throw std::runtime_error( RPCHelpMan{"validateaddress", "\nReturn information about the given bitcoin address.\n", { {"address", RPCArg::Type::STR, RPCArg::Optional::NO, "The bitcoin address to validate"}, }, RPCResult{ "{\n" " \"isvalid\" : true|false, (boolean) If the address is valid or not. If not, this is the only property returned.\n" " \"address\" : \"address\", (string) The bitcoin address validated\n" " \"scriptPubKey\" : \"hex\", (string) The hex-encoded scriptPubKey generated by the address\n" " \"isscript\" : true|false, (boolean) If the key is a script\n" " \"iswitness\" : true|false, (boolean) If the address is a witness address\n" " \"witness_version\" : version (numeric, optional) The version number of the witness program\n" " \"witness_program\" : \"hex\" (string, optional) The hex value of the witness program\n" "}\n" }, RPCExamples{ HelpExampleCli("validateaddress", "\"1PSSGeFHDnKNxiEyFrD1wcEaHr9hrQDDWc\"") + HelpExampleRpc("validateaddress", "\"1PSSGeFHDnKNxiEyFrD1wcEaHr9hrQDDWc\"") }, }.ToString()); CTxDestination dest = DecodeDestination(request.params[0].get_str()); bool isValid = IsValidDestination(dest); UniValue ret(UniValue::VOBJ); ret.pushKV("isvalid", isValid); if (isValid) { std::string currentAddress = EncodeDestination(dest); ret.pushKV("address", currentAddress); CScript scriptPubKey = GetScriptForDestination(dest); ret.pushKV("scriptPubKey", HexStr(scriptPubKey.begin(), scriptPubKey.end())); UniValue detail = DescribeAddress(dest); ret.pushKVs(detail); } return ret; }
void Bip38ToolDialog::on_decryptKeyButton_DEC_clicked() { string strPassTNXase = ui->passTNXaseIn_DEC->text().toStdString(); string strKey = ui->encryptedKeyIn_DEC->text().toStdString(); uint256 privKey; bool fCompressed; if (!BIP38_Decrypt(strPassTNXase, strKey, privKey, fCompressed)) { ui->statusLabel_DEC->setStyleSheet("QLabel { color: red; }"); ui->statusLabel_DEC->setText(tr("Failed to decrypt.") + QString(" ") + tr("Please check the key and passTNXase and try again.")); return; } key.Set(privKey.begin(), privKey.end(), fCompressed); CPubKey pubKey = key.GetPubKey(); CTxDestination address(pubKey.GetID()); ui->decryptedKeyOut_DEC->setText(QString::fromStdString(CBitcoinSecret(key).ToString())); ui->addressOut_DEC->setText(QString::fromStdString(EncodeDestination(address))); }
void refreshAddressTable() { cachedAddressTable.clear(); { LOCK(wallet->cs_wallet); for (const std::pair<CTxDestination, CAddressBookData>& item : wallet->mapAddressBook) { const CTxDestination& address = item.first; bool fMine = IsMine(*wallet, address); AddressTableEntry::Type addressType = translateTransactionType( QString::fromStdString(item.second.purpose), fMine); const std::string& strName = item.second.name; cachedAddressTable.append(AddressTableEntry(addressType, QString::fromStdString(strName), QString::fromStdString(EncodeDestination(address)))); } } // qLowerBound() and qUpperBound() require our cachedAddressTable list to be sorted in asc order // Even though the map is already sorted this re-sorting step is needed because the originating map // is sorted by binary address, not by base58() address. qSort(cachedAddressTable.begin(), cachedAddressTable.end(), AddressTableEntryLessThan()); }
UniValue operator()(const CScriptID &scriptID) const { UniValue obj(UniValue::VOBJ); CScript subscript; obj.push_back(Pair("isscript", true)); obj.push_back(Pair("iswitness", false)); if (pwallet && pwallet->GetCScript(scriptID, subscript)) { std::vector<CTxDestination> addresses; txnouttype whichType; int nRequired; ExtractDestinations(subscript, whichType, addresses, nRequired); obj.push_back(Pair("script", GetTxnOutputType(whichType))); obj.push_back(Pair("hex", HexStr(subscript.begin(), subscript.end()))); UniValue a(UniValue::VARR); for (const CTxDestination& addr : addresses) { a.push_back(EncodeDestination(addr)); } obj.push_back(Pair("addresses", a)); if (whichType == TX_MULTISIG) obj.push_back(Pair("sigsrequired", nRequired)); } return obj; }
bool PaymentServer::processPaymentRequest(const PaymentRequestPlus& request, SendCoinsRecipient& recipient) { if (!optionsModel) return false; if (request.IsInitialized()) { // Payment request network matches client network? if (!verifyNetwork(request.getDetails())) { Q_EMIT message(tr("Payment request rejected"), tr("Payment request network doesn't match client network."), CClientUIInterface::MSG_ERROR); return false; } // Make sure any payment requests involved are still valid. // This is re-checked just before sending coins in WalletModel::sendCoins(). if (verifyExpired(request.getDetails())) { Q_EMIT message(tr("Payment request rejected"), tr("Payment request expired."), CClientUIInterface::MSG_ERROR); return false; } } else { Q_EMIT message(tr("Payment request error"), tr("Payment request is not initialized."), CClientUIInterface::MSG_ERROR); return false; } recipient.paymentRequest = request; recipient.message = GUIUtil::HtmlEscape(request.getDetails().memo()); request.getMerchant(certStore.get(), recipient.authenticatedMerchant); QList<std::pair<CScript, CAmount> > sendingTos = request.getPayTo(); QStringList addresses; for (const std::pair<CScript, CAmount>& sendingTo : sendingTos) { // Extract and check destination addresses CTxDestination dest; if (ExtractDestination(sendingTo.first, dest)) { // Append destination address addresses.append(QString::fromStdString(EncodeDestination(dest))); } else if (!recipient.authenticatedMerchant.isEmpty()) { // Unauthenticated payment requests to custom bitcoin addresses are not supported // (there is no good way to tell the user where they are paying in a way they'd // have a chance of understanding). Q_EMIT message(tr("Payment request rejected"), tr("Unverified payment requests to custom payment scripts are unsupported."), CClientUIInterface::MSG_ERROR); return false; } // Bitcoin amounts are stored as (optional) uint64 in the protobuf messages (see paymentrequest.proto), // but CAmount is defined as int64_t. Because of that we need to verify that amounts are in a valid range // and no overflow has happened. if (!verifyAmount(sendingTo.second)) { Q_EMIT message(tr("Payment request rejected"), tr("Invalid payment request."), CClientUIInterface::MSG_ERROR); return false; } // Extract and check amounts CTxOut txOut(sendingTo.second, sendingTo.first); if (IsDust(txOut, ::dustRelayFee)) { Q_EMIT message(tr("Payment request error"), tr("Requested payment amount of %1 is too small (considered dust).") .arg(BitcoinUnits::formatWithUnit(optionsModel->getDisplayUnit(), sendingTo.second)), CClientUIInterface::MSG_ERROR); return false; } recipient.amount += sendingTo.second; // Also verify that the final amount is still in a valid range after adding additional amounts. if (!verifyAmount(recipient.amount)) { Q_EMIT message(tr("Payment request rejected"), tr("Invalid payment request."), CClientUIInterface::MSG_ERROR); return false; } } // Store addresses and format them to fit nicely into the GUI recipient.address = addresses.join("<br />"); if (!recipient.authenticatedMerchant.isEmpty()) { qDebug() << "PaymentServer::processPaymentRequest: Secure payment request from " << recipient.authenticatedMerchant; } else { qDebug() << "PaymentServer::processPaymentRequest: Insecure payment request to " << addresses.join(", "); } return true; }
UniValue deriveaddresses(const JSONRPCRequest& request) { if (request.fHelp || request.params.empty() || request.params.size() > 2) { throw std::runtime_error( RPCHelpMan{"deriveaddresses", {"\nDerives one or more addresses corresponding to an output descriptor.\n" "Examples of output descriptors are:\n" " pkh(<pubkey>) P2PKH outputs for the given pubkey\n" " wpkh(<pubkey>) Native segwit P2PKH outputs for the given pubkey\n" " sh(multi(<n>,<pubkey>,<pubkey>,...)) P2SH-multisig outputs for the given threshold and pubkeys\n" " raw(<hex script>) Outputs whose scriptPubKey equals the specified hex scripts\n" "\nIn the above, <pubkey> either refers to a fixed public key in hexadecimal notation, or to an xpub/xprv optionally followed by one\n" "or more path elements separated by \"/\", where \"h\" represents a hardened child key.\n" "For more information on output descriptors, see the documentation in the doc/descriptors.md file.\n"}, { {"descriptor", RPCArg::Type::STR, RPCArg::Optional::NO, "The descriptor."}, {"range", RPCArg::Type::RANGE, RPCArg::Optional::OMITTED_NAMED_ARG, "If a ranged descriptor is used, this specifies the end or the range (in [begin,end] notation) to derive."}, }, RPCResult{ "[ address ] (array) the derived addresses\n" }, RPCExamples{ "First three native segwit receive addresses\n" + HelpExampleCli("deriveaddresses", "\"wpkh([d34db33f/84h/0h/0h]xpub6DJ2dNUysrn5Vt36jH2KLBT2i1auw1tTSSomg8PhqNiUtx8QX2SvC9nrHu81fT41fvDUnhMjEzQgXnQjKEu3oaqMSzhSrHMxyyoEAmUHQbY/0/*)#trd0mf0l\" \"[0,2]\"") }}.ToString() ); } RPCTypeCheck(request.params, {UniValue::VSTR, UniValueType()}); // Range argument is checked later const std::string desc_str = request.params[0].get_str(); int64_t range_begin = 0; int64_t range_end = 0; if (request.params.size() >= 2 && !request.params[1].isNull()) { std::tie(range_begin, range_end) = ParseDescriptorRange(request.params[1]); } FlatSigningProvider key_provider; auto desc = Parse(desc_str, key_provider, /* require_checksum = */ true); if (!desc) { throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("Invalid descriptor")); } if (!desc->IsRange() && request.params.size() > 1) { throw JSONRPCError(RPC_INVALID_PARAMETER, "Range should not be specified for an un-ranged descriptor"); } if (desc->IsRange() && request.params.size() == 1) { throw JSONRPCError(RPC_INVALID_PARAMETER, "Range must be specified for a ranged descriptor"); } UniValue addresses(UniValue::VARR); for (int i = range_begin; i <= range_end; ++i) { FlatSigningProvider provider; std::vector<CScript> scripts; if (!desc->Expand(i, key_provider, scripts, provider)) { throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("Cannot derive script without private keys")); } for (const CScript &script : scripts) { CTxDestination dest; if (!ExtractDestination(script, dest)) { throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("Descriptor does not have a corresponding address")); } addresses.push_back(EncodeDestination(dest)); } } // This should not be possible, but an assert seems overkill: if (addresses.empty()) { throw JSONRPCError(RPC_MISC_ERROR, "Unexpected empty result"); } return addresses; }
/* * Decompose CWallet transaction to model transaction records. */ QList<TransactionRecord> TransactionRecord::decomposeTransaction(const interfaces::WalletTx& wtx) { QList<TransactionRecord> parts; int64_t nTime = wtx.time; CAmount nCredit = wtx.credit; CAmount nDebit = wtx.debit; CAmount nNet = nCredit - nDebit; uint256 hash = wtx.tx->GetHash(); std::map<std::string, std::string> mapValue = wtx.value_map; if (nNet > 0 || wtx.is_coinbase) { // // Credit // for(unsigned int i = 0; i < wtx.tx->vout.size(); i++) { const CTxOut& txout = wtx.tx->vout[i]; isminetype mine = wtx.txout_is_mine[i]; if(mine) { TransactionRecord sub(hash, nTime); CTxDestination address; sub.idx = i; // vout index sub.credit = txout.nValue; sub.involvesWatchAddress = mine & ISMINE_WATCH_ONLY; if (wtx.txout_address_is_mine[i]) { // Received by Fujicoin Address sub.type = TransactionRecord::RecvWithAddress; sub.address = EncodeDestination(wtx.txout_address[i]); } else { // Received by IP connection (deprecated features), or a multisignature or other non-simple transaction sub.type = TransactionRecord::RecvFromOther; sub.address = mapValue["from"]; } if (wtx.is_coinbase) { // Generated sub.type = TransactionRecord::Generated; } parts.append(sub); } } } else { bool involvesWatchAddress = false; isminetype fAllFromMe = ISMINE_SPENDABLE; for (isminetype mine : wtx.txin_is_mine) { if(mine & ISMINE_WATCH_ONLY) involvesWatchAddress = true; if(fAllFromMe > mine) fAllFromMe = mine; } isminetype fAllToMe = ISMINE_SPENDABLE; for (isminetype mine : wtx.txout_is_mine) { if(mine & ISMINE_WATCH_ONLY) involvesWatchAddress = true; if(fAllToMe > mine) fAllToMe = mine; } if (fAllFromMe && fAllToMe) { // Payment to self CAmount nChange = wtx.change; parts.append(TransactionRecord(hash, nTime, TransactionRecord::SendToSelf, "", -(nDebit - nChange), nCredit - nChange)); parts.last().involvesWatchAddress = involvesWatchAddress; // maybe pass to TransactionRecord as constructor argument } else if (fAllFromMe) { // // Debit // CAmount nTxFee = nDebit - wtx.tx->GetValueOut(); for (unsigned int nOut = 0; nOut < wtx.tx->vout.size(); nOut++) { const CTxOut& txout = wtx.tx->vout[nOut]; TransactionRecord sub(hash, nTime); sub.idx = nOut; sub.involvesWatchAddress = involvesWatchAddress; if(wtx.txout_is_mine[nOut]) { // Ignore parts sent to self, as this is usually the change // from a transaction sent back to our own address. continue; } if (!boost::get<CNoDestination>(&wtx.txout_address[nOut])) { // Sent to Fujicoin Address sub.type = TransactionRecord::SendToAddress; sub.address = EncodeDestination(wtx.txout_address[nOut]); } else { // Sent to IP, or other non-address transaction like OP_EVAL sub.type = TransactionRecord::SendToOther; sub.address = mapValue["to"]; } CAmount nValue = txout.nValue; /* Add fee to first output */ if (nTxFee > 0) { nValue += nTxFee; nTxFee = 0; } sub.debit = -nValue; parts.append(sub); } } else { // // Mixed debit transaction, can't break down payees // parts.append(TransactionRecord(hash, nTime, TransactionRecord::Other, "", nNet, 0)); parts.last().involvesWatchAddress = involvesWatchAddress; } } return parts; }
QString TransactionDesc::toHTML(interfaces::Node& node, interfaces::Wallet& wallet, TransactionRecord *rec, int unit) { int numBlocks; int64_t adjustedTime; interfaces::WalletTxStatus status; interfaces::WalletOrderForm orderForm; bool inMempool; interfaces::WalletTx wtx = wallet.getWalletTxDetails(rec->hash, status, orderForm, inMempool, numBlocks, adjustedTime); QString strHTML; strHTML.reserve(4000); strHTML += "<html><font face='verdana, arial, helvetica, sans-serif'>"; int64_t nTime = wtx.time; CAmount nCredit = wtx.credit; CAmount nDebit = wtx.debit; CAmount nNet = nCredit - nDebit; strHTML += "<b>" + tr("Status") + ":</b> " + FormatTxStatus(wtx, status, inMempool, numBlocks, adjustedTime); strHTML += "<br>"; strHTML += "<b>" + tr("Date") + ":</b> " + (nTime ? GUIUtil::dateTimeStr(nTime) : "") + "<br>"; // // From // if (wtx.is_coinbase) { strHTML += "<b>" + tr("Source") + ":</b> " + tr("Generated") + "<br>"; } else if (wtx.value_map.count("from") && !wtx.value_map["from"].empty()) { // Online transaction strHTML += "<b>" + tr("From") + ":</b> " + GUIUtil::HtmlEscape(wtx.value_map["from"]) + "<br>"; } else { // Offline transaction if (nNet > 0) { // Credit CTxDestination address = DecodeDestination(rec->address); if (IsValidDestination(address)) { std::string name; isminetype ismine; if (wallet.getAddress(address, &name, &ismine, /* purpose= */ nullptr)) { strHTML += "<b>" + tr("From") + ":</b> " + tr("unknown") + "<br>"; strHTML += "<b>" + tr("To") + ":</b> "; strHTML += GUIUtil::HtmlEscape(rec->address); QString addressOwned = ismine == ISMINE_SPENDABLE ? tr("own address") : tr("watch-only"); if (!name.empty()) strHTML += " (" + addressOwned + ", " + tr("label") + ": " + GUIUtil::HtmlEscape(name) + ")"; else strHTML += " (" + addressOwned + ")"; strHTML += "<br>"; } } } } // // To // if (wtx.value_map.count("to") && !wtx.value_map["to"].empty()) { // Online transaction std::string strAddress = wtx.value_map["to"]; strHTML += "<b>" + tr("To") + ":</b> "; CTxDestination dest = DecodeDestination(strAddress); std::string name; if (wallet.getAddress( dest, &name, /* is_mine= */ nullptr, /* purpose= */ nullptr) && !name.empty()) strHTML += GUIUtil::HtmlEscape(name) + " "; strHTML += GUIUtil::HtmlEscape(strAddress) + "<br>"; } // // Amount // if (wtx.is_coinbase && nCredit == 0) { // // Coinbase // CAmount nUnmatured = 0; for (const CTxOut& txout : wtx.tx->vout) nUnmatured += wallet.getCredit(txout, ISMINE_ALL); strHTML += "<b>" + tr("Credit") + ":</b> "; if (status.is_in_main_chain) strHTML += BitcoinUnits::formatHtmlWithUnit(unit, nUnmatured)+ " (" + tr("matures in %n more block(s)", "", status.blocks_to_maturity) + ")"; else strHTML += "(" + tr("not accepted") + ")"; strHTML += "<br>"; } else if (nNet > 0) { // // Credit // strHTML += "<b>" + tr("Credit") + ":</b> " + BitcoinUnits::formatHtmlWithUnit(unit, nNet) + "<br>"; } else { isminetype fAllFromMe = ISMINE_SPENDABLE; for (isminetype mine : wtx.txin_is_mine) { if(fAllFromMe > mine) fAllFromMe = mine; } isminetype fAllToMe = ISMINE_SPENDABLE; for (isminetype mine : wtx.txout_is_mine) { if(fAllToMe > mine) fAllToMe = mine; } if (fAllFromMe) { if(fAllFromMe & ISMINE_WATCH_ONLY) strHTML += "<b>" + tr("From") + ":</b> " + tr("watch-only") + "<br>"; // // Debit // auto mine = wtx.txout_is_mine.begin(); for (const CTxOut& txout : wtx.tx->vout) { // Ignore change isminetype toSelf = *(mine++); if ((toSelf == ISMINE_SPENDABLE) && (fAllFromMe == ISMINE_SPENDABLE)) continue; if (!wtx.value_map.count("to") || wtx.value_map["to"].empty()) { // Offline transaction CTxDestination address; if (ExtractDestination(txout.scriptPubKey, address)) { strHTML += "<b>" + tr("To") + ":</b> "; std::string name; if (wallet.getAddress( address, &name, /* is_mine= */ nullptr, /* purpose= */ nullptr) && !name.empty()) strHTML += GUIUtil::HtmlEscape(name) + " "; strHTML += GUIUtil::HtmlEscape(EncodeDestination(address)); if(toSelf == ISMINE_SPENDABLE) strHTML += " (own address)"; else if(toSelf & ISMINE_WATCH_ONLY) strHTML += " (watch-only)"; strHTML += "<br>"; } } strHTML += "<b>" + tr("Debit") + ":</b> " + BitcoinUnits::formatHtmlWithUnit(unit, -txout.nValue) + "<br>"; if(toSelf) strHTML += "<b>" + tr("Credit") + ":</b> " + BitcoinUnits::formatHtmlWithUnit(unit, txout.nValue) + "<br>"; } if (fAllToMe) { // Payment to self CAmount nChange = wtx.change; CAmount nValue = nCredit - nChange; strHTML += "<b>" + tr("Total debit") + ":</b> " + BitcoinUnits::formatHtmlWithUnit(unit, -nValue) + "<br>"; strHTML += "<b>" + tr("Total credit") + ":</b> " + BitcoinUnits::formatHtmlWithUnit(unit, nValue) + "<br>"; } CAmount nTxFee = nDebit - wtx.tx->GetValueOut(); if (nTxFee > 0) strHTML += "<b>" + tr("Transaction fee") + ":</b> " + BitcoinUnits::formatHtmlWithUnit(unit, -nTxFee) + "<br>"; } else { // // Mixed debit transaction // auto mine = wtx.txin_is_mine.begin(); for (const CTxIn& txin : wtx.tx->vin) { if (*(mine++)) { strHTML += "<b>" + tr("Debit") + ":</b> " + BitcoinUnits::formatHtmlWithUnit(unit, -wallet.getDebit(txin, ISMINE_ALL)) + "<br>"; } } mine = wtx.txout_is_mine.begin(); for (const CTxOut& txout : wtx.tx->vout) { if (*(mine++)) { strHTML += "<b>" + tr("Credit") + ":</b> " + BitcoinUnits::formatHtmlWithUnit(unit, wallet.getCredit(txout, ISMINE_ALL)) + "<br>"; } } } } strHTML += "<b>" + tr("Net amount") + ":</b> " + BitcoinUnits::formatHtmlWithUnit(unit, nNet, true) + "<br>"; // // Message // if (wtx.value_map.count("message") && !wtx.value_map["message"].empty()) strHTML += "<br><b>" + tr("Message") + ":</b><br>" + GUIUtil::HtmlEscape(wtx.value_map["message"], true) + "<br>"; if (wtx.value_map.count("comment") && !wtx.value_map["comment"].empty()) strHTML += "<br><b>" + tr("Comment") + ":</b><br>" + GUIUtil::HtmlEscape(wtx.value_map["comment"], true) + "<br>"; strHTML += "<b>" + tr("Transaction ID") + ":</b> " + rec->getTxHash() + "<br>"; strHTML += "<b>" + tr("Transaction total size") + ":</b> " + QString::number(wtx.tx->GetTotalSize()) + " bytes<br>"; strHTML += "<b>" + tr("Transaction virtual size") + ":</b> " + QString::number(GetVirtualTransactionSize(*wtx.tx)) + " bytes<br>"; strHTML += "<b>" + tr("Output index") + ":</b> " + QString::number(rec->getOutputIndex()) + "<br>"; // Message from normal bitcoin:URI (bitcoin:123...?message=example) for (const std::pair<std::string, std::string>& r : orderForm) if (r.first == "Message") strHTML += "<br><b>" + tr("Message") + ":</b><br>" + GUIUtil::HtmlEscape(r.second, true) + "<br>"; // // PaymentRequest info: // for (const std::pair<std::string, std::string>& r : orderForm) { if (r.first == "PaymentRequest") { PaymentRequestPlus req; req.parse(QByteArray::fromRawData(r.second.data(), r.second.size())); QString merchant; if (req.getMerchant(PaymentServer::getCertStore(), merchant)) strHTML += "<b>" + tr("Merchant") + ":</b> " + GUIUtil::HtmlEscape(merchant) + "<br>"; } } if (wtx.is_coinbase) { quint32 numBlocksToMaturity = COINBASE_MATURITY + 1; strHTML += "<br>" + tr("Generated coins must mature %1 blocks before they can be spent. When you generated this block, it was broadcast to the network to be added to the block chain. If it fails to get into the chain, its state will change to \"not accepted\" and it won't be spendable. This may occasionally happen if another node generates a block within a few seconds of yours.").arg(QString::number(numBlocksToMaturity)) + "<br>"; } // // Debug view // if (node.getLogCategories() != BCLog::NONE) { strHTML += "<hr><br>" + tr("Debug information") + "<br><br>"; for (const CTxIn& txin : wtx.tx->vin) if(wallet.txinIsMine(txin)) strHTML += "<b>" + tr("Debit") + ":</b> " + BitcoinUnits::formatHtmlWithUnit(unit, -wallet.getDebit(txin, ISMINE_ALL)) + "<br>"; for (const CTxOut& txout : wtx.tx->vout) if(wallet.txoutIsMine(txout)) strHTML += "<b>" + tr("Credit") + ":</b> " + BitcoinUnits::formatHtmlWithUnit(unit, wallet.getCredit(txout, ISMINE_ALL)) + "<br>"; strHTML += "<br><b>" + tr("Transaction") + ":</b><br>"; strHTML += GUIUtil::HtmlEscape(wtx.tx->ToString(), true); strHTML += "<br><b>" + tr("Inputs") + ":</b>"; strHTML += "<ul>"; for (const CTxIn& txin : wtx.tx->vin) { COutPoint prevout = txin.prevout; Coin prev; if(node.getUnspentOutput(prevout, prev)) { { strHTML += "<li>"; const CTxOut &vout = prev.out; CTxDestination address; if (ExtractDestination(vout.scriptPubKey, address)) { std::string name; if (wallet.getAddress(address, &name, /* is_mine= */ nullptr, /* purpose= */ nullptr) && !name.empty()) strHTML += GUIUtil::HtmlEscape(name) + " "; strHTML += QString::fromStdString(EncodeDestination(address)); } strHTML = strHTML + " " + tr("Amount") + "=" + BitcoinUnits::formatHtmlWithUnit(unit, vout.nValue); strHTML = strHTML + " IsMine=" + (wallet.txoutIsMine(vout) & ISMINE_SPENDABLE ? tr("true") : tr("false")) + "</li>"; strHTML = strHTML + " IsWatchOnly=" + (wallet.txoutIsMine(vout) & ISMINE_WATCH_ONLY ? tr("true") : tr("false")) + "</li>"; } } } strHTML += "</ul>"; } strHTML += "</font></html>"; return strHTML; }
UniValue validateaddress(const JSONRPCRequest& request) { if (request.fHelp || request.params.size() != 1) throw std::runtime_error( "validateaddress \"address\"\n" "\nReturn information about the given bitcoin address.\n" "\nArguments:\n" "1. \"address\" (string, required) The bitcoin address to validate\n" "\nResult:\n" "{\n" " \"isvalid\" : true|false, (boolean) If the address is valid or not. If not, this is the only property returned.\n" " \"address\" : \"address\", (string) The bitcoin address validated\n" " \"scriptPubKey\" : \"hex\", (string) The hex encoded scriptPubKey generated by the address\n" " \"ismine\" : true|false, (boolean) If the address is yours or not\n" " \"iswatchonly\" : true|false, (boolean) If the address is watchonly\n" " \"isscript\" : true|false, (boolean) If the key is a script\n" " \"script\" : \"type\" (string, optional) The output script type. Possible types: nonstandard, pubkey, pubkeyhash, scripthash, multisig, nulldata, witness_v0_keyhash, witness_v0_scripthash\n" " \"hex\" : \"hex\", (string, optional) The redeemscript for the p2sh address\n" " \"addresses\" (string, optional) Array of addresses associated with the known redeemscript\n" " [\n" " \"address\"\n" " ,...\n" " ]\n" " \"sigsrequired\" : xxxxx (numeric, optional) Number of signatures required to spend multisig output\n" " \"pubkey\" : \"publickeyhex\", (string) The hex value of the raw public key\n" " \"iscompressed\" : true|false, (boolean) If the address is compressed\n" " \"account\" : \"account\" (string) DEPRECATED. The account associated with the address, \"\" is the default account\n" " \"timestamp\" : timestamp, (number, optional) The creation time of the key if available in seconds since epoch (Jan 1 1970 GMT)\n" " \"hdkeypath\" : \"keypath\" (string, optional) The HD keypath if the key is HD and available\n" " \"hdmasterkeyid\" : \"<hash160>\" (string, optional) The Hash160 of the HD master pubkey\n" "}\n" "\nExamples:\n" + HelpExampleCli("validateaddress", "\"1PSSGeFHDnKNxiEyFrD1wcEaHr9hrQDDWc\"") + HelpExampleRpc("validateaddress", "\"1PSSGeFHDnKNxiEyFrD1wcEaHr9hrQDDWc\"") ); #ifdef ENABLE_WALLET CWallet * const pwallet = GetWalletForJSONRPCRequest(request); LOCK2(cs_main, pwallet ? &pwallet->cs_wallet : nullptr); #else LOCK(cs_main); #endif CTxDestination dest = DecodeDestination(request.params[0].get_str()); bool isValid = IsValidDestination(dest); UniValue ret(UniValue::VOBJ); ret.push_back(Pair("isvalid", isValid)); if (isValid) { std::string currentAddress = EncodeDestination(dest); ret.push_back(Pair("address", currentAddress)); CScript scriptPubKey = GetScriptForDestination(dest); ret.push_back(Pair("scriptPubKey", HexStr(scriptPubKey.begin(), scriptPubKey.end()))); #ifdef ENABLE_WALLET isminetype mine = pwallet ? IsMine(*pwallet, dest) : ISMINE_NO; ret.push_back(Pair("ismine", bool(mine & ISMINE_SPENDABLE))); ret.push_back(Pair("iswatchonly", bool(mine & ISMINE_WATCH_ONLY))); UniValue detail = boost::apply_visitor(DescribeAddressVisitor(pwallet), dest); ret.pushKVs(detail); if (pwallet && pwallet->mapAddressBook.count(dest)) { ret.push_back(Pair("account", pwallet->mapAddressBook[dest].name)); } if (pwallet) { const auto& meta = pwallet->mapKeyMetadata; const CKeyID *keyID = boost::get<CKeyID>(&dest); auto it = keyID ? meta.find(*keyID) : meta.end(); if (it == meta.end()) { it = meta.find(CScriptID(scriptPubKey)); } if (it != meta.end()) { ret.push_back(Pair("timestamp", it->second.nCreateTime)); if (!it->second.hdKeypath.empty()) { ret.push_back(Pair("hdkeypath", it->second.hdKeypath)); ret.push_back(Pair("hdmasterkeyid", it->second.hdMasterKeyID.GetHex())); } } } #endif } return ret; }
static UniValue createmultisig(const JSONRPCRequest& request) { if (request.fHelp || request.params.size() < 2 || request.params.size() > 3) { std::string msg = "createmultisig nrequired [\"key\",...] ( \"address_type\" )\n" "\nCreates a multi-signature address with n signature of m keys required.\n" "It returns a json object with the address and redeemScript.\n" "\nArguments:\n" "1. nrequired (numeric, required) The number of required signatures out of the n keys.\n" "2. \"keys\" (string, required) A json array of hex-encoded public keys\n" " [\n" " \"key\" (string) The hex-encoded public key\n" " ,...\n" " ]\n" "3. \"address_type\" (string, optional) The address type to use. Options are \"legacy\", \"p2sh-segwit\", and \"bech32\". Default is legacy.\n" "\nResult:\n" "{\n" " \"address\":\"multisigaddress\", (string) The value of the new multisig address.\n" " \"redeemScript\":\"script\" (string) The string value of the hex-encoded redemption script.\n" "}\n" "\nExamples:\n" "\nCreate a multisig address from 2 public keys\n" + HelpExampleCli("createmultisig", "2 \"[\\\"03789ed0bb717d88f7d321a368d905e7430207ebbd82bd342cf11ae157a7ace5fd\\\",\\\"03dbc6764b8884a92e871274b87583e6d5c2a58819473e17e107ef3f6aa5a61626\\\"]\"") + "\nAs a json rpc call\n" + HelpExampleRpc("createmultisig", "2, \"[\\\"03789ed0bb717d88f7d321a368d905e7430207ebbd82bd342cf11ae157a7ace5fd\\\",\\\"03dbc6764b8884a92e871274b87583e6d5c2a58819473e17e107ef3f6aa5a61626\\\"]\"") ; throw std::runtime_error(msg); } int required = request.params[0].get_int(); // Get the public keys const UniValue& keys = request.params[1].get_array(); std::vector<CPubKey> pubkeys; for (unsigned int i = 0; i < keys.size(); ++i) { if (IsHex(keys[i].get_str()) && (keys[i].get_str().length() == 66 || keys[i].get_str().length() == 130)) { pubkeys.push_back(HexToPubKey(keys[i].get_str())); } else { throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("Invalid public key: %s\n.", keys[i].get_str())); } } // Get the output type OutputType output_type = OutputType::LEGACY; if (!request.params[2].isNull()) { if (!ParseOutputType(request.params[2].get_str(), output_type)) { throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("Unknown address type '%s'", request.params[2].get_str())); } } // Construct using pay-to-script-hash: const CScript inner = CreateMultisigRedeemscript(required, pubkeys); CBasicKeyStore keystore; const CTxDestination dest = AddAndGetDestinationForScript(keystore, inner, output_type); UniValue result(UniValue::VOBJ); result.pushKV("address", EncodeDestination(dest)); result.pushKV("redeemScript", HexStr(inner.begin(), inner.end())); return result; }
void CoinControlDialog::updateView() { if (!model || !model->getOptionsModel() || !model->getAddressTableModel()) return; bool treeMode = ui->radioTreeMode->isChecked(); ui->treeWidget->clear(); ui->treeWidget->setEnabled(false); // performance, otherwise updateLabels would be called for every checked checkbox ui->treeWidget->setAlternatingRowColors(!treeMode); QFlags<Qt::ItemFlag> flgCheckbox = Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsUserCheckable; QFlags<Qt::ItemFlag> flgTristate = Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsUserCheckable | Qt::ItemIsTristate; int nDisplayUnit = model->getOptionsModel()->getDisplayUnit(); std::map<QString, std::vector<COutput> > mapCoins; model->listCoins(mapCoins); for (const std::pair<QString, std::vector<COutput>>& coins : mapCoins) { CCoinControlWidgetItem *itemWalletAddress = new CCoinControlWidgetItem(); itemWalletAddress->setCheckState(COLUMN_CHECKBOX, Qt::Unchecked); QString sWalletAddress = coins.first; QString sWalletLabel = model->getAddressTableModel()->labelForAddress(sWalletAddress); if (sWalletLabel.isEmpty()) sWalletLabel = tr("(no label)"); if (treeMode) { // wallet address ui->treeWidget->addTopLevelItem(itemWalletAddress); itemWalletAddress->setFlags(flgTristate); itemWalletAddress->setCheckState(COLUMN_CHECKBOX, Qt::Unchecked); // label itemWalletAddress->setText(COLUMN_LABEL, sWalletLabel); // address itemWalletAddress->setText(COLUMN_ADDRESS, sWalletAddress); } CAmount nSum = 0; int nChildren = 0; for (const COutput& out : coins.second) { nSum += out.tx->tx->vout[out.i].nValue; nChildren++; CCoinControlWidgetItem *itemOutput; if (treeMode) itemOutput = new CCoinControlWidgetItem(itemWalletAddress); else itemOutput = new CCoinControlWidgetItem(ui->treeWidget); itemOutput->setFlags(flgCheckbox); itemOutput->setCheckState(COLUMN_CHECKBOX,Qt::Unchecked); // address CTxDestination outputAddress; QString sAddress = ""; if(ExtractDestination(out.tx->tx->vout[out.i].scriptPubKey, outputAddress)) { sAddress = QString::fromStdString(EncodeDestination(outputAddress)); // if listMode or change => show bitcoin address. In tree mode, address is not shown again for direct wallet address outputs if (!treeMode || (!(sAddress == sWalletAddress))) itemOutput->setText(COLUMN_ADDRESS, sAddress); } // label if (!(sAddress == sWalletAddress)) // change { // tooltip from where the change comes from itemOutput->setToolTip(COLUMN_LABEL, tr("change from %1 (%2)").arg(sWalletLabel).arg(sWalletAddress)); itemOutput->setText(COLUMN_LABEL, tr("(change)")); } else if (!treeMode) { QString sLabel = model->getAddressTableModel()->labelForAddress(sAddress); if (sLabel.isEmpty()) sLabel = tr("(no label)"); itemOutput->setText(COLUMN_LABEL, sLabel); } // amount itemOutput->setText(COLUMN_AMOUNT, BitcoinUnits::format(nDisplayUnit, out.tx->tx->vout[out.i].nValue)); itemOutput->setData(COLUMN_AMOUNT, Qt::UserRole, QVariant((qlonglong)out.tx->tx->vout[out.i].nValue)); // padding so that sorting works correctly // date itemOutput->setText(COLUMN_DATE, GUIUtil::dateTimeStr(out.tx->GetTxTime())); itemOutput->setData(COLUMN_DATE, Qt::UserRole, QVariant((qlonglong)out.tx->GetTxTime())); // confirmations itemOutput->setText(COLUMN_CONFIRMATIONS, QString::number(out.nDepth)); itemOutput->setData(COLUMN_CONFIRMATIONS, Qt::UserRole, QVariant((qlonglong)out.nDepth)); // transaction hash uint256 txhash = out.tx->GetHash(); itemOutput->setText(COLUMN_TXHASH, QString::fromStdString(txhash.GetHex())); // vout index itemOutput->setText(COLUMN_VOUT_INDEX, QString::number(out.i)); // disable locked coins if (model->isLockedCoin(txhash, out.i)) { COutPoint outpt(txhash, out.i); coinControl->UnSelect(outpt); // just to be sure itemOutput->setDisabled(true); itemOutput->setIcon(COLUMN_CHECKBOX, platformStyle->SingleColorIcon(":/icons/lock_closed")); } // set checkbox if (coinControl->IsSelected(COutPoint(txhash, out.i))) itemOutput->setCheckState(COLUMN_CHECKBOX, Qt::Checked); } // amount if (treeMode) { itemWalletAddress->setText(COLUMN_CHECKBOX, "(" + QString::number(nChildren) + ")"); itemWalletAddress->setText(COLUMN_AMOUNT, BitcoinUnits::format(nDisplayUnit, nSum)); itemWalletAddress->setData(COLUMN_AMOUNT, Qt::UserRole, QVariant((qlonglong)nSum)); } } // expand all partially selected if (treeMode) { for (int i = 0; i < ui->treeWidget->topLevelItemCount(); i++) if (ui->treeWidget->topLevelItem(i)->checkState(COLUMN_CHECKBOX) == Qt::PartiallyChecked) ui->treeWidget->topLevelItem(i)->setExpanded(true); } // sort view sortView(sortColumn, sortOrder); ui->treeWidget->setEnabled(true); }