}
contains(USE_LEVELDB, 1) {
- message(Building with LevelDB)
+ message(Building with LevelDB transaction index)
DEFINES += USE_LEVELDB
INCLUDEPATH += src/leveldb/include src/leveldb/helpers
# Gross ugly hack that depends on qmake internals, unfortunately there is no other way to do it.
QMAKE_CLEAN += $$PWD/src/leveldb/libleveldb.a; cd $$PWD/src/leveldb ; $(MAKE) clean
} else {
- message(Building without LevelDB)
+ message(Building with Berkeley DB transaction index)
SOURCES += src/txdb-bdb.cpp
}
}
}
-system($$QMAKE_LRELEASE -silent $$_PRO_FILE_)
+system($$QMAKE_LRELEASE -silent $$PWD/src/qt/locale/translations.pro)
{ "getaccount", &getaccount, false, false },
{ "getaddressesbyaccount", &getaddressesbyaccount, true, false },
{ "sendtoaddress", &sendtoaddress, false, false },
+ { "mergecoins", &mergecoins, false, false },
{ "getreceivedbyaddress", &getreceivedbyaddress, false, false },
{ "getreceivedbyaccount", &getreceivedbyaccount, false, false },
{ "listreceivedbyaddress", &listreceivedbyaddress, false, false },
//
if (strMethod == "stop" && n > 0) ConvertTo<bool>(params[0]);
if (strMethod == "sendtoaddress" && n > 1) ConvertTo<double>(params[1]);
+ if (strMethod == "mergecoins" && n > 0) ConvertTo<double>(params[0]);
+ if (strMethod == "mergecoins" && n > 1) ConvertTo<double>(params[1]);
+ if (strMethod == "mergecoins" && n > 2) ConvertTo<double>(params[2]);
if (strMethod == "settxfee" && n > 0) ConvertTo<double>(params[0]);
if (strMethod == "getreceivedbyaddress" && n > 1) ConvertTo<boost::int64_t>(params[1]);
if (strMethod == "getreceivedbyaccount" && n > 1) ConvertTo<boost::int64_t>(params[1]);
extern json_spirit::Value repairwallet(const json_spirit::Array& params, bool fHelp);
extern json_spirit::Value resendtx(const json_spirit::Array& params, bool fHelp);
extern json_spirit::Value makekeypair(const json_spirit::Array& params, bool fHelp);
+extern json_spirit::Value mergecoins(const json_spirit::Array& params, bool fHelp);
extern json_spirit::Value getrawtransaction(const json_spirit::Array& params, bool fHelp); // in rcprawtransaction.cpp
extern json_spirit::Value listunspent(const json_spirit::Array& params, bool fHelp);
DEFS += $(addprefix -I,$(CURDIR)/leveldb/helpers)
OBJS += obj/txdb-leveldb.o
leveldb/libleveldb.a:
-@echo "Building LevelDB ..."; cd leveldb; make libleveldb.a libmemenv.a; cd ..;
+ @echo "Building LevelDB ..."; cd leveldb; make libleveldb.a libmemenv.a; cd ..;
obj/txdb-leveldb.o: leveldb/libleveldb.a
endif
ifneq (${USE_LEVELDB}, 1)
DEFS += -I"$(CURDIR)/leveldb/helpers"
OBJS += obj/txdb-leveldb.o
leveldb/libleveldb.a:
-@echo "Building LevelDB ..." && cd leveldb && CC=$(CC) CXX=$(CXX) TARGET_OS=OS_WINDOWS_CROSSCOMPILE CXXFLAGS="-I$(INCLUDEPATHS)" LDFLAGS="-L$(LIBPATHS)" $(MAKE) libleveldb.a libmemenv.a && $(RANLIB) libleveldb.a && $(RANLIB) libmemenv.a && cd ..
+ @echo "Building LevelDB ..." && cd leveldb && CC=$(CC) CXX=$(CXX) TARGET_OS=OS_WINDOWS_CROSSCOMPILE CXXFLAGS="-I$(INCLUDEPATHS)" LDFLAGS="-L$(LIBPATHS)" $(MAKE) libleveldb.a libmemenv.a && $(RANLIB) libleveldb.a && $(RANLIB) libmemenv.a && cd ..
obj/txdb-leveldb.o: leveldb/libleveldb.a
else
OBJS += obj/txdb-bdb.o
DEFS += $(addprefix -I,$(CURDIR)/leveldb/helpers)
OBJS += obj/txdb-leveldb.o
leveldb/libleveldb.a:
-cd leveldb; make; cd ..
+ cd leveldb; make; cd ..
obj/txdb-leveldb.o: leveldb/libleveldb.lib
else
OBJS += obj/txdb-bdb.o
DEFS += $(addprefix -I,$(CURDIR)/leveldb/helpers)
OBJS += obj/txdb-leveldb.o
leveldb/libleveldb.a:
-@echo "Building LevelDB ..."; cd leveldb; make; cd ..
+ @echo "Building LevelDB ..."; cd leveldb; make; cd ..
obj/txdb-leveldb.o: leveldb/libleveldb.a
else
OBJS += obj/txdb-bdb.o
DEFS += $(addprefix -I,$(CURDIR)/leveldb/helpers)
OBJS += obj/txdb-leveldb.o
leveldb/libleveldb.a:
-@echo "Building LevelDB ..."; cd leveldb; make libleveldb.a libmemenv.a; cd ..;
+ @echo "Building LevelDB ..."; cd leveldb; make libleveldb.a libmemenv.a; cd ..;
obj/txdb-leveldb.o: leveldb/libleveldb.a
endif
ifneq (${USE_LEVELDB}, 1)
--- /dev/null
+CODECFORTR = UTF-8
+
+# for lrelease/lupdate
+# also add new translations to src/qt/bitcoin.qrc under translations/
+TRANSLATIONS = $$files(bitcoin_*.ts)
+
+isEmpty(QM_DIR):QM_DIR = $$PWD/src/qt/locale
+# automatically build translations, so they can be included in resource file
+TSQM.name = lrelease ${QMAKE_FILE_IN}
+TSQM.input = TRANSLATIONS
+TSQM.output = $$QM_DIR/${QMAKE_FILE_BASE}.qm
+TSQM.commands = $$QMAKE_LRELEASE ${QMAKE_FILE_IN} -qm ${QMAKE_FILE_OUT}
+TSQM.CONFIG = no_link
+QMAKE_EXTRA_COMPILERS += TSQM
+
+windows:DEFINES += WIN32
+windows:RC_FILE = $$PWD/src/qt/res/bitcoin-qt.rc
return ret;
}
+Value mergecoins(const Array& params, bool fHelp)
+{
+ if (fHelp || params.size() != 3)
+ throw runtime_error(
+ "mergecoins <amount> <outputvalue> <maxvalue>\n"
+ "<amount> is resulting inputs sum\n"
+ "<outputvalue> is resulting value of inputs which will be created\n"
+ "<maxvalue> is maximum value of inputs which are used in join process\n"
+ "All values are real and and rounded to the nearest " + FormatMoney(MIN_TXOUT_AMOUNT)
+ + HelpRequiringPassphrase());
+
+ if (pwalletMain->IsLocked())
+ throw JSONRPCError(RPC_WALLET_UNLOCK_NEEDED, "Error: Please enter the wallet passphrase with walletpassphrase first.");
+
+ // Amount
+ int64 nAmount = AmountFromValue(params[0]);
+
+ // Amount
+ int64 nOutputValue = AmountFromValue(params[1]);
+
+ // Amount
+ int64 nMaxValue = AmountFromValue(params[2]);
+
+ if (nAmount < MIN_TXOUT_AMOUNT)
+ throw JSONRPCError(-101, "Send amount too small");
+
+ if (nOutputValue < MIN_TXOUT_AMOUNT)
+ throw JSONRPCError(-101, "Output value too small");
+
+ if (nMaxValue < MIN_TXOUT_AMOUNT)
+ throw JSONRPCError(-101, "Max value too small");
+
+ if (nOutputValue < nMaxValue)
+ throw JSONRPCError(-101, "Output value is lower than max value");
+
+
+ list<uint256> listMerged;
+ if (!pwalletMain->MergeCoins(nAmount, nMaxValue, nOutputValue, listMerged))
+ return Value::null;
+
+ Array mergedHashes;
+ BOOST_FOREACH(const uint256 txHash, listMerged)
+ mergedHashes.push_back(txHash.GetHex());
+
+ return mergedHashes;
+}
+
Value sendtoaddress(const Array& params, bool fHelp)
{
if (fHelp || params.size() < 2 || params.size() > 4)
return true;
}
+bool CWallet::MergeCoins(const int64& nAmount, const int64& nMaxValue, const int64& nOutputValue, list<uint256>& listMerged)
+{
+ int64 nBalance = GetBalance();
+
+ if (nAmount > nBalance)
+ return false;
+
+ listMerged.clear();
+ int64 nValueIn = 0;
+ set<pair<const CWalletTx*,unsigned int> > setCoins;
+
+ // Simple coins selection - no randomization
+ if (!SelectCoinsSimple(nAmount, GetTime(), 1, setCoins, nValueIn))
+ return false;
+
+ if (setCoins.empty())
+ return false;
+
+ CWalletTx wtxNew;
+ vector<const CWalletTx*> vwtxPrev;
+
+ // Reserve a new key pair from key pool
+ CReserveKey reservekey(this);
+ CPubKey vchPubKey = reservekey.GetReservedKey();
+
+ // Output script
+ CScript scriptOutput;
+ scriptOutput.SetDestination(vchPubKey.GetID());
+
+ // Insert output
+ wtxNew.vout.push_back(CTxOut(0, scriptOutput));
+
+ double dWeight = 0;
+
+ BOOST_FOREACH(PAIRTYPE(const CWalletTx*, unsigned int) pcoin, setCoins)
+ {
+ int64 nCredit = pcoin.first->vout[pcoin.second].nValue;
+
+ // Ignore coin if credit is too high
+ if (nCredit >= nMaxValue)
+ continue;
+
+ // Ignore immature coins
+ if (pcoin.first->GetBlocksToMaturity() > 0)
+ continue;
+
+ // Add current coin to inputs list and add its credit to transaction output
+ wtxNew.vin.push_back(CTxIn(pcoin.first->GetHash(), pcoin.second));
+ wtxNew.vout[0].nValue += nCredit;
+ vwtxPrev.push_back(pcoin.first);
+
+ for (unsigned int i = 0; i < wtxNew.vin.size(); i++) {
+ const CWalletTx *txin = vwtxPrev[i];
+
+ // Sign scripts to get actual transaction size for fee calculation
+ if (!SignSignature(*this, *txin, wtxNew, i))
+ return false;
+ }
+
+ int64 nBytes = ::GetSerializeSize(*(CTransaction*)&wtxNew, SER_NETWORK, PROTOCOL_VERSION);
+ dWeight += (double)nCredit * pcoin.first->GetDepthInMainChain();
+
+ double dFinalPriority = dWeight /= nBytes;
+ bool fAllowFree = CTransaction::AllowFree(dFinalPriority);
+
+ // Get actual transaction fee according to its size and priority
+ int64 nMinFee = wtxNew.GetMinFee(1, fAllowFree, GMF_SEND, nBytes);
+
+ // Prepare transaction for commit if sum is enough ot its size is too big
+ if (nBytes >= MAX_BLOCK_SIZE_GEN/6 || (wtxNew.vout[0].nValue >= nOutputValue && wtxNew.vout.size() > 1))
+ {
+ wtxNew.vout[0].nValue -= nMinFee; // Set actual fee
+
+ for (unsigned int i = 0; i < wtxNew.vin.size(); i++) {
+ const CWalletTx *txin = vwtxPrev[i];
+
+ // Sign all scripts again
+ if (!SignSignature(*this, *txin, wtxNew, i))
+ return false;
+ }
+
+ // Try to commit, return false on failure
+ if (!CommitTransaction(wtxNew, reservekey))
+ return false;
+
+ listMerged.push_back(wtxNew.GetHash()); // Add to hashes list
+
+ dWeight = 0; // Reset all temporary values
+ vwtxPrev.clear();
+ wtxNew.SetNull();
+ wtxNew.vout.push_back(CTxOut(0, scriptOutput));
+ }
+ }
+
+ // Create transactions if there are some unhandled coins left
+ if (wtxNew.vout[0].nValue > 0) {
+ int64 nBytes = ::GetSerializeSize(*(CTransaction*)&wtxNew, SER_NETWORK, PROTOCOL_VERSION);
+
+ double dFinalPriority = dWeight /= nBytes;
+ bool fAllowFree = CTransaction::AllowFree(dFinalPriority);
+
+ // Get actual transaction fee according to its size and priority
+ int64 nMinFee = wtxNew.GetMinFee(1, fAllowFree, GMF_SEND, nBytes);
+
+ wtxNew.vout[0].nValue -= nMinFee; // Set actual fee
+
+ if (wtxNew.vout[0].nValue <= 0)
+ return false;
+
+ for (unsigned int i = 0; i < wtxNew.vin.size(); i++) {
+ const CWalletTx *txin = vwtxPrev[i];
+
+ // Sign all scripts again
+ if (!SignSignature(*this, *txin, wtxNew, i))
+ return false;
+ }
+
+ // Try to commit, return false on failure
+ if (!CommitTransaction(wtxNew, reservekey))
+ return false;
+
+ listMerged.push_back(wtxNew.GetHash()); // Add to hashes list
+ }
+
+ return true;
+}
+
+
bool CWallet::CreateCoinStake(const CKeyStore& keystore, unsigned int nBits, int64 nSearchInterval, CTransaction& txNew, CKey& key)
{
// The following combine threshold is important to security
bool GetStakeWeight(const CKeyStore& keystore, uint64& nMinWeight, uint64& nMaxWeight, uint64& nWeight);
void GetStakeWeightFromValue(const int64& nTime, const int64& nValue, uint64& nWeight);
bool CreateCoinStake(const CKeyStore& keystore, unsigned int nBits, int64 nSearchInterval, CTransaction& txNew, CKey& key);
+ bool MergeCoins(const int64& nAmount, const int64& nMaxValue, const int64& nOutputValue, list<uint256>& listMerged);
std::string SendMoney(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, bool fAskFee=false);
std::string SendMoneyToDestination(const CTxDestination &address, int64 nValue, CWalletTx& wtxNew, bool fAskFee=false);