Пример #1
0
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));
}
Пример #2
0
bool SysTestBase::GetKeyId(string const &addr,CKeyID &KeyId) {
	if (!CRegID::GetKeyID(addr, KeyId)) {
		KeyId=CKeyID(addr);
		if (KeyId.IsEmpty())
		return false;
	}
	return true;
};
Пример #3
0
bool CRegID::GetKeyID(const string & str,CKeyID &keyId)
{
	CRegID te(str);
	if(te.IsEmpty())
		return false;
	keyId = te.getKeyID(*pAccountViewTip);
	return !keyId.IsEmpty();
}
Пример #4
0
// Retrieves a public key for an address from the given CKeyStore
CPubKey AddrToPubKey(CKeyStore* const keystore, const std::string& addr_in)
{
    CTxDestination dest = DecodeDestination(addr_in);
    if (!IsValidDestination(dest)) {
        throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid address: " + addr_in);
    }
    CKeyID key = GetKeyForDestination(*keystore, dest);
    if (key.IsNull()) {
        throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("%s does not refer to a key", addr_in));
    }
    CPubKey vchPubKey;
    if (!keystore->GetPubKey(key, vchPubKey)) {
        throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("no full public key for address %s", addr_in));
    }
    if (!vchPubKey.IsFullyValid()) {
       throw JSONRPCError(RPC_INTERNAL_ERROR, "Wallet contains an invalid public key");
    }
    return vchPubKey;
}
Пример #5
0
Value getnewaddress(const Array& params, bool fHelp)
{
    if (fHelp || params.size() > 1)
        throw runtime_error(
            "getnewaddress  (\"IsMiner\")\n"
            "\nget a new address\n"
            "\nArguments:\n"
        	"1. \"IsMiner\"  (bool, optional)  private key Is used for miner if true will create tow key ,another for miner.\n"
           "\nExamples:\n"
            + HelpExampleCli("getnewaddress", "")
            + HelpExampleCli("getnewaddress", "true")
        );
	EnsureWalletIsUnlocked();

    CKey  mCkey;
    mCkey.MakeNewKey();

    CKey  Minter;
    bool IsForMiner = false;
	if (params.size() == 1) {
		RPCTypeCheck(params, list_of(bool_type));
		Minter.MakeNewKey();
		IsForMiner = params[0].get_bool();
	}

    CPubKey newKey = mCkey.GetPubKey();

    CKeyID keyID = newKey.GetKeyID();

	if (IsForMiner) {
		if (!pwalletMain->AddKey(mCkey, Minter))
			throw runtime_error("add key failed ");
	}
	else if (!pwalletMain->AddKey(mCkey)) {
		throw runtime_error("add key failed ");
	}
	Object obj;
	obj.push_back(Pair("addr", keyID.ToAddress()));
	obj.push_back(Pair("minerpubkey", IsForMiner?Minter.GetPubKey().ToString(): "no" ));
	return obj;
}
Пример #6
0
bool MessageModel::getAddressOrPubkey(QString &address, QString &pubkey) const
{
    CBitcoinAddress addressParsed(address.toStdString());

    if(addressParsed.IsValid()) {
        CKeyID  destinationAddress;
        CPubKey destinationKey;

        addressParsed.GetKeyID(destinationAddress);

        if (SecureMsgGetStoredKey(destinationAddress, destinationKey) != 0
            && SecureMsgGetLocalKey(destinationAddress, destinationKey) != 0) // test if it's a local key
            return false;

        address = destinationAddress.ToString().c_str();
        pubkey = EncodeBase58(destinationKey.Raw()).c_str();

        return true;
    }

    return false;
}
Пример #7
0
static bool GetKeyId(const CAccountViewCache &view, const vector<unsigned char> &ret,
		CKeyID &KeyId) {
	if (ret.size() == 6) {
		CRegID reg(ret);
		KeyId = reg.getKeyID(view);
	} else if (ret.size() == 34) {
		string addr(ret.begin(), ret.end());
		KeyId = CKeyID(addr);
	}else{
		return false;
	}
	if (KeyId.IsEmpty())
		return false;

	return true;
}
Пример #8
0
bool CBitcoinAddress::GetKeyID(CKeyID &keyID) const {
	uint160 id;

	if (vchVersion == Params().Base58Prefix(CBaseParams::PUBKEY_ADDRESS) && vchData.size() == 20) {
		memcpy(&id, &vchData[0], 20);
		keyID = CKeyID(id);
		return true;
	}

	vector<unsigned char> vid;
	vid.push_back(CBaseParams::ACC_ADDRESS);
	if (vchData.size() == 26 && vchVersion == vid) {
		memcpy(keyID.begin(), &vchData[0], 20);
		return true;
	}
	return false;
}
Пример #9
0
uint256 CreateBlockWithAppointedAddr(CKeyID const &keyID)
{
	if (SysCfg().NetworkID() == CBaseParams::REGTEST)
	{
//		unsigned int nTransactionsUpdatedLast = mempool.GetTransactionsUpdated();
		mempool.GetTransactionsUpdated();
		CBlockIndex* pindexPrev = chainActive.Tip();

		CAccountViewCache accview(*pAccountViewTip, true);
		CTransactionDBCache txCache(*pTxCacheTip, true);
		CScriptDBViewCache ScriptDbTemp(*pScriptDBTip, true);
		shared_ptr<CBlockTemplate> pblocktemplate(CreateNewBlock(accview,txCache,ScriptDbTemp));
		if (!pblocktemplate.get())
			return uint256();
		CBlock *pblock = &pblocktemplate.get()->block;

//		int nBlockSize = pblock->GetSerializeSize(SER_NETWORK, PROTOCOL_VERSION);
		pblock->GetSerializeSize(SER_NETWORK, PROTOCOL_VERSION);

//		int64_t nStart = GetTime();
		while (true) {
			pblock->SetTime(max(pindexPrev->GetMedianTimePast() + 1, GetAdjustedTime()));
			set<CKeyID> setCreateKey;
			setCreateKey.clear();
			setCreateKey.insert(keyID);
			if (CreatePosTx(pindexPrev, pblock,setCreateKey,accview,txCache,ScriptDbTemp)) {
				CheckWork(pblock, *pwalletMain);
//				int nBlockSize = pblock->GetSerializeSize(SER_NETWORK, PROTOCOL_VERSION);
			}
			if(setCreateKey.empty())
			{
				LogPrint("postx", "%s is not exist in the wallet\r\n",keyID.ToAddress());
				break;
			}
			::MilliSleep(1);
			if (pindexPrev != chainActive.Tip())
			{
				return chainActive.Tip()->GetBlockHash() ;
			}
		}
	}
	return uint256();
}
Пример #10
0
bool CheckProRegTx(const CTransaction& tx, const CBlockIndex* pindexPrev, CValidationState& state)
{
    if (tx.nType != TRANSACTION_PROVIDER_REGISTER) {
        return state.DoS(100, false, REJECT_INVALID, "bad-protx-type");
    }

    CProRegTx ptx;
    if (!GetTxPayload(tx, ptx)) {
        return state.DoS(100, false, REJECT_INVALID, "bad-protx-payload");
    }

    if (ptx.nVersion == 0 || ptx.nVersion > CProRegTx::CURRENT_VERSION) {
        return state.DoS(100, false, REJECT_INVALID, "bad-protx-version");
    }
    if (ptx.nType != 0) {
        return state.DoS(100, false, REJECT_INVALID, "bad-protx-type");
    }
    if (ptx.nMode != 0) {
        return state.DoS(100, false, REJECT_INVALID, "bad-protx-mode");
    }

    if (ptx.keyIDOwner.IsNull() || !ptx.pubKeyOperator.IsValid() || ptx.keyIDVoting.IsNull()) {
        return state.DoS(10, false, REJECT_INVALID, "bad-protx-key-null");
    }
    if (!ptx.scriptPayout.IsPayToPublicKeyHash() && !ptx.scriptPayout.IsPayToScriptHash()) {
        return state.DoS(10, false, REJECT_INVALID, "bad-protx-payee");
    }

    CTxDestination payoutDest;
    if (!ExtractDestination(ptx.scriptPayout, payoutDest)) {
        // should not happen as we checked script types before
        return state.DoS(10, false, REJECT_INVALID, "bad-protx-payee-dest");
    }
    // don't allow reuse of payout key for other keys (don't allow people to put the payee key onto an online server)
    if (payoutDest == CTxDestination(ptx.keyIDOwner) || payoutDest == CTxDestination(ptx.keyIDVoting)) {
        return state.DoS(10, false, REJECT_INVALID, "bad-protx-payee-reuse");
    }

    // It's allowed to set addr to 0, which will put the MN into PoSe-banned state and require a ProUpServTx to be issues later
    // If any of both is set, it must be valid however
    if (ptx.addr != CService() && !CheckService(tx.GetHash(), ptx, state)) {
        return false;
    }

    if (ptx.nOperatorReward > 10000) {
        return state.DoS(10, false, REJECT_INVALID, "bad-protx-operator-reward");
    }

    CTxDestination collateralTxDest;
    CKeyID keyForPayloadSig;
    COutPoint collateralOutpoint;

    if (!ptx.collateralOutpoint.hash.IsNull()) {
        Coin coin;
        if (!GetUTXOCoin(ptx.collateralOutpoint, coin) || coin.out.nValue != 1000 * COIN) {
            return state.DoS(10, false, REJECT_INVALID, "bad-protx-collateral");
        }

        if (!ExtractDestination(coin.out.scriptPubKey, collateralTxDest)) {
            return state.DoS(10, false, REJECT_INVALID, "bad-protx-collateral-dest");
        }

        // Extract key from collateral. This only works for P2PK and P2PKH collaterals and will fail for P2SH.
        // Issuer of this ProRegTx must prove ownership with this key by signing the ProRegTx
        if (!CBitcoinAddress(collateralTxDest).GetKeyID(keyForPayloadSig)) {
            return state.DoS(10, false, REJECT_INVALID, "bad-protx-collateral-pkh");
        }

        collateralOutpoint = ptx.collateralOutpoint;
    } else {
        if (ptx.collateralOutpoint.n >= tx.vout.size()) {
            return state.DoS(10, false, REJECT_INVALID, "bad-protx-collateral-index");
        }
        if (tx.vout[ptx.collateralOutpoint.n].nValue != 1000 * COIN) {
            return state.DoS(10, false, REJECT_INVALID, "bad-protx-collateral");
        }

        if (!ExtractDestination(tx.vout[ptx.collateralOutpoint.n].scriptPubKey, collateralTxDest)) {
            return state.DoS(10, false, REJECT_INVALID, "bad-protx-collateral-dest");
        }

        collateralOutpoint = COutPoint(tx.GetHash(), ptx.collateralOutpoint.n);
    }

    // don't allow reuse of collateral key for other keys (don't allow people to put the collateral key onto an online server)
    // this check applies to internal and external collateral, but internal collaterals are not necessarely a P2PKH
    if (collateralTxDest == CTxDestination(ptx.keyIDOwner) || collateralTxDest == CTxDestination(ptx.keyIDVoting)) {
        return state.DoS(10, false, REJECT_INVALID, "bad-protx-collateral-reuse");
    }

    if (pindexPrev) {
        auto mnList = deterministicMNManager->GetListForBlock(pindexPrev->GetBlockHash());

        // only allow reusing of addresses when it's for the same collateral (which replaces the old MN)
        if (mnList.HasUniqueProperty(ptx.addr) && mnList.GetUniquePropertyMN(ptx.addr)->collateralOutpoint != collateralOutpoint) {
            return state.DoS(10, false, REJECT_DUPLICATE, "bad-protx-dup-addr");
        }

        // never allow duplicate keys, even if this ProTx would replace an existing MN
        if (mnList.HasUniqueProperty(ptx.keyIDOwner) || mnList.HasUniqueProperty(ptx.pubKeyOperator)) {
            return state.DoS(10, false, REJECT_DUPLICATE, "bad-protx-dup-key");
        }

        if (!deterministicMNManager->IsDIP3Enforced(pindexPrev->nHeight)) {
            if (ptx.keyIDOwner != ptx.keyIDVoting) {
                return state.DoS(10, false, REJECT_INVALID, "bad-protx-key-not-same");
            }
        }
    }

    if (!CheckInputsHash(tx, ptx, state)) {
        return false;
    }

    if (!keyForPayloadSig.IsNull()) {
        // collateral is not part of this ProRegTx, so we must verify ownership of the collateral
        if (!CheckStringSig(ptx, keyForPayloadSig, state)) {
            return false;
        }
    } else {
        // collateral is part of this ProRegTx, so we know the collateral is owned by the issuer
        if (!ptx.vchSig.empty()) {
            return state.DoS(100, false, REJECT_INVALID, "bad-protx-sig");
        }
    }

    return true;
}
Пример #11
0
Value sendtoaddress(const Array& params, bool fHelp)
 {
	int size = params.size();
	if (fHelp || (!(size == 2 || size == 3)))
		throw runtime_error(
						"sendtoaddress (\"Dacrsaddress\") \"receive address\" \"amount\"\n"
						"\nSend an amount to a given address. The amount is a real and is rounded to the nearest 0.00000001\n"
						+ HelpRequiringPassphrase() + "\nArguments:\n"
						"1. \"Dacrsaddress\"  (string, optional) The Honghuo address to send to.\n"
						"2. receive address   (string, required) The Honghuo address to receive\n"
						"3.\"amount\"   (string, required) \n"
						"\nResult:\n"
						"\"transactionid\"  (string) The transaction id.\n"
						"\nExamples:\n"
						+ HelpExampleCli("sendtoaddress", "\"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\" 0.1")
						+ HelpExampleCli("sendtoaddress",
						"\"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\" 0.1 \"donation\" \"seans outpost\"")
						+ HelpExampleRpc("sendtoaddress",
						"\"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\", 0.1, \"donation\", \"seans outpost\""
						+ HelpExampleCli("sendtoaddress", "\"0-6\" 10 ")
						+ HelpExampleCli("sendtoaddress", "\"00000000000000000005\" 10 ")
						+ HelpExampleCli("sendtoaddress", "\"0-6\" \"0-5\" 10 ")
						+ HelpExampleCli("sendtoaddress", "\"00000000000000000005\" \"0-6\"10 ")));

	EnsureWalletIsUnlocked();
	CKeyID sendKeyId;
	CKeyID RevKeyId;

	auto GetKeyId = [](string const &addr,CKeyID &KeyId) {
		if (!CRegID::GetKeyID(addr, KeyId)) {
			KeyId=CKeyID(addr);
			if (KeyId.IsEmpty())
			return false;
		}
		return true;
	};

	// Amount
	int64_t nAmount = 0;
	CRegID sendreg;
	//// from address to addreww
	if (size == 3) {

		if (!GetKeyId(params[0].get_str(), sendKeyId)) {
			throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "FROM Invalid  address");
		}
		if (!GetKeyId(params[1].get_str(), RevKeyId)) {
			throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "to Invalid  address");
		}

		nAmount = AmountToRawValue(params[2]);
		if (pAccountViewTip->GetRawBalance(sendKeyId) <= nAmount + SysCfg().GetTxFee()) {
			throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "FROM address not enough coins");
		}
	} else {
		if (!GetKeyId(params[0].get_str(), RevKeyId)) {
			throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "to address Invalid  ");
		}

		nAmount = AmountToRawValue(params[1]);
		set<CKeyID> sKeyid;
		sKeyid.clear();
		pwalletMain->GetKeys(sKeyid); //get addrs
		if(sKeyid.empty())
		{
			throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "No Key In wallet \n");
		}
		for (auto &te : sKeyid) {
			if (pAccountViewTip->GetRawBalance(te) >= nAmount + SysCfg().GetTxFee()) {
				if (pAccountViewTip->GetRegId(CUserID(te), sendreg)) {
					sendKeyId = te;
					break;
				}
			}
		}

		if (sendKeyId.IsNull()) {
			throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "not find enough moeny account ");
		}
	}

	CRegID revreg;
	CUserID rev;

	if (!pAccountViewTip->GetRegId(CUserID(sendKeyId), sendreg)) {
		throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid  address");
	}

	if (pAccountViewTip->GetRegId(CUserID(RevKeyId), revreg)) {
		rev = revreg;
	} else {
		rev = RevKeyId;
	}

	CTransaction tx(sendreg, rev, SysCfg().GetTxFee(), nAmount, chainActive.Height());

	if (!pwalletMain->Sign(sendKeyId, tx.SignatureHash(), tx.signature)) {
		throw JSONRPCError(RPC_INVALID_PARAMETER,  "Sign failed");
	}

	std::tuple<bool,string> ret = pwalletMain->CommitTransaction((CBaseTransaction *) &tx);
	if(!std::get<0>(ret))
		 throw JSONRPCError(RPC_INVALID_PARAMETER,  std::get<1>(ret));

	Object obj;
	obj.push_back(Pair("hash" , std::get<1>(ret)));
	return obj;
}
Пример #12
0
Value sendtoaddresswithfee(const Array& params, bool fHelp)
 {
	int size = params.size();
	if (fHelp || (!(size == 3 || size == 4)))
		throw runtime_error(
						"sendtoaddresswithfee (\"sendaddress\") \"recvaddress\" \"amount\" (fee)\n"
						"\nSend an amount to a given address with fee. The amount is a real and is rounded to the nearest 0.00000001\n"
						"\nArguments:\n"
						"1. \"sendaddress\"  (string, optional) The Honghuo address to send to.\n"
						"2. \"recvaddress\" (string, required) The Honghuo address to receive.\n"
						"3.\"amount\"   (string,required) \n"
						"4.\"fee\"      (string,required) \n"
						"\nResult:\n"
						"\"transactionid\"  (string) The transaction id.\n"
						"\nExamples:\n"
						+ HelpExampleCli("sendtoaddresswithfee", "\"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\" 10000000 1000")
						+ HelpExampleCli("sendtoaddresswithfee",
						"\"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\" 0.1 \"donation\" \"seans outpost\"")
						+ HelpExampleRpc("sendtoaddresswithfee",
						"\"1M72Sfpbz1BPpXFHz9m3CdqATR44Jvaydd\", 0.1, \"donation\", \"seans outpost\""
						+ HelpExampleCli("sendtoaddresswithfee", "\"0-6\" 10 ")
						+ HelpExampleCli("sendtoaddresswithfee", "\"00000000000000000005\" 10 ")
						+ HelpExampleCli("sendtoaddresswithfee", "\"0-6\" \"0-5\" 10 ")
						+ HelpExampleCli("sendtoaddresswithfee", "\"00000000000000000005\" \"0-6\"10 ")));

	EnsureWalletIsUnlocked();
	CKeyID sendKeyId;
	CKeyID RevKeyId;

	auto GetKeyId = [](string const &addr,CKeyID &KeyId) {
		if (!CRegID::GetKeyID(addr, KeyId)) {
			KeyId=CKeyID(addr);
			if (KeyId.IsEmpty())
			return false;
		}
		return true;
	};

	// Amount
	int64_t nAmount = 0;
	int64_t nFee = 0;
	//// from address to addreww
	if (size == 4) {

		if (!GetKeyId(params[0].get_str(), sendKeyId)) {
			throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "FROM Invalid  address");
		}
		if (!GetKeyId(params[1].get_str(), RevKeyId)) {
			throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "to Invalid  address");
		}

		nAmount = AmountToRawValue(params[2]);
		if (pAccountViewTip->GetRawBalance(sendKeyId) <= nAmount + SysCfg().GetTxFee()) {
			throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "FROM address not enough coins");
		}
		nFee = AmountToRawValue(params[3]);
	} else {
		if (!GetKeyId(params[0].get_str(), RevKeyId)) {
			throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "to address Invalid  ");
		}

		nAmount = AmountToRawValue(params[1]);
		set<CKeyID> sKeyid;
		sKeyid.clear();
		pwalletMain->GetKeys(sKeyid);
		if (sKeyid.empty()) //get addrs
		{
			throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "No Key In wallet \n");
		}
		nFee = AmountToRawValue(params[2]);
		for (auto &te : sKeyid) {
			if (pAccountViewTip->GetRawBalance(te) >= nAmount + SysCfg().GetTxFee()) {
				sendKeyId = te;
				break;
			}
		}

		if (sendKeyId.IsNull()) {
			throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "not find enough moeny account ");
		}
	}

	auto SendMoney = [&](const CRegID &send, const CUserID &rsv, int64_t nValue, int64_t nFee) {
		CTransaction tx;
		tx.srcRegId = send;
		tx.desUserId = rsv;
		tx.llValues = nValue;
		if (0 == nFee) {
			tx.llFees = SysCfg().GetTxFee();
		} else
		tx.llFees = nFee;
		tx.nValidHeight = chainActive.Tip()->nHeight;

		CKeyID keID;
		if(!pAccountViewTip->GetKeyId(send,keID)) {
			return std::make_tuple (false,"key or keID failed");
		}

		if (!pwalletMain->Sign(keID,tx.SignatureHash(), tx.signature)) {
			return std::make_tuple (false,"Sign failed");
		}
		std::tuple<bool,string> ret = pwalletMain->CommitTransaction((CBaseTransaction *) &tx);
		bool falg = std::get<0>(ret);
		string te = std::get<1>(ret);
		if(falg == true)
		te = tx.GetHash().ToString();
		return std::make_tuple (falg,te.c_str());
	};


	CRegID sendreg;
	CRegID revreg;


	if (!pAccountViewTip->GetRegId(CUserID(sendKeyId), sendreg)) {
		throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid  address");
	}

	std::tuple<bool,string> ret;
	if (pAccountViewTip->GetRegId(CUserID(RevKeyId), revreg)) {
		ret = SendMoney(sendreg, revreg, nAmount, nFee);
	} else {


		ret = SendMoney(sendreg, CUserID(RevKeyId), nAmount, nFee);
	}

	Object obj;
	obj.push_back(Pair(std::get<0>(ret) ? "hash" : "error code", std::get<1>(ret)));
	return obj;
}