Пример #1
0
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);
}
Пример #2
0
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;
}
Пример #3
0
    // /////////////////////////////////////////////////////////////////
    //
    // /////////////////////////////////////////////////////////////////
    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);
    }
Пример #4
0
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();
}
Пример #5
0
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);
}
Пример #6
0
/*
 * 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;
}
Пример #7
0
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);
    }
}
Пример #8
0
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);
	}
}