UniValue createrawtransaction(const UniValue& params, bool fHelp) { if (fHelp || (params.size() < 2 || params.size() > 3)) throw runtime_error( "createrawtransaction [{\"txid\":txid,\"vout\":n},...] {address:amount,...} [tx-comment]\n" "Create a transaction spending given inputs\n" "(array of objects containing transaction id and output number),\n" "sending to given address(es).\n" "Each <amount> is either an amount to send or {\"count\":c,\"amount\":a,\"locktime\":t}\n" "which adds <c> outputs each sending <a> CON with a locktime of <t>.\n" "The count <c> and locktime <t> are both optional.\n" "Returns hex-encoded raw transaction.\n" "Note that the transaction's inputs are not signed, and\n" "it is not stored in the wallet or transmitted to the network."); RPCTypeCheck(params, list_of(UniValue::VARR)(UniValue::VOBJ)); UniValue inputs = params[0].get_array(); UniValue sendTo = params[1].get_obj(); CTransaction rawTx; // set conSpeech when creating a raw transaction if (params.size() == 3) rawTx.strCONSpeech = params[2].get_str(); else if (mapArgs["-conspeech"] != "off") rawTx.strCONSpeech = GetDefaultConSpeech(); if (rawTx.strCONSpeech.length() > MAX_TX_COMMENT_LEN) rawTx.strCONSpeech.resize(MAX_TX_COMMENT_LEN); for (unsigned int idx = 0; idx < inputs.size(); idx++) { const UniValue& input = inputs[idx]; const UniValue& o = input.get_obj(); const UniValue& txid_v = find_value(o, "txid"); if (txid_v.isNull()) throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, missing txid key"); string txid = txid_v.get_str(); if (!IsHex(txid)) throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, expected hex txid"); const UniValue& vout_v = find_value(o, "vout"); if (!vout_v.isNum()) throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, missing vout key"); int nOutput = vout_v.get_int(); if (nOutput < 0) throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, vout must be positive"); CTxIn in(COutPoint(uint256(txid), nOutput)); rawTx.vin.push_back(in); } // set<CBitcoinAddress> setAddress; vector<string> addrList = sendTo.getKeys(); vector<UniValue> valueList= sendTo.getValues(); vector<UniValue>::iterator valueList_iterator = valueList.begin(); BOOST_FOREACH(const string& name_, addrList) { const UniValue& value_ = *valueList_iterator++; CBitcoinAddress address(name_); if (!address.IsValid()) throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, string("Invalid PayCon address: ")+name_); // if (setAddress.count(address)) // throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, duplicated address: ")+name_); // setAddress.insert(address); CScript scriptPubKey; scriptPubKey.SetDestination(address.Get()); // we usually want the 2nd parameter to be {"addr1":ammount1,"addr2":ammount2,...} // in addition to numerical amounts we now also accept values like: // '{"count":2,"amount":1.3,"locktime":333333}' meaning 'make 2 outputs worth 1.3 CON each, locked until block 333333' // "count" is a non-negative integer; 0 works and simply makes no new outputs // "locktime" is a non-negative integer; values less than LOCKTIME_THRESHOLD (500,000,000) are block heights; others are epoch timestamps if (value_.isObject()) { const UniValue& o = value_.get_obj(); const UniValue& count_v = find_value(o, "count"); const UniValue& locktime_v = find_value(o, "locktime"); int64_t count, locktime; if (count_v.isNull()) count = 1; else if (count_v.isNum()) count = count_v.get_int64(); else throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, count must be integer"); if (count < 0) throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, count must not be negative"); if (!locktime_v.isNull()) { if (locktime_v.isNum()) locktime = locktime_v.get_int64(); else throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, locktime must be integer"); if (locktime < 0) throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, locktime must not be negative"); scriptPubKey.SetLockTime(locktime); } CTxOut out(AmountFromValue(find_value(o, "amount")), scriptPubKey); while (count--) rawTx.vout.push_back(out); } else { CTxOut out(AmountFromValue(value_), scriptPubKey); rawTx.vout.push_back(out); } } CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); ss << rawTx; return HexStr(ss.begin(), ss.end()); }
void DBBComServer::startLongPollThread() { std::unique_lock<std::mutex> lock(cs_com); if (longPollThread) return; longPollThread = DBBNetThread::DetachThread(); longPollThread->currentThread = std::thread([this]() { std::string response; long httpStatusCode; long sequence = 0; int errorCounts = 0; UniValue jsonOut; while(1) { response = ""; httpStatusCode = 400; { // we store the channel ID to detect channelID changes during long poll std::unique_lock<std::mutex> lock(cs_com); currentLongPollChannelID = channelID; currentLongPollURL = comServerURL; } SendRequest("post", currentLongPollURL, "c=gd&uuid="+currentLongPollChannelID+"&dt=0&s="+std::to_string(sequence), response, httpStatusCode); sequence++; if (httpStatusCode >= 300) { errorCounts++; if (errorCounts > 5) { DBB::LogPrintDebug("Error, can't connect to the smart verification server"); // wait 10 seconds before the next try std::this_thread::sleep_for(std::chrono::milliseconds(10000)); } else std::this_thread::sleep_for(std::chrono::milliseconds(2000)); } else errorCounts = 0; // ignore the response if the channel has been switched (re-pairing) { std::unique_lock<std::mutex> lock(cs_com); if (currentLongPollChannelID != channelID || currentLongPollURL != comServerURL) continue; } jsonOut.read(response); if (jsonOut.isObject()) { UniValue data = find_value(jsonOut, "data"); if (data.isArray()) { for (const UniValue& element : data.getValues()) { UniValue payload = find_value(element, "payload"); if (payload.isStr()) { std::string plaintextPayload; std::string keyS(encryptionKey.begin(), encryptionKey.end()); if (DBB::decryptAndDecodeCommand(payload.get_str(), keyS, plaintextPayload, false)) { std::unique_lock<std::mutex> lock(cs_com); if (parseMessageCB) parseMessageCB(this, plaintextPayload, ctx); } // mem-cleanse the key std::fill(keyS.begin(), keyS.end(), 0); keyS.clear(); } } } } } std::unique_lock<std::mutex> lock(cs_com); longPollThread->completed(); }); }