void MultisigDialog::on_saveRedeemScriptButton_clicked() { if(!model) return; CWallet *wallet = model->getWallet(); std::string redeemScript = ui->redeemScript->text().toStdString(); std::vector<unsigned char> scriptData(ParseHex(redeemScript)); CScript script(scriptData.begin(), scriptData.end()); CScriptID scriptID = script.GetID(); LOCK(wallet->cs_wallet); if(!wallet->HaveCScript(scriptID)) wallet->AddCScript(script); }
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; }
// ///////////////////////////////////////////////////////////////// // // ///////////////////////////////////////////////////////////////// bool LuaStateManager::ExecuteResourceFile(LuaPlus::LuaStateOwner &luaState, const char * const scriptName, ResCache *rcManagerPtr) { if(!rcManagerPtr || !scriptName || strlen(scriptName) == 0) { return (false); } std::string rn(scriptName); TextResource tr(rn); boost::shared_ptr<TextResHandle> scriptHandle = boost::static_pointer_cast<TextResHandle>(rcManagerPtr->GetHandle(&tr)); if(!scriptHandle || !scriptHandle->VInitialize()) { GF_LOG_TRACE_ERR("LuaStateManager::ExecuteResourceFile()", std::string("Failed to initialize from cache: ") + tr.GetName()); return (false); } std::string scriptData(scriptHandle->GetTextBuffer()); // Split up the file by the newline character. #ifdef _WINDOWS std::string newLine("\n"); #else std::string newLine("\t\n"); #endif // Make a large vector to prevent repeating reallocations (500 - we dont know how long the file is, this is a guess to help reduce reallocations). std::vector<std::string> linesVec; linesVec.reserve(500); boost::algorithm::split(linesVec, scriptData, boost::algorithm::is_any_of(newLine)); // Trim excess capacity. std::vector<std::string>(linesVec.begin(), linesVec.end()).swap(linesVec); RemoveTrailingCr fo; std::for_each(linesVec.begin(), linesVec.end(), fo); scriptData.clear(); for(std::vector<std::string>::iterator i = linesVec.begin(), end = linesVec.end(); i != end; ++i) { scriptData += *i; } if(luaState->DoString(scriptData.c_str()) != 0) { GF_LOG_TRACE_ERR("LuaStateManager::ExecuteResourceFile()", std::string("Failed to execute ") + tr.GetName()); return (false); } return (true); }
PassOwnPtr<v8::ScriptData> V8Proxy::precompileScript(v8::Handle<v8::String> code, CachedScript* cachedScript) { // A pseudo-randomly chosen ID used to store and retrieve V8 ScriptData from // the CachedScript. If the format changes, this ID should be changed too. static const unsigned dataTypeID = 0xECC13BD7; // Very small scripts are not worth the effort to preparse. static const int minPreparseLength = 1024; if (!cachedScript || code->Length() < minPreparseLength) return 0; CachedMetadata* cachedMetadata = cachedScript->cachedMetadata(dataTypeID); if (cachedMetadata) return v8::ScriptData::New(cachedMetadata->data(), cachedMetadata->size()); OwnPtr<v8::ScriptData> scriptData(v8::ScriptData::PreCompile(code)); cachedScript->setCachedMetadata(dataTypeID, scriptData->Data(), scriptData->Length()); return scriptData.release(); }
void MultisigDialog::on_saveMultisigAddressButton_clicked() { if(!model) return; CWallet *wallet = model->getWallet(); std::string redeemScript = ui->redeemScript->text().toStdString(); std::string address = ui->multisigAddress->text().toStdString(); std::string label("multisig"); if(!model->validateAddress(QString(address.c_str()))) return; std::vector<unsigned char> scriptData(ParseHex(redeemScript)); CScript script(scriptData.begin(), scriptData.end()); CScriptID scriptID = script.GetID(); LOCK(wallet->cs_wallet); if(!wallet->HaveCScript(scriptID)) wallet->AddCScript(script); if(!wallet->mapAddressBook.count(CBitcoinAddress(address).Get())) wallet->SetAddressBookName(CBitcoinAddress(address).Get(), label); }
/* * Command line options for autostart (keep synchronized with binaries/system/readme.txt): * * -autostart="TYPEDIR/MAPNAME" enables autostart and sets MAPNAME; TYPEDIR is skirmishes, scenarios, or random * -autostart-ai=PLAYER:AI sets the AI for PLAYER (e.g. 2:petra) * -autostart-aidiff=PLAYER:DIFF sets the DIFFiculty of PLAYER's AI (0: sandbox, 5: very hard) * -autostart-civ=PLAYER:CIV sets PLAYER's civilisation to CIV (skirmish and random maps only) * -autostart-aiseed=AISEED sets the seed used for the AI random generator (default 0, use -1 for random) * Multiplayer: * -autostart-playername=NAME sets local player NAME (default 'anonymous') * -autostart-host sets multiplayer host mode * -autostart-host-players=NUMBER sets NUMBER of human players for multiplayer game (default 2) * -autostart-client=IP sets multiplayer client to join host at given IP address * Random maps only: * -autostart-seed=SEED sets random map SEED value (default 0, use -1 for random) * -autostart-size=TILES sets random map size in TILES (default 192) * -autostart-players=NUMBER sets NUMBER of players on random map (default 2) * * Examples: * 1) "Bob" will host a 2 player game on the Arcadia map: * -autostart="scenarios/Arcadia 02" -autostart-host -autostart-host-players=2 -autostart-playername="Bob" * 2) Load Alpine Lakes random map with random seed, 2 players (Athens and Britons), and player 2 is PetraBot: * -autostart="random/alpine_lakes" -autostart-seed=-1 -autostart-players=2 -autostart-civ=1:athen -autostart-civ=2:brit -autostart-ai=2:petra */ bool Autostart(const CmdLineArgs& args) { CStr autoStartName = args.Get("autostart"); if (autoStartName.empty()) return false; g_Game = new CGame(); ScriptInterface& scriptInterface = g_Game->GetSimulation2()->GetScriptInterface(); JSContext* cx = scriptInterface.GetContext(); JSAutoRequest rq(cx); JS::RootedValue attrs(cx); scriptInterface.Eval("({})", &attrs); JS::RootedValue settings(cx); scriptInterface.Eval("({})", &settings); JS::RootedValue playerData(cx); scriptInterface.Eval("([])", &playerData); // The directory in front of the actual map name indicates which type // of map is being loaded. Drawback of this approach is the association // of map types and folders is hard-coded, but benefits are: // - No need to pass the map type via command line separately // - Prevents mixing up of scenarios and skirmish maps to some degree Path mapPath = Path(autoStartName); std::wstring mapDirectory = mapPath.Parent().Filename().string(); std::string mapType; if (mapDirectory == L"random") { // Default seed is 0 u32 seed = 0; CStr seedArg = args.Get("autostart-seed"); if (!seedArg.empty()) { // Random seed value if (seedArg == "-1") seed = rand(); else seed = seedArg.ToULong(); } // Random map definition will be loaded from JSON file, so we need to parse it std::wstring scriptPath = L"maps/" + autoStartName.FromUTF8() + L".json"; JS::RootedValue scriptData(cx); scriptInterface.ReadJSONFile(scriptPath, &scriptData); if (!scriptData.isUndefined() && scriptInterface.GetProperty(scriptData, "settings", &settings)) { // JSON loaded ok - copy script name over to game attributes std::wstring scriptFile; scriptInterface.GetProperty(settings, "Script", scriptFile); scriptInterface.SetProperty(attrs, "script", scriptFile); // RMS filename } else { // Problem with JSON file LOGERROR("Autostart: Error reading random map script '%s'", utf8_from_wstring(scriptPath)); throw PSERROR_Game_World_MapLoadFailed("Error reading random map script.\nCheck application log for details."); } // Get optional map size argument (default 192) uint mapSize = 192; if (args.Has("autostart-size")) { CStr size = args.Get("autostart-size"); mapSize = size.ToUInt(); } scriptInterface.SetProperty(settings, "Seed", seed); // Random seed scriptInterface.SetProperty(settings, "Size", mapSize); // Random map size (in patches) // Get optional number of players (default 2) size_t numPlayers = 2; if (args.Has("autostart-players")) { CStr num = args.Get("autostart-players"); numPlayers = num.ToUInt(); } // Set up player data for (size_t i = 0; i < numPlayers; ++i) { JS::RootedValue player(cx); scriptInterface.Eval("({})", &player); // We could load player_defaults.json here, but that would complicate the logic // even more and autostart is only intended for developers anyway scriptInterface.SetProperty(player, "Civ", std::string("athen")); scriptInterface.SetPropertyInt(playerData, i, player); } mapType = "random"; } else if (mapDirectory == L"scenarios" || mapDirectory == L"skirmishes") { // Initialize general settings from the map data so some values // (e.g. name of map) are always present, even when autostart is // partially configured CStr8 mapSettingsJSON = LoadSettingsOfScenarioMap("maps/" + autoStartName + ".xml"); scriptInterface.ParseJSON(mapSettingsJSON, &settings); // Initialize the playerData array being modified by autostart // with the real map data, so sensible values are present: scriptInterface.GetProperty(settings, "PlayerData", &playerData); if (mapDirectory == L"scenarios") mapType = "scenario"; else mapType = "skirmish"; } else { LOGERROR("Autostart: Unrecognized map type '%s'", utf8_from_wstring(mapDirectory)); throw PSERROR_Game_World_MapLoadFailed("Unrecognized map type.\nConsult readme.txt for the currently supported types."); } scriptInterface.SetProperty(attrs, "mapType", mapType); scriptInterface.SetProperty(attrs, "map", std::string("maps/" + autoStartName)); scriptInterface.SetProperty(settings, "mapType", mapType); // Set seed for AIs u32 aiseed = 0; if (args.Has("autostart-aiseed")) { CStr seedArg = args.Get("autostart-aiseed"); if (seedArg == "-1") aiseed = rand(); else aiseed = seedArg.ToULong(); } scriptInterface.SetProperty(settings, "AISeed", aiseed); // Set player data for AIs // attrs.settings = { PlayerData: [ { AI: ... }, ... ] }: if (args.Has("autostart-ai")) { std::vector<CStr> aiArgs = args.GetMultiple("autostart-ai"); for (size_t i = 0; i < aiArgs.size(); ++i) { int playerID = aiArgs[i].BeforeFirst(":").ToInt(); // Instead of overwriting existing player data, modify the array JS::RootedValue player(cx); if (!scriptInterface.GetPropertyInt(playerData, playerID-1, &player) || player.isUndefined()) { if (mapDirectory == L"scenarios" || mapDirectory == L"skirmishes") { // playerID is certainly bigger than this map player number LOGWARNING("Autostart: Invalid player %d in autostart-ai option", playerID); continue; } scriptInterface.Eval("({})", &player); } CStr name = aiArgs[i].AfterFirst(":"); scriptInterface.SetProperty(player, "AI", std::string(name)); scriptInterface.SetProperty(player, "AIDiff", 3); scriptInterface.SetPropertyInt(playerData, playerID-1, player); } } // Set AI difficulty if (args.Has("autostart-aidiff")) { std::vector<CStr> civArgs = args.GetMultiple("autostart-aidiff"); for (size_t i = 0; i < civArgs.size(); ++i) { int playerID = civArgs[i].BeforeFirst(":").ToInt(); // Instead of overwriting existing player data, modify the array JS::RootedValue player(cx); if (!scriptInterface.GetPropertyInt(playerData, playerID-1, &player) || player.isUndefined()) { if (mapDirectory == L"scenarios" || mapDirectory == L"skirmishes") { // playerID is certainly bigger than this map player number LOGWARNING("Autostart: Invalid player %d in autostart-aidiff option", playerID); continue; } scriptInterface.Eval("({})", &player); } int difficulty = civArgs[i].AfterFirst(":").ToInt(); scriptInterface.SetProperty(player, "AIDiff", difficulty); scriptInterface.SetPropertyInt(playerData, playerID-1, player); } } // Set player data for Civs if (args.Has("autostart-civ")) { if (mapDirectory != L"scenarios") { std::vector<CStr> civArgs = args.GetMultiple("autostart-civ"); for (size_t i = 0; i < civArgs.size(); ++i) { int playerID = civArgs[i].BeforeFirst(":").ToInt(); // Instead of overwriting existing player data, modify the array JS::RootedValue player(cx); if (!scriptInterface.GetPropertyInt(playerData, playerID-1, &player) || player.isUndefined()) { if (mapDirectory == L"skirmishes") { // playerID is certainly bigger than this map player number LOGWARNING("Autostart: Invalid player %d in autostart-civ option", playerID); continue; } scriptInterface.Eval("({})", &player); } CStr name = civArgs[i].AfterFirst(":"); scriptInterface.SetProperty(player, "Civ", std::string(name)); scriptInterface.SetPropertyInt(playerData, playerID-1, player); } } else LOGWARNING("Autostart: Option 'autostart-civ' is invalid for scenarios"); } // Add player data to map settings scriptInterface.SetProperty(settings, "PlayerData", playerData); // Add map settings to game attributes scriptInterface.SetProperty(attrs, "settings", settings); JS::RootedValue mpInitData(cx); scriptInterface.Eval("({isNetworked:true, playerAssignments:{}})", &mpInitData); scriptInterface.SetProperty(mpInitData, "attribs", attrs); // Get optional playername CStrW userName = L"anonymous"; if (args.Has("autostart-playername")) { userName = args.Get("autostart-playername").FromUTF8(); } if (args.Has("autostart-host")) { InitPs(true, L"page_loading.xml", &scriptInterface, mpInitData); size_t maxPlayers = 2; if (args.Has("autostart-host-players")) maxPlayers = args.Get("autostart-host-players").ToUInt(); g_NetServer = new CNetServer(maxPlayers); g_NetServer->UpdateGameAttributes(&attrs, scriptInterface); bool ok = g_NetServer->SetupConnection(); ENSURE(ok); g_NetClient = new CNetClient(g_Game); g_NetClient->SetUserName(userName); g_NetClient->SetupConnection("127.0.0.1"); } else if (args.Has("autostart-client")) { InitPs(true, L"page_loading.xml", &scriptInterface, mpInitData); g_NetClient = new CNetClient(g_Game); g_NetClient->SetUserName(userName); CStr ip = args.Get("autostart-client"); if (ip.empty()) ip = "127.0.0.1"; bool ok = g_NetClient->SetupConnection(ip); ENSURE(ok); } else { g_Game->SetPlayerID(1); g_Game->StartGame(&attrs, ""); LDR_NonprogressiveLoad(); PSRETURN ret = g_Game->ReallyStartGame(); ENSURE(ret == PSRETURN_OK); InitPs(true, L"page_session.xml", NULL, JS::UndefinedHandleValue); } return true; }
void MultisigDialog::on_signTransactionButton_clicked() { ui->signedTransaction->clear(); if(!model) return; CWallet *wallet = model->getWallet(); // Decode the raw transaction std::vector<unsigned char> txData(ParseHex(ui->transaction->text().toStdString())); CDataStream ss(txData, SER_NETWORK, PROTOCOL_VERSION); CTransaction tx; try { ss >> tx; } catch(std::exception &e) { (void)e; return; } CTransaction mergedTx(tx); // Fetch previous transactions (inputs) std::map<COutPoint, CScript> mapPrevOut; for(unsigned int i = 0; i < mergedTx.vin.size(); i++) { CTransaction tempTx; MapPrevTx mapPrevTx; CTxDB txdb("r"); std::map<uint256, CTxIndex> unused; bool fInvalid; tempTx.vin.push_back(mergedTx.vin[i]); tempTx.FetchInputs(txdb, unused, false, false, mapPrevTx, fInvalid); BOOST_FOREACH(const CTxIn& txin, tempTx.vin) { const uint256& prevHash = txin.prevout.hash; if(mapPrevTx.count(prevHash) && mapPrevTx[prevHash].second.vout.size() > txin.prevout.n) mapPrevOut[txin.prevout] = mapPrevTx[prevHash].second.vout[txin.prevout.n].scriptPubKey; } } // Add the redeem scripts to the wallet keystore for(int i = 0; i < ui->inputs->count(); i++) { MultisigInputEntry *entry = qobject_cast<MultisigInputEntry *>(ui->inputs->itemAt(i)->widget()); if(entry) { QString redeemScriptStr = entry->getRedeemScript(); if(redeemScriptStr.size() > 0) { std::vector<unsigned char> scriptData(ParseHex(redeemScriptStr.toStdString())); CScript redeemScript(scriptData.begin(), scriptData.end()); wallet->AddCScript(redeemScript); } } } WalletModel::UnlockContext ctx(model->requestUnlock()); if(!ctx.isValid()) return; // Sign what we can bool fComplete = true; for(unsigned int i = 0; i < mergedTx.vin.size(); i++) { CTxIn& txin = mergedTx.vin[i]; if(mapPrevOut.count(txin.prevout) == 0) { fComplete = false; continue; } const CScript& prevPubKey = mapPrevOut[txin.prevout]; txin.scriptSig.clear(); SignSignature(*wallet, prevPubKey, mergedTx, i, SIGHASH_ALL); txin.scriptSig = CombineSignatures(prevPubKey, mergedTx, i, txin.scriptSig, tx.vin[i].scriptSig); if(!VerifyScript(txin.scriptSig, prevPubKey, mergedTx, i, true, 0)) { fComplete = false; } } CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION); ssTx << mergedTx; ui->signedTransaction->setText(HexStr(ssTx.begin(), ssTx.end()).c_str()); if(fComplete) { ui->statusLabel->setText(tr("Transaction signature is complete")); ui->sendTransactionButton->setEnabled(true); } else { ui->statusLabel->setText(tr("Transaction is NOT completely signed")); ui->sendTransactionButton->setEnabled(false); } }
void MultisigDialog::on_signTransactionButton_clicked() { ui->signedTransaction->clear(); if(!model) return; CWallet *wallet = model->getWallet(); // Decode the raw transaction std::vector<unsigned char> txData(ParseHex(ui->transaction->text().toStdString())); CDataStream ss(txData, SER_NETWORK, PROTOCOL_VERSION); CTransaction tx; try { ss >> tx; } catch(std::exception &e) { return; } CTransaction mergedTx(tx); // Fetch previous transactions (inputs) // duplicated in rpcrawtransaction.cpp:389 CCoinsView viewDummy; CCoinsViewCache view(viewDummy); { LOCK(mempool.cs); CCoinsViewCache &viewChain = *pcoinsTip; CCoinsViewMemPool viewMempool(viewChain, mempool); view.SetBackend(viewMempool); // temporarily switch cache backend to db+mempool view BOOST_FOREACH(const CTxIn& txin, mergedTx.vin) { const uint256& prevHash = txin.prevout.hash; CCoins coins; view.GetCoins(prevHash, coins); // this is certainly allowed to fail } view.SetBackend(viewDummy); // switch back to avoid locking mempool for too long } // Add the redeem scripts to the wallet keystore for(int i = 0; i < ui->inputs->count(); i++) { MultisigInputEntry *entry = qobject_cast<MultisigInputEntry *>(ui->inputs->itemAt(i)->widget()); if(entry) { QString redeemScriptStr = entry->getRedeemScript(); if(redeemScriptStr.size() > 0) { std::vector<unsigned char> scriptData(ParseHex(redeemScriptStr.toStdString())); CScript redeemScript(scriptData.begin(), scriptData.end()); wallet->AddCScript(redeemScript); } } } WalletModel::UnlockContext ctx(model->requestUnlock()); if(!ctx.isValid()) return; // Sign what we can: // mostly like rpcrawtransaction:503 bool fComplete = true; // Sign what we can: for (unsigned int i = 0; i < mergedTx.vin.size(); i++) { CTxIn& txin = mergedTx.vin[i]; CCoins coins; if (!view.GetCoins(txin.prevout.hash, coins) || !coins.IsAvailable(txin.prevout.n)) { fComplete = false; continue; } const CScript& prevPubKey = coins.vout[txin.prevout.n].scriptPubKey; txin.scriptSig.clear(); SignSignature(*wallet, prevPubKey, mergedTx, i, SIGHASH_ALL); txin.scriptSig = CombineSignatures(prevPubKey, mergedTx, i, txin.scriptSig, tx.vin[i].scriptSig); if (!VerifyScript(txin.scriptSig, prevPubKey, mergedTx, i, SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_STRICTENC, 0)) fComplete = false; } CDataStream ssTx(SER_NETWORK, PROTOCOL_VERSION); ssTx << mergedTx; ui->signedTransaction->setText(HexStr(ssTx.begin(), ssTx.end()).c_str()); if(fComplete) { ui->statusLabel->setText(tr("Transaction signature is complete")); ui->sendTransactionButton->setEnabled(true); } else { ui->statusLabel->setText(tr("Transaction is NOT completely signed")); ui->sendTransactionButton->setEnabled(false); } }