src/coincontrol.h \
src/sync.h \
src/util.h \
+ src/timestamps.h \
src/uint256.h \
src/kernel.h \
src/scrypt.h \
void ThreadFlushWalletDB(void* parg);
bool BackupWallet(const CWallet& wallet, const std::string& strDest);
-
+bool DumpWallet(CWallet* pwallet, const std::string& strDest);
+bool ImportWallet(CWallet* pwallet, const std::string& strLocation);
class CDBEnv
{
#include "ui_interface.h"
#include "checkpoints.h"
#include "zerocoin/ZeroTest.h"
+#include <boost/format.hpp>
#include <boost/filesystem.hpp>
#include <boost/filesystem/fstream.hpp>
#include <boost/filesystem/convenience.hpp>
" -conf=<file> " + _("Specify configuration file (default: novacoin.conf)") + "\n" +
" -pid=<file> " + _("Specify pid file (default: novacoind.pid)") + "\n" +
" -datadir=<dir> " + _("Specify data directory") + "\n" +
- " -wallet=<dir> " + _("Specify wallet file (within data directory)") + "\n" +
+ " -wallet=<file> " + _("Specify wallet file (within data directory)") + "\n" +
" -dbcache=<n> " + _("Set database cache size in megabytes (default: 25)") + "\n" +
" -dblogsize=<n> " + _("Set database disk log size in megabytes (default: 100)") + "\n" +
" -timeout=<n> " + _("Specify connection timeout in milliseconds (default: 5000)") + "\n" +
#endif
" -detachdb " + _("Detach block and address databases. Increases shutdown time (default: 0)") + "\n" +
" -paytxfee=<amt> " + _("Fee per KB to add to transactions you send") + "\n" +
- " -mininput=<amt> " + _("When creating transactions, ignore inputs with value less than this (default: 0.01)") + "\n" +
+ " -mininput=<amt> " + str(boost::format(_("When creating transactions, ignore inputs with value less than this (default: %s)")) % FormatMoney(MIN_TXOUT_AMOUNT)) + "\n" +
#ifdef QT_GUI
" -server " + _("Accept command line and JSON-RPC commands") + "\n" +
#endif
extern int nStakeMaxAge;
extern int nStakeTargetSpacing;
+// Protocol switch time for fixed kernel modifier interval
+unsigned int nModifierSwitchTime = 1413763200; // Mon, 20 Oct 2014 00:00:00 GMT
+unsigned int nModifierTestSwitchTime = 1397520000; // Tue, 15 Apr 2014 00:00:00 GMT
+
+// Note: user must upgrade before the protocol switch deadline, otherwise it's required to
+// re-download the blockchain. The timestamp of upgrade is recorded in the blockchain
+// database.
+unsigned int nModifierUpgradeTime = 0;
+
typedef std::map<int, unsigned int> MapModifierCheckpoints;
// Hard checkpoints of stake modifiers to ensure they are deterministic
( 0, 0x0e00670bu )
;
+// Whether the given block is subject to new modifier protocol
+bool IsFixedModifierInterval(unsigned int nTimeBlock)
+{
+ return (nTimeBlock >= (fTestNet? nModifierTestSwitchTime : nModifierSwitchTime));
+}
+
// Get time weight
int64 GetWeight(int64 nIntervalBeginning, int64 nIntervalEnd)
{
// block. This is to make it difficult for an attacker to gain control of
// additional bits in the stake modifier, even after generating a chain of
// blocks.
-bool ComputeNextStakeModifier(const CBlockIndex* pindexPrev, uint64& nStakeModifier, bool& fGeneratedStakeModifier)
+bool ComputeNextStakeModifier(const CBlockIndex* pindexCurrent, uint64& nStakeModifier, bool& fGeneratedStakeModifier)
{
nStakeModifier = 0;
fGeneratedStakeModifier = false;
+ const CBlockIndex* pindexPrev = pindexCurrent->pprev;
if (!pindexPrev)
{
fGeneratedStakeModifier = true;
return true; // genesis block's modifier is 0
}
+
// First find current stake modifier and its generation block time
// if it's not old enough, return the same stake modifier
int64 nModifierTime = 0;
return error("ComputeNextStakeModifier: unable to get last modifier");
if (fDebug)
{
- printf("ComputeNextStakeModifier: prev modifier=0x%016"PRI64x" time=%s\n", nStakeModifier, DateTimeStrFormat(nModifierTime).c_str());
+ printf("ComputeNextStakeModifier: prev modifier=0x%016"PRI64x" time=%s epoch=%u\n", nStakeModifier, DateTimeStrFormat(nModifierTime).c_str(), (unsigned int)nModifierTime);
}
if (nModifierTime / nModifierInterval >= pindexPrev->GetBlockTime() / nModifierInterval)
+ {
+ if (fDebug)
+ {
+ printf("ComputeNextStakeModifier: no new interval keep current modifier: pindexPrev nHeight=%d nTime=%u\n", pindexPrev->nHeight, (unsigned int)pindexPrev->GetBlockTime());
+ }
return true;
+ }
+ if (nModifierTime / nModifierInterval >= pindexCurrent->GetBlockTime() / nModifierInterval)
+ {
+ // fixed interval protocol requires current block timestamp also be in a different modifier interval
+ if (IsFixedModifierInterval(pindexCurrent->nTime))
+ {
+ if (fDebug)
+ {
+ printf("ComputeNextStakeModifier: no new interval keep current modifier: pindexCurrent nHeight=%d nTime=%u\n", pindexCurrent->nHeight, (unsigned int)pindexCurrent->GetBlockTime());
+ }
+ return true;
+ }
+ else
+ {
+ if (fDebug)
+ {
+ printf("ComputeNextStakeModifier: old modifier at block %s not meeting fixed modifier interval: pindexCurrent nHeight=%d nTime=%u\n", pindexCurrent->GetBlockHash().ToString().c_str(), pindexCurrent->nHeight, (unsigned int)pindexCurrent->GetBlockTime());
+ }
+ }
+ }
// Sort candidate blocks by timestamp
vector<pair<int64, uint256> > vSortedByTimestamp;
return true;
}
-// Check whether the coinstake timestamp meets protocol
-bool CheckCoinStakeTimestamp(int64 nTimeBlock, int64 nTimeTx)
-{
- // v0.3 protocol
- return (nTimeBlock == nTimeTx);
-}
-
// Get stake modifier checksum
unsigned int GetStakeModifierChecksum(const CBlockIndex* pindex)
{
#include "main.h"
+// ChainDB upgrade time
+extern unsigned int nModifierUpgradeTime;
+
// MODIFIER_INTERVAL: time to elapse before new modifier is computed
extern unsigned int nModifierInterval;
// ratio of group interval length between the last group and the first group
static const int MODIFIER_INTERVAL_RATIO = 3;
+// Whether the given block is subject to new modifier protocol
+bool IsFixedModifierInterval(unsigned int nTimeBlock);
+
// Compute the hash modifier for proof-of-stake
-bool ComputeNextStakeModifier(const CBlockIndex* pindexPrev, uint64& nStakeModifier, bool& fGeneratedStakeModifier);
+bool ComputeNextStakeModifier(const CBlockIndex* pindexCurrent, uint64& nStakeModifier, bool& fGeneratedStakeModifier);
// Check whether stake kernel meets hash target
// Sets hashProofOfStake on success return
// Sets hashProofOfStake on success return
bool CheckProofOfStake(const CTransaction& tx, unsigned int nBits, uint256& hashProofOfStake, uint256& targetProofOfStake);
-// Check whether the coinstake timestamp meets protocol
-bool CheckCoinStakeTimestamp(int64 nTimeBlock, int64 nTimeTx);
-
// Get stake modifier checksum
unsigned int GetStakeModifierChecksum(const CBlockIndex* pindex);
#include "keystore.h"
#include "script.h"
+extern bool fWalletUnlockMintOnly;
+
bool CKeyStore::GetPubKey(const CKeyID &address, CPubKey &vchPubKeyOut) const
{
CKey key;
{
LOCK(cs_KeyStore);
vMasterKey.clear();
+ fWalletUnlockMintOnly = false;
}
NotifyStatusChanged(this);
if (nVersion > CTransaction::CURRENT_VERSION)
return false;
+ unsigned int nDataOut = 0;
+ txnouttype whichType;
BOOST_FOREACH(const CTxIn& txin, vin)
{
// Biggest 'standard' txin is a 3-signature 3-of-3 CHECKMULTISIG
}
}
BOOST_FOREACH(const CTxOut& txout, vout) {
- if (!::IsStandard(txout.scriptPubKey))
- return false;
- if (txout.nValue == 0)
- return false;
- if (fEnforceCanonical && !txout.scriptPubKey.HasCanonicalPushes()) {
+ if (!::IsStandard(txout.scriptPubKey, whichType)) {
return false;
}
+ if (whichType == TX_NULL_DATA)
+ nDataOut++;
+ else {
+ if (txout.nValue == 0) {
+ return false;
+ }
+ if (fEnforceCanonical && !txout.scriptPubKey.HasCanonicalPushes()) {
+ return false;
+ }
+ }
+ }
+
+ // only one OP_RETURN txout is permitted
+ if (nDataOut > 1) {
+ return false;
}
+
return true;
}
if (txout.IsEmpty() && !IsCoinBase() && !IsCoinStake())
return DoS(100, error("CTransaction::CheckTransaction() : txout empty for user transaction"));
- // NovaCoin: enforce minimum output amount for user transactions until 1 May 2014 04:00:00 GMT
- if (!fTestNet && !IsCoinBase() && !txout.IsEmpty() && nTime < OUTPUT_SWITCH_TIME && txout.nValue < MIN_TXOUT_AMOUNT)
- return DoS(100, error("CTransaction::CheckTransaction() : txout.nValue below minimum"));
-
if (txout.nValue < 0)
return DoS(100, error("CTransaction::CheckTransaction() : txout.nValue is negative"));
if (txout.nValue > MAX_MONEY)
return true;
}
-int64 CTransaction::GetMinFee(unsigned int nBlockSize, bool fAllowFree,
- enum GetMinFee_mode mode, unsigned int nBytes) const
+int64 CTransaction::GetMinFee(unsigned int nBlockSize, bool fAllowFree, enum GetMinFee_mode mode, unsigned int nBytes) const
{
- // Base fee is either MIN_TX_FEE or MIN_RELAY_TX_FEE
- int64 nBaseFee = (mode == GMF_RELAY) ? MIN_RELAY_TX_FEE : MIN_TX_FEE;
+ // Use new fees approach if we are on test network or
+ // switch date has been reached
+ bool fNewApproach = fTestNet || nTime > FEE_SWITCH_TIME;
+
+ int64 nMinTxFee = MIN_TX_FEE, nMinRelayTxFee = MIN_RELAY_TX_FEE;
+
+ if(!fNewApproach || IsCoinStake())
+ {
+ // Enforce 0.01 as minimum fee for old approach or coinstake
+ nMinTxFee = CENT;
+ nMinRelayTxFee = CENT;
+ }
+
+ // Base fee is either nMinTxFee or nMinRelayTxFee
+ int64 nBaseFee = (mode == GMF_RELAY) ? nMinRelayTxFee : nMinTxFee;
unsigned int nNewBlockSize = nBlockSize + nBytes;
int64 nMinFee = (1 + (int64)nBytes / 1000) * nBaseFee;
- // To limit dust spam, require MIN_TX_FEE/MIN_RELAY_TX_FEE if any output is less than 0.01
- if (nMinFee < nBaseFee)
+ if (fNewApproach)
{
+ if (fAllowFree)
+ {
+ if (nBlockSize == 1)
+ {
+ // Transactions under 1K are free
+ if (nBytes < 1000)
+ nMinFee = 0;
+ }
+ else
+ {
+ // Free transaction area
+ if (nNewBlockSize < 27000)
+ nMinFee = 0;
+ }
+ }
+
+ // To limit dust spam, require additional MIN_TX_FEE/MIN_RELAY_TX_FEE for
+ // each non empty output which is less than 0.01
+ //
+ // It's safe to ignore empty outputs here, because these inputs are allowed
+ // only for coinbase and coinstake transactions.
+ BOOST_FOREACH(const CTxOut& txout, vout)
+ if (txout.nValue < CENT && !txout.IsEmpty())
+ nMinFee += nBaseFee;
+ }
+ else if (nMinFee < nBaseFee)
+ {
+ // To limit dust spam, require MIN_TX_FEE/MIN_RELAY_TX_FEE if
+ // any output is less than 0.01
BOOST_FOREACH(const CTxOut& txout, vout)
if (txout.nValue < CENT)
nMinFee = nBaseFee;
if (!MoneyRange(nMinFee))
nMinFee = MAX_MONEY;
+
return nMinFee;
}
unsigned int nSize = ::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION);
// Don't accept it if it can't get into a block
- int64 txMinFee = tx.GetMinFee(1000, false, GMF_RELAY, nSize);
+ int64 txMinFee = tx.GetMinFee(1000, true, GMF_RELAY, nSize);
if (nFees < txMinFee)
return error("CTxMemPool::accept() : not enough fees %s, %"PRI64d" < %"PRI64d,
hash.ToString().c_str(),
}
// miner's coin base reward based on nBits
-int64 GetProofOfWorkReward(unsigned int nBits)
+int64 GetProofOfWorkReward(unsigned int nBits, int64 nFees)
{
CBigNum bnSubsidyLimit = MAX_MINT_PROOF_OF_WORK;
if (fDebug && GetBoolArg("-printcreation"))
printf("GetProofOfWorkReward() : create=%s nBits=0x%08x nSubsidy=%"PRI64d"\n", FormatMoney(nSubsidy).c_str(), nBits, nSubsidy);
- return min(nSubsidy, MAX_MINT_PROOF_OF_WORK);
+ return min(nSubsidy, MAX_MINT_PROOF_OF_WORK) + nFees;
}
// miner's coin stake reward based on nBits and coin age spent (coin-days)
if (!GetCoinAge(txdb, nCoinAge))
return error("ConnectInputs() : %s unable to get coin age for coinstake", GetHash().ToString().substr(0,10).c_str());
- int64 nStakeReward = GetValueOut() - nValueIn;
- int64 nCalculatedStakeReward = GetProofOfStakeReward(nCoinAge, pindexBlock->nBits, nTime) - GetMinFee() + MIN_TX_FEE;
+ unsigned int nTxSize = (nTime > VALIDATION_SWITCH_TIME || fTestNet) ? GetSerializeSize(SER_NETWORK, PROTOCOL_VERSION) : 0;
+
+ int64 nReward = GetValueOut() - nValueIn;
+ int64 nCalculatedReward = GetProofOfStakeReward(nCoinAge, pindexBlock->nBits, nTime) - GetMinFee(1, false, GMF_BLOCK, nTxSize) + CENT;
- if (nStakeReward > nCalculatedStakeReward)
- return DoS(100, error("ConnectInputs() : coinstake pays too much(actual=%"PRI64d" vs calculated=%"PRI64d")", nStakeReward, nCalculatedStakeReward));
+ if (nReward > nCalculatedReward)
+ return DoS(100, error("CheckInputs() : coinstake pays too much(actual=%"PRI64d" vs calculated=%"PRI64d")", nReward, nCalculatedReward));
}
else
{
if (nTxFee < 0)
return DoS(100, error("ConnectInputs() : %s nTxFee < 0", GetHash().ToString().substr(0,10).c_str()));
- // enforce transaction fees for every block until 1 May 2014 04:00:00 GMT
- if (!fTestNet && nTxFee < GetMinFee() && nTime < OUTPUT_SWITCH_TIME)
- return fBlock? DoS(100, error("ConnectInputs() : %s not paying required fee=%s, paid=%s", GetHash().ToString().substr(0,10).c_str(), FormatMoney(GetMinFee()).c_str(), FormatMoney(nTxFee).c_str())) : false;
-
nFees += nTxFee;
if (!MoneyRange(nFees))
return DoS(100, error("ConnectInputs() : nFees out of range"));
if (!CheckBlock(!fJustCheck, !fJustCheck, false))
return false;
+ bool fProtocol048 = fTestNet || VALIDATION_SWITCH_TIME < nTime;
+
// Do not allow blocks that contain transactions which 'overwrite' older transactions,
// unless those are already completely spent.
// If such overwrites are allowed, coinbases and transactions depending upon those
mapQueuedChanges[hashTx] = CTxIndex(posThisTx, tx.vout.size());
}
- // ppcoin: track money supply and mint amount info
+ if (IsProofOfWork())
+ {
+ int64 nBlockReward = GetProofOfWorkReward(nBits, fProtocol048 ? nFees : 0);
+
+ // Check coinbase reward
+ if (vtx[0].GetValueOut() > nBlockReward)
+ return error("CheckBlock() : coinbase reward exceeded (actual=%"PRI64d" vs calculated=%"PRI64d")",
+ vtx[0].GetValueOut(),
+ nBlockReward);
+ }
+
+ // track money supply and mint amount info
pindex->nMint = nValueOut - nValueIn + nFees;
pindex->nMoneySupply = (pindex->pprev? pindex->pprev->nMoneySupply : 0) + nValueOut - nValueIn;
if (!txdb.WriteBlockIndex(CDiskBlockIndex(pindex)))
return error("Connect() : WriteBlockIndex for pindex failed");
- // ppcoin: fees are not collected by miners as in bitcoin
- // ppcoin: fees are destroyed to compensate the entire network
- if (fDebug && GetBoolArg("-printcreation"))
+ // fees are not collected by proof-of-stake miners
+ // fees are destroyed to compensate the entire network
+ if (fProtocol048 && fDebug && IsProofOfStake() && GetBoolArg("-printcreation"))
printf("ConnectBlock() : destroy=%s nFees=%"PRI64d"\n", FormatMoney(nFees).c_str(), nFees);
if (fJustCheck)
// ppcoin: compute stake modifier
uint64 nStakeModifier = 0;
bool fGeneratedStakeModifier = false;
- if (!ComputeNextStakeModifier(pindexNew->pprev, nStakeModifier, fGeneratedStakeModifier))
+ if (!ComputeNextStakeModifier(pindexNew, nStakeModifier, fGeneratedStakeModifier))
return error("AddToBlockIndex() : ComputeNextStakeModifier() failed");
pindexNew->SetStakeModifier(nStakeModifier, fGeneratedStakeModifier);
pindexNew->nStakeModifierChecksum = GetStakeModifierChecksum(pindexNew);
if (vtx.empty() || vtx.size() > MAX_BLOCK_SIZE || ::GetSerializeSize(*this, SER_NETWORK, PROTOCOL_VERSION) > MAX_BLOCK_SIZE)
return DoS(100, error("CheckBlock() : size limits failed"));
+ bool fProtocol048 = fTestNet || VALIDATION_SWITCH_TIME < nTime;
+
// Check proof of work matches claimed amount
if (fCheckPOW && IsProofOfWork() && !CheckProofOfWork(GetHash(), nBits))
return DoS(50, error("CheckBlock() : proof of work failed"));
// First transaction must be coinbase, the rest must not be
if (vtx.empty() || !vtx[0].IsCoinBase())
return DoS(100, error("CheckBlock() : first tx is not coinbase"));
+
+ if (!fProtocol048)
+ {
+ // Check coinbase timestamp
+ if (GetBlockTime() < (int64)vtx[0].nTime)
+ return DoS(100, error("CheckBlock() : coinbase timestamp violation"));
+ }
+ else
+ {
+ // Check coinbase timestamp
+ if (GetBlockTime() < PastDrift((int64)vtx[0].nTime))
+ return DoS(50, error("CheckBlock() : coinbase timestamp is too late"));
+ }
+
for (unsigned int i = 1; i < vtx.size(); i++)
+ {
if (vtx[i].IsCoinBase())
return DoS(100, error("CheckBlock() : more than one coinbase"));
- // Check coinbase timestamp
- if (GetBlockTime() > FutureDrift((int64)vtx[0].nTime))
- return DoS(50, error("CheckBlock() : coinbase timestamp is too early"));
+ // Check transaction timestamp
+ if (GetBlockTime() < (int64)vtx[i].nTime)
+ return DoS(50, error("CheckBlock() : block timestamp earlier than transaction timestamp"));
+ }
if (IsProofOfStake())
{
+ if (fProtocol048)
+ {
+ if (nNonce != 0)
+ return DoS(100, error("CheckBlock() : non-zero nonce in proof-of-stake block"));
+ }
+
// Coinbase output should be empty if proof-of-stake block
if (vtx[0].vout.size() != 1 || !vtx[0].vout[0].IsEmpty())
return DoS(100, error("CheckBlock() : coinbase output not empty for proof-of-stake block"));
return DoS(100, error("CheckBlock() : more than one coinstake"));
// Check coinstake timestamp
- if (!CheckCoinStakeTimestamp(GetBlockTime(), (int64)vtx[1].nTime))
+ if (GetBlockTime() != (int64)vtx[1].nTime)
return DoS(50, error("CheckBlock() : coinstake timestamp violation nTimeBlock=%"PRI64d" nTimeTx=%u", GetBlockTime(), vtx[1].nTime));
// NovaCoin: check proof-of-stake block signature
}
else
{
- int64 nReward = GetProofOfWorkReward(nBits);
- // Check coinbase reward
- if (vtx[0].GetValueOut() > nReward)
- return DoS(50, error("CheckBlock() : coinbase reward exceeded (actual=%"PRI64d" vs calculated=%"PRI64d")",
- vtx[0].GetValueOut(),
- nReward));
-
// Should we check proof-of-work block signature or not?
//
// * Always skip on TestNet
{
if (!tx.CheckTransaction())
return DoS(tx.nDoS, error("CheckBlock() : CheckTransaction failed"));
-
- // ppcoin: check transaction timestamp
- if (GetBlockTime() < (int64)tx.nTime)
- return DoS(50, error("CheckBlock() : block timestamp earlier than transaction timestamp"));
}
// Check for duplicate txids. This is caught by ConnectInputs(),
if (!block.AddToBlockIndex(nFile, nBlockPos))
return error("LoadBlockIndex() : genesis block not accepted");
- // ppcoin: initialize synchronized checkpoint
+ // initialize synchronized checkpoint
if (!Checkpoints::WriteSyncCheckpoint((!fTestNet ? hashGenesisBlock : hashGenesisBlockTestNet)))
return error("LoadBlockIndex() : failed to init sync checkpoint");
+
+ // upgrade time set to zero if txdb initialized
+ {
+ if (!txdb.WriteModifierUpgradeTime(0))
+ return error("LoadBlockIndex() : failed to init upgrade info");
+ printf(" Upgrade Info: ModifierUpgradeTime txdb initialization\n");
+ }
}
string strPubKey = "";
return error("LoadBlockIndex() : failed to reset sync-checkpoint");
}
+ // upgrade time set to zero if blocktreedb initialized
+ if (txdb.ReadModifierUpgradeTime(nModifierUpgradeTime))
+ {
+ if (nModifierUpgradeTime)
+ printf(" Upgrade Info: blocktreedb upgrade detected at timestamp %d\n", nModifierUpgradeTime);
+ else
+ printf(" Upgrade Info: no blocktreedb upgrade detected.\n");
+ }
+ else
+ {
+ nModifierUpgradeTime = GetTime();
+ printf(" Upgrade Info: upgrading blocktreedb at timestamp %u\n", nModifierUpgradeTime);
+ if (!txdb.WriteModifierUpgradeTime(nModifierUpgradeTime))
+ return error("LoadBlockIndex() : failed to write upgrade info");
+ }
+
+
return true;
}
extern map<uint256, CAlert> mapAlerts;
extern CCriticalSection cs_mapAlerts;
-extern string strMintMessage;
-extern string strMintWarning;
-
string GetWarnings(string strFor)
{
int nPriority = 0;
if (GetBoolArg("-testsafemode"))
strRPC = "test";
- // wallet lock warning for minting
- if (strMintWarning != "")
- {
- nPriority = 0;
- strStatusBar = strMintWarning;
- }
-
// Misc warnings like out of disk space and clock is wrong
if (strMiscWarning != "")
{
strStatusBar = strMiscWarning;
}
+ // if detected unmet upgrade requirement enter safe mode
+ // Note: Modifier upgrade requires blockchain redownload if past protocol switch
+ if (IsFixedModifierInterval(nModifierUpgradeTime + 60*60*24)) // 1 day margin
+ {
+ nPriority = 5000;
+ strStatusBar = strRPC = "WARNING: Blockchain redownload required approaching or past v.0.4.4.6u4 upgrade deadline.";
+ }
+
// if detected invalid checkpoint enter safe mode
if (Checkpoints::hashInvalidCheckpoint != 0)
{
#ifndef BITCOIN_MAIN_H
#define BITCOIN_MAIN_H
+#include "timestamps.h"
#include "bignum.h"
#include "sync.h"
#include "net.h"
static const unsigned int MAX_BLOCK_SIGOPS = MAX_BLOCK_SIZE/50;
static const unsigned int MAX_ORPHAN_TRANSACTIONS = MAX_BLOCK_SIZE/100;
static const unsigned int MAX_INV_SZ = 50000;
-static const int64 MIN_TX_FEE = CENT;
-static const int64 MIN_RELAY_TX_FEE = CENT;
+
+static const int64 MIN_TX_FEE = CENT/10;
+static const int64 MIN_RELAY_TX_FEE = CENT/50;
+
static const int64 MAX_MONEY = 2000000000 * COIN;
static const int64 MAX_MINT_PROOF_OF_WORK = 100 * COIN;
static const int64 MAX_MINT_PROOF_OF_STAKE = 1 * COIN;
-static const int64 MIN_TXOUT_AMOUNT = MIN_TX_FEE;
-
-static const unsigned int ENTROPY_SWITCH_TIME = 1362791041; // Sat, 09 Mar 2013 01:04:01 GMT
-static const unsigned int STAKE_SWITCH_TIME = 1371686400; // Thu, 20 Jun 2013 00:00:00 GMT
-static const unsigned int TARGETS_SWITCH_TIME = 1374278400; // Sat, 20 Jul 2013 00:00:00 GMT
-static const unsigned int CHAINCHECKS_SWITCH_TIME = 1379635200; // Fri, 20 Sep 2013 00:00:00 GMT
-static const unsigned int STAKECURVE_SWITCH_TIME = 1382227200; // Sun, 20 Oct 2013 00:00:00 GMT
-static const unsigned int OUTPUT_SWITCH_TIME = 1398916800; // Thu, 01 May 2014 04:00:00 GMT
-
+static const int64 MIN_TXOUT_AMOUNT = CENT/100;
inline bool MoneyRange(int64 nValue) { return (nValue >= 0 && nValue <= MAX_MONEY); }
// Threshold for nLockTime: below this value it is interpreted as block number, otherwise as UNIX timestamp.
bool CheckProofOfWork(uint256 hash, unsigned int nBits);
unsigned int GetNextTargetRequired(const CBlockIndex* pindexLast, bool fProofOfStake);
-int64 GetProofOfWorkReward(unsigned int nBits);
+int64 GetProofOfWorkReward(unsigned int nBits, int64 nFees=0);
int64 GetProofOfStakeReward(int64 nCoinAge, unsigned int nBits, unsigned int nTime, bool bCoinYearOnly=false);
unsigned int ComputeMinWork(unsigned int nBase, int64 nTime);
unsigned int ComputeMinStake(unsigned int nBase, int64 nTime, unsigned int nBlockTime);
// BitcoinMiner
//
-string strMintMessage = "Stake miner suspended due to locked wallet.";
-string strMintWarning;
-
extern unsigned int nMinerSleep;
int static FormatHashBlocks(void* pbuffer, unsigned int len)
continue;
// Simplify transaction fee - allow free = false
- int64 nMinFee = tx.GetMinFee(nBlockSize, false, GMF_BLOCK);
+ int64 nMinFee = tx.GetMinFee(nBlockSize, true, GMF_BLOCK, nTxSize);
// Skip free transactions if we're past the minimum block size:
if (fSortedByFee && (dFeePerKb < nMinTxFee) && (nBlockSize + nTxSize >= nBlockMinSize))
printf("CreateNewBlock(): total size %"PRI64u"\n", nBlockSize);
if (!fProofOfStake)
- pblock->vtx[0].vout[0].nValue = GetProofOfWorkReward(pblock->nBits);
+ {
+ bool fProtocol048 = fTestNet || VALIDATION_SWITCH_TIME < pblock->nTime;
+ pblock->vtx[0].vout[0].nValue = GetProofOfWorkReward(pblock->nBits, fProtocol048 ? nFees : 0);
+ }
// Fill in header
pblock->hashPrevBlock = pindexPrev->GetBlockHash();
while (pwallet->IsLocked())
{
- strMintWarning = strMintMessage;
Sleep(1000);
if (fShutdown)
return;
return;
}
- strMintWarning = "";
-
//
// Create new block
//
// Trying to sign a block
if (pblock->SignBlock(*pwallet))
{
- strMintWarning = _("Stake generation: new block found!");
SetThreadPriority(THREAD_PRIORITY_NORMAL);
CheckStake(pblock.get(), *pwallet);
SetThreadPriority(THREAD_PRIORITY_LOWEST);
#include <QPushButton>
#include <QKeyEvent>
+extern bool fWalletUnlockMintOnly;
+
AskPassphraseDialog::AskPassphraseDialog(Mode mode, QWidget *parent) :
QDialog(parent),
ui(new Ui::AskPassphraseDialog),
setWindowTitle(tr("Encrypt wallet"));
break;
case Unlock: // Ask passphrase
+ case UnlockMining:
ui->warningLabel->setText(tr("This operation needs your wallet passphrase to unlock the wallet."));
ui->passLabel2->hide();
ui->passEdit2->hide();
QDialog::accept(); // Success
}
break;
+ case UnlockMining:
+ if(!model->setWalletLocked(false, oldpass))
+ {
+ QMessageBox::critical(this, tr("Wallet unlock failed"),
+ tr("The passphrase entered for the wallet decryption was incorrect."));
+ }
+ else
+ {
+ QDialog::accept(); // Success
+ fWalletUnlockMintOnly = true;
+ }
+ break;
case Decrypt:
if(!model->setWalletEncrypted(false, oldpass))
{
acceptable = !ui->passEdit2->text().isEmpty() && !ui->passEdit3->text().isEmpty();
break;
case Unlock: // Old passphrase x1
+ case UnlockMining:
case Decrypt:
acceptable = !ui->passEdit1->text().isEmpty();
break;
public:
enum Mode {
- Encrypt, /**< Ask passphrase twice and encrypt */
- Unlock, /**< Ask passphrase and unlock */
- ChangePass, /**< Ask old passphrase + new passphrase twice */
- Decrypt /**< Ask passphrase and decrypt wallet */
+ Encrypt, /**< Ask passphrase twice and encrypt */
+ Unlock, /**< Ask passphrase and unlock */
+ UnlockMining, /**< Ask passphrase and unlock for mining */
+ ChangePass, /**< Ask old passphrase + new passphrase twice */
+ Decrypt /**< Ask passphrase and decrypt wallet */
};
explicit AskPassphraseDialog(Mode mode, QWidget *parent = 0);
<file alias="connect_2">res/icons/connect2_16.png</file>
<file alias="connect_3">res/icons/connect3_16.png</file>
<file alias="connect_4">res/icons/connect4_16.png</file>
+ <file alias="mining_active">res/icons/mining_active.png</file>
+ <file alias="mining_inactive">res/icons/mining_inactive.png</file>
<file alias="transaction_0">res/icons/transaction0.png</file>
<file alias="transaction_confirmed">res/icons/transaction2.png</file>
<file alias="transaction_1">res/icons/clock1.png</file>
<file alias="filesave">res/icons/filesave.png</file>
<file alias="qrcode">res/icons/qrcode.png</file>
<file alias="debugwindow">res/icons/debugwindow.png</file>
+ <file alias="dump">res/icons/dump.png</file>
+ <file alias="import">res/icons/import.png</file>
</qresource>
<qresource prefix="/images">
<file alias="about">res/images/about.png</file>
#include "askpassphrasedialog.h"
#include "notificator.h"
#include "guiutil.h"
+#include "ui_interface.h"
#include "rpcconsole.h"
#ifdef Q_OS_MAC
#include <iostream>
+extern bool fWalletUnlockMintOnly;
+
BitcoinGUI::BitcoinGUI(QWidget *parent):
QMainWindow(parent),
clientModel(0),
walletModel(0),
encryptWalletAction(0),
+ lockWalletAction(0),
+ unlockWalletAction(0),
+ unlockWalletMiningAction(0),
changePassphraseAction(0),
aboutQtAction(0),
trayIcon(0),
// Status bar notification icons
QFrame *frameBlocks = new QFrame();
frameBlocks->setContentsMargins(0,0,0,0);
- frameBlocks->setMinimumWidth(56);
- frameBlocks->setMaximumWidth(56);
+ frameBlocks->setMinimumWidth(72);
+ frameBlocks->setMaximumWidth(72);
QHBoxLayout *frameBlocksLayout = new QHBoxLayout(frameBlocks);
frameBlocksLayout->setContentsMargins(3,0,3,0);
frameBlocksLayout->setSpacing(3);
labelEncryptionIcon = new QLabel();
+ labelMiningIcon = new QLabel();
labelConnectionsIcon = new QLabel();
labelBlocksIcon = new QLabel();
frameBlocksLayout->addStretch();
frameBlocksLayout->addWidget(labelEncryptionIcon);
frameBlocksLayout->addStretch();
+ frameBlocksLayout->addWidget(labelMiningIcon);
+ frameBlocksLayout->addStretch();
frameBlocksLayout->addWidget(labelConnectionsIcon);
frameBlocksLayout->addStretch();
frameBlocksLayout->addWidget(labelBlocksIcon);
encryptWalletAction->setCheckable(true);
backupWalletAction = new QAction(QIcon(":/icons/filesave"), tr("&Backup Wallet..."), this);
backupWalletAction->setToolTip(tr("Backup wallet to another location"));
+ dumpWalletAction = new QAction(QIcon(":/icons/dump"), tr("&Dump Wallet..."), this);
+ dumpWalletAction->setStatusTip(tr("Dump keys to a text file"));
+ importWalletAction = new QAction(QIcon(":/icons/import"), tr("&Import Wallet..."), this);
+ importWalletAction->setStatusTip(tr("Import keys into a wallet"));
changePassphraseAction = new QAction(QIcon(":/icons/key"), tr("&Change Passphrase..."), this);
changePassphraseAction->setToolTip(tr("Change the passphrase used for wallet encryption"));
signMessageAction = new QAction(QIcon(":/icons/edit"), tr("Sign &message..."), this);
verifyMessageAction = new QAction(QIcon(":/icons/transaction_0"), tr("&Verify message..."), this);
+ lockWalletAction = new QAction(QIcon(":/icons/lock_closed"), tr("&Lock wallet"), this);
+ lockWalletAction->setToolTip(tr("Lock wallet"));
+ lockWalletAction->setCheckable(true);
+
+ unlockWalletAction = new QAction(QIcon(":/icons/lock_open"), tr("Unlo&ck wallet"), this);
+ unlockWalletAction->setToolTip(tr("Unlock wallet"));
+ unlockWalletAction->setCheckable(true);
+
+ unlockWalletMiningAction = new QAction(QIcon(":/icons/mining_active"), tr("Unlo&ck wallet for mining"), this);
+ unlockWalletMiningAction->setToolTip(tr("Unlock wallet for mining"));
+ unlockWalletMiningAction->setCheckable(true);
+
exportAction = new QAction(QIcon(":/icons/export"), tr("&Export..."), this);
exportAction->setToolTip(tr("Export the data in the current tab to a file"));
openRPCConsoleAction = new QAction(QIcon(":/icons/debugwindow"), tr("&Debug window"), this);
connect(optionsAction, SIGNAL(triggered()), this, SLOT(optionsClicked()));
connect(toggleHideAction, SIGNAL(triggered()), this, SLOT(toggleHidden()));
connect(encryptWalletAction, SIGNAL(triggered(bool)), this, SLOT(encryptWallet(bool)));
+ connect(lockWalletAction, SIGNAL(triggered(bool)), this, SLOT(lockWallet()));
+ connect(unlockWalletAction, SIGNAL(triggered(bool)), this, SLOT(unlockWallet()));
+ connect(unlockWalletMiningAction, SIGNAL(triggered(bool)), this, SLOT(unlockWalletMining(bool)));
connect(backupWalletAction, SIGNAL(triggered()), this, SLOT(backupWallet()));
+ connect(dumpWalletAction, SIGNAL(triggered()), this, SLOT(dumpWallet()));
+ connect(importWalletAction, SIGNAL(triggered()), this, SLOT(importWallet()));
connect(changePassphraseAction, SIGNAL(triggered()), this, SLOT(changePassphrase()));
connect(signMessageAction, SIGNAL(triggered()), this, SLOT(gotoSignMessageTab()));
connect(verifyMessageAction, SIGNAL(triggered()), this, SLOT(gotoVerifyMessageTab()));
// Configure the menus
QMenu *file = appMenuBar->addMenu(tr("&File"));
file->addAction(backupWalletAction);
+ file->addSeparator();
+ file->addAction(dumpWalletAction);
+ file->addAction(importWalletAction);
file->addAction(exportAction);
file->addAction(signMessageAction);
file->addAction(verifyMessageAction);
file->addAction(quitAction);
QMenu *settings = appMenuBar->addMenu(tr("&Settings"));
- settings->addAction(encryptWalletAction);
- settings->addAction(changePassphraseAction);
- settings->addSeparator();
+ QMenu *securityMenu = settings->addMenu(QIcon(":/icons/key"), tr("&Wallet security"));
+ securityMenu->addAction(encryptWalletAction);
+ securityMenu->addAction(changePassphraseAction);
+ securityMenu->addAction(unlockWalletAction);
+ securityMenu->addAction(unlockWalletMiningAction);
+ securityMenu->addAction(lockWalletAction);
settings->addAction(optionsAction);
QMenu *help = appMenuBar->addMenu(tr("&Help"));
setNumBlocks(clientModel->getNumBlocks(), clientModel->getNumBlocksOfPeers());
connect(clientModel, SIGNAL(numBlocksChanged(int,int)), this, SLOT(setNumBlocks(int,int)));
+ connect(clientModel, SIGNAL(numBlocksChanged(int,int)), this, SLOT(updateMining()));
// Report errors from network/worker thread
connect(clientModel, SIGNAL(error(QString,QString,bool)), this, SLOT(error(QString,QString,bool)));
setEncryptionStatus(walletModel->getEncryptionStatus());
connect(walletModel, SIGNAL(encryptionStatusChanged(int)), this, SLOT(setEncryptionStatus(int)));
+ connect(walletModel, SIGNAL(encryptionStatusChanged(int)), this, SLOT(updateMining()));
// Balloon pop-up for new transaction
connect(walletModel->getTransactionTableModel(), SIGNAL(rowsInserted(QModelIndex,int,int)),
progressBar->setToolTip(tooltip);
}
+void BitcoinGUI::updateMining()
+{
+ if(!walletModel)
+ return;
+
+ labelMiningIcon->setPixmap(QIcon(":/icons/mining_inactive").pixmap(STATUSBAR_ICONSIZE,STATUSBAR_ICONSIZE));
+
+ if (!clientModel->getNumConnections())
+ {
+ labelMiningIcon->setToolTip(tr("Wallet is offline"));
+ return;
+ }
+
+ if (walletModel->getEncryptionStatus() == WalletModel::Locked)
+ {
+ labelMiningIcon->setToolTip(tr("Wallet is locked"));
+ return;
+ }
+
+ if (clientModel->inInitialBlockDownload() || clientModel->getNumBlocksOfPeers() > clientModel->getNumBlocks())
+ {
+ labelMiningIcon->setToolTip(tr("Blockchain download is in progress"));
+ return;
+ }
+
+ uint64 nMinWeight = 0, nMaxWeight = 0, nTotalWeight = 0;
+ walletModel->getStakeWeight(nMinWeight, nMaxWeight, nTotalWeight);
+
+ if (nTotalWeight > 0)
+ {
+ labelMiningIcon->setPixmap(QIcon(":/icons/mining_active").pixmap(STATUSBAR_ICONSIZE,STATUSBAR_ICONSIZE));
+
+ uint64 nNetworkWeight = clientModel->getPoSKernelPS();
+/*
+ double dDifficulty = clientModel->getDifficulty(true);
+ QString msg;
+
+ int nApproxTime = 4294967297 * dDifficulty / nTotalWeight;
+
+ if (nApproxTime < 60)
+ msg = tr("%n second(s)", "", nApproxTime);
+ else if (nApproxTime < 60*60)
+ msg = tr("%n minute(s)", "", nApproxTime / 60);
+ else if (nApproxTime < 24*60*60)
+ msg = tr("%n hour(s)", "", nApproxTime / 3600);
+ else
+ msg = tr("%n day(s)", "", nApproxTime / 86400);
+
+ labelMiningIcon->setToolTip(tr("Stake miner is active\nYour current stake weight is %1\nNetwork weight is %2\nAverage block generation time is %3").arg(nTotalWeight).arg(dNetworkWeight).arg(msg));
+*/
+
+ labelMiningIcon->setToolTip(tr("Stake miner is active\nYour current stake weight is %1\nNetwork weight is %2").arg(nTotalWeight).arg(nNetworkWeight));
+ }
+ else
+ labelMiningIcon->setToolTip(tr("No suitable inputs were found"));
+}
+
void BitcoinGUI::error(const QString &title, const QString &message, bool modal)
{
// Report errors from network/worker thread
}
}
+void BitcoinGUI::message(const QString &title, const QString &message, unsigned int style, const QString &detail)
+{
+ QString strTitle = tr("NovaCoin") + " - ";
+ // Default to information icon
+ int nMBoxIcon = QMessageBox::Information;
+ int nNotifyIcon = Notificator::Information;
+
+
+ // Check for usage of predefined title
+ switch (style) {
+ case CClientUIInterface::MSG_ERROR:
+ strTitle += tr("Error");
+ break;
+ case CClientUIInterface::MSG_WARNING:
+ strTitle += tr("Warning");
+ break;
+ case CClientUIInterface::MSG_INFORMATION:
+ strTitle += tr("Information");
+ break;
+ default:
+ strTitle += title; // Use supplied title
+ }
+
+ // Check for error/warning icon
+ if (style & CClientUIInterface::ICON_ERROR) {
+ nMBoxIcon = QMessageBox::Critical;
+ nNotifyIcon = Notificator::Critical;
+ }
+ else if (style & CClientUIInterface::ICON_WARNING) {
+ nMBoxIcon = QMessageBox::Warning;
+ nNotifyIcon = Notificator::Warning;
+ }
+
+ // Display message
+ if (style & CClientUIInterface::MODAL) {
+ // Check for buttons, use OK as default, if none was supplied
+ QMessageBox::StandardButton buttons;
+ buttons = QMessageBox::Ok;
+
+ QMessageBox mBox((QMessageBox::Icon)nMBoxIcon, strTitle, message, buttons);
+
+ if(!detail.isEmpty()) { mBox.setDetailedText(detail); }
+
+ mBox.exec();
+ }
+ else
+ notificator->notify((Notificator::Class)nNotifyIcon, strTitle, message);
+}
+
+
void BitcoinGUI::changeEvent(QEvent *e)
{
QMainWindow::changeEvent(e);
labelEncryptionIcon->hide();
encryptWalletAction->setChecked(false);
changePassphraseAction->setEnabled(false);
+ lockWalletAction->setEnabled(false);
+ unlockWalletAction->setEnabled(false);
+ unlockWalletMiningAction->setEnabled(false);
encryptWalletAction->setEnabled(true);
break;
case WalletModel::Unlocked:
encryptWalletAction->setChecked(true);
changePassphraseAction->setEnabled(true);
encryptWalletAction->setEnabled(false); // TODO: decrypt currently not supported
+
+ lockWalletAction->setEnabled(true);
+ lockWalletAction->setChecked(false);
+ unlockWalletAction->setEnabled(false);
+ unlockWalletMiningAction->setEnabled(false);
+
+ if (fWalletUnlockMintOnly)
+ unlockWalletMiningAction->setChecked(true);
+ else
+ unlockWalletAction->setChecked(true);
+
break;
case WalletModel::Locked:
labelEncryptionIcon->show();
encryptWalletAction->setChecked(true);
changePassphraseAction->setEnabled(true);
encryptWalletAction->setEnabled(false); // TODO: decrypt currently not supported
+
+ lockWalletAction->setChecked(true);
+ unlockWalletAction->setChecked(false);
+ unlockWalletMiningAction->setChecked(false);
+
+ lockWalletAction->setEnabled(false);
+ unlockWalletAction->setEnabled(true);
+ unlockWalletMiningAction->setEnabled(true);
break;
}
}
setEncryptionStatus(walletModel->getEncryptionStatus());
}
+void BitcoinGUI::unlockWalletMining(bool status)
+{
+ if(!walletModel)
+ return;
+
+ // Unlock wallet when requested by wallet model
+ if(walletModel->getEncryptionStatus() == WalletModel::Locked)
+ {
+ AskPassphraseDialog dlg(AskPassphraseDialog::UnlockMining, this);
+ dlg.setModel(walletModel);
+ dlg.exec();
+ }
+}
+
void BitcoinGUI::backupWallet()
{
QString saveDir = QDesktopServices::storageLocation(QDesktopServices::DocumentsLocation);
}
}
+void BitcoinGUI::dumpWallet()
+{
+ if(!walletModel)
+ return;
+
+ WalletModel::UnlockContext ctx(walletModel->requestUnlock());
+ if(!ctx.isValid())
+ {
+ // Unlock wallet failed or was cancelled
+ return;
+ }
+
+#if QT_VERSION < 0x050000
+ QString saveDir = QDesktopServices::storageLocation(QDesktopServices::DocumentsLocation);
+#else
+ QString saveDir = QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation);
+#endif
+ QString filename = QFileDialog::getSaveFileName(this, tr("Dump Wallet"), saveDir, tr("Wallet dump (*.txt)"));
+ if(!filename.isEmpty()) {
+ if(!walletModel->dumpWallet(filename)) {
+ error(tr("Dump failed"),
+ tr("An error happened while trying to save the keys to your location.\n"
+ "Keys were not saved.")
+ ,CClientUIInterface::MSG_ERROR);
+ }
+ else
+ message(tr("Dump successful"),
+ tr("Keys were saved to this file:\n%2")
+ .arg(filename)
+ ,CClientUIInterface::MSG_INFORMATION);
+ }
+}
+
+void BitcoinGUI::importWallet()
+{
+ if(!walletModel)
+ return;
+
+ WalletModel::UnlockContext ctx(walletModel->requestUnlock());
+ if(!ctx.isValid())
+ {
+ // Unlock wallet failed or was cancelled
+ return;
+ }
+
+#if QT_VERSION < 0x050000
+ QString openDir = QDesktopServices::storageLocation(QDesktopServices::DocumentsLocation);
+#else
+ QString openDir = QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation);
+#endif
+ QString filename = QFileDialog::getOpenFileName(this, tr("Import Wallet"), openDir, tr("Wallet dump (*.txt)"));
+ if(!filename.isEmpty()) {
+ if(!walletModel->importWallet(filename)) {
+ error(tr("Import Failed"),
+ tr("An error happened while trying to import the keys.\n"
+ "Some or all keys from:\n %1,\n were not imported into your wallet.")
+ .arg(filename)
+ ,CClientUIInterface::MSG_ERROR);
+ }
+ else
+ message(tr("Import Successful"),
+ tr("All keys from:\n %1,\n were imported into your wallet.")
+ .arg(filename)
+ ,CClientUIInterface::MSG_INFORMATION);
+ }
+}
+
+
void BitcoinGUI::changePassphrase()
{
AskPassphraseDialog dlg(AskPassphraseDialog::ChangePass, this);
}
}
+void BitcoinGUI::lockWallet()
+{
+ if(!walletModel)
+ return;
+
+ walletModel->setWalletLocked(true);
+}
+
void BitcoinGUI::showNormalIfMinimized(bool fToggleHidden)
{
// activateWindow() (sometimes) helps with keyboard focus on Windows
QLabel *labelEncryptionIcon;
QLabel *labelConnectionsIcon;
QLabel *labelBlocksIcon;
+ QLabel *labelMiningIcon;
QLabel *progressBarLabel;
QProgressBar *progressBar;
QAction *toggleHideAction;
QAction *exportAction;
QAction *encryptWalletAction;
+ QAction *lockWalletAction;
+ QAction *unlockWalletAction;
+ QAction *unlockWalletMiningAction;
QAction *backupWalletAction;
+ QAction *dumpWalletAction;
+ QAction *importWalletAction;
QAction *changePassphraseAction;
QAction *aboutQtAction;
QAction *openRPCConsoleAction;
void setNumConnections(int count);
/** Set number of blocks shown in the UI */
void setNumBlocks(int count, int nTotalBlocks);
+ /** Set stake miner status in the UI */
+ void updateMining();
/** Set the encryption status as shown in the UI.
@param[in] status current encryption status
@see WalletModel::EncryptionStatus
/** Notify the user of an error in the network or transaction handling code. */
void error(const QString &title, const QString &message, bool modal);
+ void message(const QString &title, const QString &message, unsigned int style, const QString &detail=QString());
+
/** Asks the user whether to pay the transaction fee or to cancel the transaction.
It is currently not possible to pass a return value to another thread through
BlockingQueuedConnection, so an indirected pointer is used.
/** Backup the wallet */
void backupWallet();
/** Change encrypted wallet passphrase */
+
+ void dumpWallet();
+ void importWallet();
+
void changePassphrase();
/** Ask for passphrase to unlock wallet temporarily */
+ void lockWallet();
void unlockWallet();
+ void unlockWalletMining(bool status);
/** Show window if hidden, unminimize when minimized, rise when obscured or show if hidden and fToggleHidden is true */
void showNormalIfMinimized(bool fToggleHidden = false);
#include <QDateTime>
#include <QTimer>
+extern double GetPoSKernelPS();
+extern double GetDifficulty(const CBlockIndex* blockindex);
+
static const int64 nClientStartupTime = GetTime();
ClientModel::ClientModel(OptionsModel *optionsModel, QObject *parent) :
unsubscribeFromCoreSignals();
}
+double ClientModel::getPoSKernelPS()
+{
+ return GetPoSKernelPS();
+}
+
+double ClientModel::getDifficulty(bool fProofofStake)
+{
+ if (fProofofStake)
+ return GetDifficulty(GetLastBlockIndex(pindexBest,true));
+ else
+ return GetDifficulty(GetLastBlockIndex(pindexBest,false));
+}
+
int ClientModel::getNumConnections() const
{
return vNodes.size();
OptionsModel *getOptionsModel();
+ double getPoSKernelPS();
+ double getDifficulty(bool fProofofStake);
+
int getNumConnections() const;
int getNumBlocks() const;
int getNumBlocksAtStartup();
ui->treeWidget->setColumnWidth(COLUMN_CHECKBOX, 84);
ui->treeWidget->setColumnWidth(COLUMN_AMOUNT, 100);
ui->treeWidget->setColumnWidth(COLUMN_LABEL, 170);
- ui->treeWidget->setColumnWidth(COLUMN_ADDRESS, 290);
- ui->treeWidget->setColumnWidth(COLUMN_DATE, 110);
- ui->treeWidget->setColumnWidth(COLUMN_CONFIRMATIONS, 100);
+ ui->treeWidget->setColumnWidth(COLUMN_ADDRESS, 250);
+ ui->treeWidget->setColumnWidth(COLUMN_DATE, 90);
+ ui->treeWidget->setColumnWidth(COLUMN_CONFIRMATIONS, 70);
ui->treeWidget->setColumnWidth(COLUMN_PRIORITY, 100);
+ ui->treeWidget->setColumnWidth(COLUMN_WEIGHT, 100);
ui->treeWidget->setColumnHidden(COLUMN_TXHASH, true); // store transacton hash in this column, but dont show it
ui->treeWidget->setColumnHidden(COLUMN_VOUT_INDEX, true); // store vout index in this column, but dont show it
ui->treeWidget->setColumnHidden(COLUMN_AMOUNT_INT64, true); // store amount int64 in this column, but dont show it
else
{
sortColumn = logicalIndex;
- sortOrder = ((sortColumn == COLUMN_AMOUNT_INT64 || sortColumn == COLUMN_PRIORITY_INT64 || sortColumn == COLUMN_DATE || sortColumn == COLUMN_CONFIRMATIONS) ? Qt::DescendingOrder : Qt::AscendingOrder); // if amount,date,conf,priority then default => desc, else default => asc
+ sortOrder = ((sortColumn == COLUMN_AMOUNT_INT64 || sortColumn == COLUMN_PRIORITY_INT64 || sortColumn == COLUMN_DATE || sortColumn == COLUMN_CONFIRMATIONS || sortColumn == COLUMN_WEIGHT) ? Qt::DescendingOrder : Qt::AscendingOrder); // if amount,date,conf,priority then default => desc, else default => asc
}
sortView(sortColumn, sortOrder);
{
if (amount < CENT)
fLowOutput = true;
+ if (amount < MIN_TX_FEE)
+ fDust = true;
CTxOut txout(amount, (CScript)vector<unsigned char>(24, 0));
txDummy.vout.push_back(txout);
double dPriority = 0;
double dPriorityInputs = 0;
unsigned int nQuantity = 0;
-
+
vector<COutPoint> vCoinControl;
vector<COutput> vOutputs;
coinControl->ListSelected(vCoinControl);
{
// Quantity
nQuantity++;
-
+
// Amount
nAmount += out.tx->vout[out.i].nValue;
-
+
// Priority
dPriorityInputs += (double)out.tx->vout[out.i].nValue * (out.nDepth+1);
-
+
// Bytes
CTxDestination address;
if(ExtractDestination(out.tx->vout[out.i].scriptPubKey, address))
}
else nBytesInputs += 148;
}
-
+
// calculation
if (nQuantity > 0)
{
// Bytes
nBytes = nBytesInputs + ((CoinControlDialog::payAmounts.size() > 0 ? CoinControlDialog::payAmounts.size() + 1 : 2) * 34) + 10; // always assume +1 output for change here
-
+
// Priority
dPriority = dPriorityInputs / nBytes;
sPriorityLabel = CoinControlDialog::getPriorityLabel(dPriority);
-
+
// Fee
int64 nFee = nTransactionFee * (1 + (int64)nBytes / 1000);
-
+
// Min Fee
- int64 nMinFee = txDummy.GetMinFee(1, false, GMF_SEND, nBytes);
-
+ bool fAllowFree = CTransaction::AllowFree(dPriority);
+
+ // Disable free transactions until 1 July 2014
+ if (!fTestNet && txDummy.nTime < FEE_SWITCH_TIME)
+ {
+ fAllowFree = false;
+ }
+
+ int64 nMinFee = txDummy.GetMinFee(1, fAllowFree, GMF_SEND, nBytes);
+
nPayFee = max(nFee, nMinFee);
-
+
if (nPayAmount > 0)
{
nChange = nAmount - nPayFee - nPayAmount;
-
+
// if sub-cent change is required, the fee must be raised to at least CTransaction::nMinTxFee
- if (nPayFee < CENT && nChange > 0 && nChange < CENT)
+ if (txDummy.nTime < FEE_SWITCH_TIME && !fTestNet)
{
- if (nChange < CENT) // change < 0.01 => simply move all change to fees
+ if (nPayFee < CENT && nChange > 0 && nChange < CENT)
{
- nPayFee = nChange;
- nChange = 0;
+ if (nChange < CENT) // change < 0.01 => simply move all change to fees
+ {
+ nPayFee = nChange;
+ nChange = 0;
+ }
+ else
+ {
+ nChange = nChange + nPayFee - CENT;
+ nPayFee = CENT;
+ }
}
- else
- {
- nChange = nChange + nPayFee - CENT;
- nPayFee = CENT;
- }
}
-
+
if (nChange == 0)
nBytes -= 34;
}
-
+
// after fee
nAfterFee = nAmount - nPayFee;
if (nAfterFee < 0)
nAfterFee = 0;
}
-
+
// actually update labels
int nDisplayUnit = BitcoinUnits::BTC;
if (model && model->getOptionsModel())
nDisplayUnit = model->getOptionsModel()->getDisplayUnit();
-
+
QLabel *l1 = dialog->findChild<QLabel *>("labelCoinControlQuantity");
QLabel *l2 = dialog->findChild<QLabel *>("labelCoinControlAmount");
QLabel *l3 = dialog->findChild<QLabel *>("labelCoinControlFee");
QLabel *l6 = dialog->findChild<QLabel *>("labelCoinControlPriority");
QLabel *l7 = dialog->findChild<QLabel *>("labelCoinControlLowOutput");
QLabel *l8 = dialog->findChild<QLabel *>("labelCoinControlChange");
-
+
// enable/disable "low output" and "change"
dialog->findChild<QLabel *>("labelCoinControlLowOutputText")->setEnabled(nPayAmount > 0);
dialog->findChild<QLabel *>("labelCoinControlLowOutput") ->setEnabled(nPayAmount > 0);
dialog->findChild<QLabel *>("labelCoinControlChangeText") ->setEnabled(nPayAmount > 0);
dialog->findChild<QLabel *>("labelCoinControlChange") ->setEnabled(nPayAmount > 0);
-
+
// stats
- l1->setText(QString::number(nQuantity)); // Quantity
+ l1->setText(QString::number(nQuantity)); // Quantity
l2->setText(BitcoinUnits::formatWithUnit(nDisplayUnit, nAmount)); // Amount
l3->setText(BitcoinUnits::formatWithUnit(nDisplayUnit, nPayFee)); // Fee
l4->setText(BitcoinUnits::formatWithUnit(nDisplayUnit, nAfterFee)); // After Fee
- l5->setText(((nBytes > 0) ? "~" : "") + QString::number(nBytes)); // Bytes
+ l5->setText(((nBytes > 0) ? "~" : "") + QString::number(nBytes)); // Bytes
l6->setText(sPriorityLabel); // Priority
l7->setText((fLowOutput ? (fDust ? tr("DUST") : tr("yes")) : tr("no"))); // Low Output / Dust
l8->setText(BitcoinUnits::formatWithUnit(nDisplayUnit, nChange)); // Change
-
+
// turn labels "red"
- l5->setStyleSheet((nBytes >= 10000) ? "color:red;" : ""); // Bytes >= 10000
- l6->setStyleSheet((dPriority <= 576000) ? "color:red;" : ""); // Priority < "medium"
- l7->setStyleSheet((fLowOutput) ? "color:red;" : ""); // Low Output = "yes"
- l8->setStyleSheet((nChange > 0 && nChange < CENT) ? "color:red;" : ""); // Change < 0.01BTC
-
+ l5->setStyleSheet((nBytes >= 1000) ? "color:red;" : ""); // Bytes >= 1000
+ l6->setStyleSheet((dPriority <= 576000) ? "color:red;" : ""); // Priority < "medium"
+ l7->setStyleSheet((fLowOutput) ? "color:red;" : ""); // Low Output = "yes"
+ l8->setStyleSheet((nChange > 0 && nChange < CENT) ? "color:red;" : ""); // Change < 0.01BTC
+
// tool tips
- l5->setToolTip(tr("This label turns red, if the transaction size is bigger than 10000 bytes.\n\n This means a fee of at least %1 per kb is required.\n\n Can vary +/- 1 Byte per input.").arg(BitcoinUnits::formatWithUnit(nDisplayUnit, CENT)));
- l6->setToolTip(tr("Transactions with higher priority get more likely into a block.\n\nThis label turns red, if the priority is smaller than \"medium\".\n\n This means a fee of at least %1 per kb is required.").arg(BitcoinUnits::formatWithUnit(nDisplayUnit, CENT)));
- l7->setToolTip(tr("This label turns red, if any recipient receives an amount smaller than %1.\n\n This means a fee of at least %2 is required. \n\n Amounts below 0.546 times the minimum relay fee are shown as DUST.").arg(BitcoinUnits::formatWithUnit(nDisplayUnit, CENT)).arg(BitcoinUnits::formatWithUnit(nDisplayUnit, CENT)));
- l8->setToolTip(tr("This label turns red, if the change is smaller than %1.\n\n This means a fee of at least %2 is required.").arg(BitcoinUnits::formatWithUnit(nDisplayUnit, CENT)).arg(BitcoinUnits::formatWithUnit(nDisplayUnit, CENT)));
+ l5->setToolTip(tr("This label turns red, if the transaction size is bigger than 1000 bytes.\n\n This means a fee of at least %1 per kb is required.\n\n Can vary +/- 1 Byte per input.").arg(BitcoinUnits::formatWithUnit(nDisplayUnit, fTestNet || FEE_SWITCH_TIME < GetTime() ? MIN_TX_FEE : CENT)));
+ l6->setToolTip(tr("Transactions with higher priority get more likely into a block.\n\nThis label turns red, if the priority is smaller than \"medium\".\n\n This means a fee of at least %1 per kb is required.").arg(BitcoinUnits::formatWithUnit(nDisplayUnit, fTestNet || FEE_SWITCH_TIME < GetTime() ? MIN_TX_FEE : CENT)));
+ l7->setToolTip(tr("This label turns red, if any recipient receives an amount smaller than %1.\n\n This means a fee of at least %2 is required. \n\n Amounts below the minimum fee are shown as DUST.").arg(BitcoinUnits::formatWithUnit(nDisplayUnit, CENT)).arg(BitcoinUnits::formatWithUnit(nDisplayUnit, fTestNet || FEE_SWITCH_TIME < GetTime() ? MIN_RELAY_TX_FEE : CENT)));
+ l8->setToolTip(tr("This label turns red, if the change is smaller than %1.\n\n This means a fee of at least %2 is required.").arg(BitcoinUnits::formatWithUnit(nDisplayUnit, CENT)).arg(BitcoinUnits::formatWithUnit(nDisplayUnit, fTestNet || FEE_SWITCH_TIME < GetTime() ? MIN_TX_FEE : CENT)));
dialog->findChild<QLabel *>("labelCoinControlBytesText") ->setToolTip(l5->toolTip());
dialog->findChild<QLabel *>("labelCoinControlPriorityText") ->setToolTip(l6->toolTip());
dialog->findChild<QLabel *>("labelCoinControlLowOutputText")->setToolTip(l7->toolTip());
dialog->findChild<QLabel *>("labelCoinControlChangeText") ->setToolTip(l8->toolTip());
-
+
// Insufficient funds
QLabel *label = dialog->findChild<QLabel *>("labelCoinControlInsuffFunds");
if (label)
ui->treeWidget->setAlternatingRowColors(!treeMode);
QFlags<Qt::ItemFlag> flgCheckbox=Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsUserCheckable;
QFlags<Qt::ItemFlag> flgTristate=Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsUserCheckable | Qt::ItemIsTristate;
-
+
int nDisplayUnit = BitcoinUnits::BTC;
if (model && model->getOptionsModel())
nDisplayUnit = model->getOptionsModel()->getDisplayUnit();
-
+
map<QString, vector<COutput> > mapCoins;
model->listCoins(mapCoins);
sWalletLabel = model->getAddressTableModel()->labelForAddress(sWalletAddress);
if (sWalletLabel.length() == 0)
sWalletLabel = tr("(no label)");
-
+
if (treeMode)
{
// wallet address
itemWalletAddress->setFlags(flgTristate);
itemWalletAddress->setCheckState(COLUMN_CHECKBOX,Qt::Unchecked);
-
+
for (int i = 0; i < ui->treeWidget->columnCount(); i++)
itemWalletAddress->setBackground(i, QColor(248, 247, 246));
-
+
// label
itemWalletAddress->setText(COLUMN_LABEL, sWalletLabel);
double dPrioritySum = 0;
int nChildren = 0;
int nInputSum = 0;
+ uint64 nTxWeight = 0, nTxWeightSum = 0;
BOOST_FOREACH(const COutput& out, coins.second)
{
int nInputSize = 148; // 180 if uncompressed public key
nSum += out.tx->vout[out.i].nValue;
+ model->getStakeWeightFromValue(out.tx->GetTxTime(), out.tx->vout[out.i].nValue, nTxWeight);
+ nTxWeightSum += nTxWeight;
nChildren++;
-
+
QTreeWidgetItem *itemOutput;
if (treeMode) itemOutput = new QTreeWidgetItem(itemWalletAddress);
else itemOutput = new QTreeWidgetItem(ui->treeWidget);
itemOutput->setFlags(flgCheckbox);
itemOutput->setCheckState(COLUMN_CHECKBOX,Qt::Unchecked);
-
+
// address
CTxDestination outputAddress;
QString sAddress = "";
if(ExtractDestination(out.tx->vout[out.i].scriptPubKey, outputAddress))
{
sAddress = CBitcoinAddress(outputAddress).ToString().c_str();
-
+
// if listMode or change => show bitcoin address. In tree mode, address is not shown again for direct wallet address outputs
if (!treeMode || (!(sAddress == sWalletAddress)))
itemOutput->setText(COLUMN_ADDRESS, sAddress);
-
+
CPubKey pubkey;
CKeyID *keyid = boost::get< CKeyID >(&outputAddress);
if (keyid && model->getPubKey(*keyid, pubkey) && !pubkey.IsCompressed())
// date
itemOutput->setText(COLUMN_DATE, QDateTime::fromTime_t(out.tx->GetTxTime()).toUTC().toString("yy-MM-dd hh:mm"));
-
+
// immature PoS reward
if (out.tx->IsCoinStake() && out.tx->GetBlocksToMaturity() > 0 && out.tx->GetDepthInMainChain() > 0) {
itemOutput->setBackground(COLUMN_CONFIRMATIONS, Qt::red);
// confirmations
itemOutput->setText(COLUMN_CONFIRMATIONS, strPad(QString::number(out.nDepth), 8, " "));
-
+
// priority
double dPriority = ((double)out.tx->vout[out.i].nValue / (nInputSize + 78)) * (out.nDepth+1); // 78 = 2 * 34 + 10
itemOutput->setText(COLUMN_PRIORITY, CoinControlDialog::getPriorityLabel(dPriority));
itemOutput->setText(COLUMN_PRIORITY_INT64, strPad(QString::number((int64)dPriority), 20, " "));
dPrioritySum += (double)out.tx->vout[out.i].nValue * (out.nDepth+1);
nInputSum += nInputSize;
-
+
+ // List Mode Weight
+ itemOutput->setText(COLUMN_WEIGHT, strPad(QString::number(nTxWeight), 8, " "));
+
// transaction hash
uint256 txhash = out.tx->GetHash();
itemOutput->setText(COLUMN_TXHASH, txhash.GetHex().c_str());
-
+
// vout index
itemOutput->setText(COLUMN_VOUT_INDEX, QString::number(out.i));
-
- // disable locked coins
+
+ // disable locked coins
/*if (model->isLockedCoin(txhash, out.i))
{
COutPoint outpt(txhash, out.i);
itemOutput->setDisabled(true);
itemOutput->setIcon(COLUMN_CHECKBOX, QIcon(":/icons/lock_closed"));
}*/
-
+
// set checkbox
if (coinControl->IsSelected(txhash, out.i))
itemOutput->setCheckState(COLUMN_CHECKBOX,Qt::Checked);
itemWalletAddress->setText(COLUMN_AMOUNT_INT64, strPad(QString::number(nSum), 15, " "));
itemWalletAddress->setText(COLUMN_PRIORITY, CoinControlDialog::getPriorityLabel(dPrioritySum));
itemWalletAddress->setText(COLUMN_PRIORITY_INT64, strPad(QString::number((int64)dPrioritySum), 20, " "));
+ itemWalletAddress->setText(COLUMN_WEIGHT, strPad(QString::number((uint64)nTxWeightSum),8," "));
+
}
}
-
+
// expand all partially selected
if (treeMode)
{
if (ui->treeWidget->topLevelItem(i)->checkState(COLUMN_CHECKBOX) == Qt::PartiallyChecked)
ui->treeWidget->topLevelItem(i)->setExpanded(true);
}
-
+
// sort view
sortView(sortColumn, sortOrder);
ui->treeWidget->setEnabled(true);
COLUMN_ADDRESS,
COLUMN_DATE,
COLUMN_CONFIRMATIONS,
+ COLUMN_WEIGHT,
COLUMN_PRIORITY,
COLUMN_TXHASH,
COLUMN_VOUT_INDEX,
<height>41</height>
</rect>
</property>
- <layout class="QHBoxLayout" name="horizontalLayoutPanel" stretch="0,0,0,0,0">
+ <layout class="QHBoxLayout" name="horizontalLayoutPanel" stretch="0,0,0,0">
<property name="spacing">
<number>14</number>
</property>
</column>
<column>
<property name="text">
+ <string>Weight</string>
+ </property>
+ </column>
+ <column>
+ <property name="text">
<string>Priority</string>
</property>
</column>
<enum>Qt::ActionsContextMenu</enum>
</property>
<property name="text">
- <string>0.00 BTC</string>
+ <string>0.00 NVC</string>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
<enum>Qt::ActionsContextMenu</enum>
</property>
<property name="text">
- <string>0.00 BTC</string>
+ <string>0.00 NVC</string>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
<enum>Qt::ActionsContextMenu</enum>
</property>
<property name="text">
- <string>0.00 BTC</string>
+ <string>0.00 NVC</string>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
<enum>Qt::ActionsContextMenu</enum>
</property>
<property name="text">
- <string>0.00 BTC</string>
+ <string>0.00 NVC</string>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
</widget>
</item>
<item>
- <widget class="QLineEdit" name="lineEditCoinControlChange">
+ <widget class="QValidatedLineEdit" name="lineEditCoinControlChange">
<property name="enabled">
<bool>false</bool>
</property>
</property>
</widget>
</item>
- <item>
- <widget class="QLabel" name="labelCoinControlChangeLabel">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Preferred" vsizetype="Expanding">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="minimumSize">
- <size>
- <width>0</width>
- <height>0</height>
- </size>
- </property>
- <property name="text">
- <string/>
- </property>
- <property name="margin">
- <number>3</number>
- </property>
- </widget>
- </item>
+ <item>
+ <widget class="QToolButton" name="addressBookButton">
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="toolTip">
+ <string>Choose address from address book</string>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ <property name="icon">
+ <iconset resource="../bitcoin.qrc">
+ <normaloff>:/icons/address-book</normaloff>:/icons/address-book</iconset>
+ </property>
+ <property name="shortcut">
+ <string>Alt+A</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QToolButton" name="pasteButton">
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="toolTip">
+ <string>Paste address from clipboard</string>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ <property name="icon">
+ <iconset resource="../bitcoin.qrc">
+ <normaloff>:/icons/editpaste</normaloff>:/icons/editpaste</iconset>
+ </property>
+ <property name="shortcut">
+ <string>Alt+P</string>
+ </property>
+ </widget>
+ </item>
</layout>
</item>
<item>
<cursorShape>IBeamCursor</cursorShape>
</property>
<property name="text">
- <string>123.456 BTC</string>
+ <string>123.456 NVC</string>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
-<?xml version="1.0" encoding="UTF-8"?>\r
-<ui version="4.0">\r
- <class>SendCoinsEntry</class>\r
- <widget class="QFrame" name="SendCoinsEntry">\r
- <property name="geometry">\r
- <rect>\r
- <x>0</x>\r
- <y>0</y>\r
- <width>729</width>\r
- <height>136</height>\r
- </rect>\r
- </property>\r
- <property name="windowTitle">\r
- <string>Form</string>\r
- </property>\r
- <property name="frameShape">\r
- <enum>QFrame::StyledPanel</enum>\r
- </property>\r
- <property name="frameShadow">\r
- <enum>QFrame::Sunken</enum>\r
- </property>\r
- <layout class="QGridLayout" name="gridLayout">\r
- <property name="spacing">\r
- <number>12</number>\r
- </property>\r
- <item row="5" column="0">\r
- <widget class="QLabel" name="label">\r
- <property name="text">\r
- <string>A&mount:</string>\r
- </property>\r
- <property name="alignment">\r
- <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>\r
- </property>\r
- <property name="buddy">\r
- <cstring>payAmount</cstring>\r
- </property>\r
- </widget>\r
- </item>\r
- <item row="3" column="0">\r
- <widget class="QLabel" name="label_2">\r
- <property name="text">\r
- <string>Pay &To:</string>\r
- </property>\r
- <property name="alignment">\r
- <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>\r
- </property>\r
- <property name="buddy">\r
- <cstring>payTo</cstring>\r
- </property>\r
- </widget>\r
- </item>\r
- <item row="5" column="1">\r
- <widget class="BitcoinAmountField" name="payAmount"/>\r
- </item>\r
- <item row="4" column="1">\r
- <layout class="QHBoxLayout" name="horizontalLayout_2">\r
- <property name="spacing">\r
- <number>0</number>\r
- </property>\r
- <item>\r
- <widget class="QValidatedLineEdit" name="addAsLabel">\r
- <property name="enabled">\r
- <bool>true</bool>\r
- </property>\r
- <property name="toolTip">\r
- <string>Enter a label for this address to add it to your address book</string>\r
- </property>\r
- </widget>\r
- </item>\r
- </layout>\r
- </item>\r
- <item row="4" column="0">\r
- <widget class="QLabel" name="label_4">\r
- <property name="text">\r
- <string>&Label:</string>\r
- </property>\r
- <property name="alignment">\r
- <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>\r
- </property>\r
- <property name="buddy">\r
- <cstring>addAsLabel</cstring>\r
- </property>\r
- </widget>\r
- </item>\r
- <item row="3" column="1">\r
- <layout class="QHBoxLayout" name="payToLayout">\r
- <property name="spacing">\r
- <number>0</number>\r
- </property>\r
- <item>\r
- <widget class="QValidatedLineEdit" name="payTo">\r
- <property name="toolTip">\r
- <string>The address to send the payment to (e.g. 4Zo1ga6xuKuQ7JV7M9rGDoxdbYwV5zgQJ5)</string>\r
- </property>\r
- <property name="maxLength">\r
- <number>34</number>\r
- </property>\r
- </widget>\r
- </item>\r
- <item>\r
- <widget class="QToolButton" name="addressBookButton">\r
- <property name="toolTip">\r
- <string>Choose address from address book</string>\r
- </property>\r
- <property name="text">\r
- <string/>\r
- </property>\r
- <property name="icon">\r
- <iconset resource="../bitcoin.qrc">\r
- <normaloff>:/icons/address-book</normaloff>:/icons/address-book</iconset>\r
- </property>\r
- <property name="shortcut">\r
- <string>Alt+A</string>\r
- </property>\r
- </widget>\r
- </item>\r
- <item>\r
- <widget class="QToolButton" name="pasteButton">\r
- <property name="toolTip">\r
- <string>Paste address from clipboard</string>\r
- </property>\r
- <property name="text">\r
- <string/>\r
- </property>\r
- <property name="icon">\r
- <iconset resource="../bitcoin.qrc">\r
- <normaloff>:/icons/editpaste</normaloff>:/icons/editpaste</iconset>\r
- </property>\r
- <property name="shortcut">\r
- <string>Alt+P</string>\r
- </property>\r
- </widget>\r
- </item>\r
- <item>\r
- <widget class="QToolButton" name="deleteButton">\r
- <property name="toolTip">\r
- <string>Remove this recipient</string>\r
- </property>\r
- <property name="text">\r
- <string/>\r
- </property>\r
- <property name="icon">\r
- <iconset resource="../bitcoin.qrc">\r
- <normaloff>:/icons/remove</normaloff>:/icons/remove</iconset>\r
- </property>\r
- </widget>\r
- </item>\r
- </layout>\r
- </item>\r
- </layout>\r
- </widget>\r
- <customwidgets>\r
- <customwidget>\r
- <class>QValidatedLineEdit</class>\r
- <extends>QLineEdit</extends>\r
- <header>qvalidatedlineedit.h</header>\r
- </customwidget>\r
- <customwidget>\r
- <class>BitcoinAmountField</class>\r
- <extends>QLineEdit</extends>\r
- <header>bitcoinamountfield.h</header>\r
- <container>1</container>\r
- </customwidget>\r
- </customwidgets>\r
- <resources>\r
- <include location="../bitcoin.qrc"/>\r
- </resources>\r
- <connections/>\r
-</ui>\r
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>SendCoinsEntry</class>
+ <widget class="QFrame" name="SendCoinsEntry">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>729</width>
+ <height>136</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Form</string>
+ </property>
+ <property name="frameShape">
+ <enum>QFrame::StyledPanel</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>QFrame::Sunken</enum>
+ </property>
+ <layout class="QGridLayout" name="gridLayout">
+ <property name="spacing">
+ <number>12</number>
+ </property>
+ <item row="5" column="0">
+ <widget class="QLabel" name="label">
+ <property name="text">
+ <string>A&mount:</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ </property>
+ <property name="buddy">
+ <cstring>payAmount</cstring>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="0">
+ <widget class="QLabel" name="label_2">
+ <property name="text">
+ <string>Pay &To:</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ </property>
+ <property name="buddy">
+ <cstring>payTo</cstring>
+ </property>
+ </widget>
+ </item>
+ <item row="5" column="1">
+ <widget class="BitcoinAmountField" name="payAmount"/>
+ </item>
+ <item row="4" column="1">
+ <layout class="QHBoxLayout" name="horizontalLayout_2">
+ <property name="spacing">
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QValidatedLineEdit" name="addAsLabel">
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="toolTip">
+ <string>Enter a label for this address to add it to your address book</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item row="4" column="0">
+ <widget class="QLabel" name="label_4">
+ <property name="text">
+ <string>&Label:</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+ </property>
+ <property name="buddy">
+ <cstring>addAsLabel</cstring>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="1">
+ <layout class="QHBoxLayout" name="payToLayout">
+ <property name="spacing">
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QValidatedLineEdit" name="payTo">
+ <property name="toolTip">
+ <string>The address to send the payment to (e.g. 4Zo1ga6xuKuQ7JV7M9rGDoxdbYwV5zgQJ5)</string>
+ </property>
+ <property name="maxLength">
+ <number>34</number>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QToolButton" name="addressBookButton">
+ <property name="toolTip">
+ <string>Choose address from address book</string>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ <property name="icon">
+ <iconset resource="../bitcoin.qrc">
+ <normaloff>:/icons/address-book</normaloff>:/icons/address-book</iconset>
+ </property>
+ <property name="shortcut">
+ <string>Alt+A</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QToolButton" name="pasteButton">
+ <property name="toolTip">
+ <string>Paste address from clipboard</string>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ <property name="icon">
+ <iconset resource="../bitcoin.qrc">
+ <normaloff>:/icons/editpaste</normaloff>:/icons/editpaste</iconset>
+ </property>
+ <property name="shortcut">
+ <string>Alt+P</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QToolButton" name="deleteButton">
+ <property name="toolTip">
+ <string>Remove this recipient</string>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ <property name="icon">
+ <iconset resource="../bitcoin.qrc">
+ <normaloff>:/icons/remove</normaloff>:/icons/remove</iconset>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ <customwidgets>
+ <customwidget>
+ <class>QValidatedLineEdit</class>
+ <extends>QLineEdit</extends>
+ <header>qvalidatedlineedit.h</header>
+ </customwidget>
+ <customwidget>
+ <class>BitcoinAmountField</class>
+ <extends>QLineEdit</extends>
+ <header>bitcoinamountfield.h</header>
+ <container>1</container>
+ </customwidget>
+ </customwidgets>
+ <resources>
+ <include location="../bitcoin.qrc"/>
+ </resources>
+ <connections/>
+</ui>
-<?xml version="1.0" encoding="UTF-8"?>\r
-<ui version="4.0">\r
- <class>SignVerifyMessageDialog</class>\r
- <widget class="QDialog" name="SignVerifyMessageDialog">\r
- <property name="geometry">\r
- <rect>\r
- <x>0</x>\r
- <y>0</y>\r
- <width>700</width>\r
- <height>380</height>\r
- </rect>\r
- </property>\r
- <property name="windowTitle">\r
- <string>Signatures - Sign / Verify a Message</string>\r
- </property>\r
- <property name="modal">\r
- <bool>true</bool>\r
- </property>\r
- <layout class="QVBoxLayout" name="verticalLayout">\r
- <item>\r
- <widget class="QTabWidget" name="tabWidget">\r
- <property name="currentIndex">\r
- <number>1</number>\r
- </property>\r
- <widget class="QWidget" name="tabSignMessage">\r
- <attribute name="title">\r
- <string>&Sign Message</string>\r
- </attribute>\r
- <layout class="QVBoxLayout" name="verticalLayout_SM">\r
- <item>\r
- <widget class="QLabel" name="infoLabel_SM">\r
- <property name="text">\r
- <string>You can sign messages with your addresses to prove you own them. Be careful not to sign anything vague, as phishing attacks may try to trick you into signing your identity over to them. Only sign fully-detailed statements you agree to.</string>\r
- </property>\r
- <property name="textFormat">\r
- <enum>Qt::PlainText</enum>\r
- </property>\r
- <property name="wordWrap">\r
- <bool>true</bool>\r
- </property>\r
- </widget>\r
- </item>\r
- <item>\r
- <layout class="QHBoxLayout" name="horizontalLayout_1_SM">\r
- <property name="spacing">\r
- <number>0</number>\r
- </property>\r
- <item>\r
- <widget class="QValidatedLineEdit" name="addressIn_SM">\r
- <property name="toolTip">\r
- <string>The address to sign the message with (e.g. 4Zo1ga6xuKuQ7JV7M9rGDoxdbYwV5zgQJ5)</string>\r
- </property>\r
- <property name="maxLength">\r
- <number>34</number>\r
- </property>\r
- </widget>\r
- </item>\r
- <item>\r
- <widget class="QPushButton" name="addressBookButton_SM">\r
- <property name="toolTip">\r
- <string>Choose an address from the address book</string>\r
- </property>\r
- <property name="text">\r
- <string/>\r
- </property>\r
- <property name="icon">\r
- <iconset resource="../bitcoin.qrc">\r
- <normaloff>:/icons/address-book</normaloff>:/icons/address-book</iconset>\r
- </property>\r
- <property name="shortcut">\r
- <string>Alt+A</string>\r
- </property>\r
- <property name="autoDefault">\r
- <bool>false</bool>\r
- </property>\r
- </widget>\r
- </item>\r
- <item>\r
- <widget class="QPushButton" name="pasteButton_SM">\r
- <property name="toolTip">\r
- <string>Paste address from clipboard</string>\r
- </property>\r
- <property name="text">\r
- <string/>\r
- </property>\r
- <property name="icon">\r
- <iconset resource="../bitcoin.qrc">\r
- <normaloff>:/icons/editpaste</normaloff>:/icons/editpaste</iconset>\r
- </property>\r
- <property name="shortcut">\r
- <string>Alt+P</string>\r
- </property>\r
- <property name="autoDefault">\r
- <bool>false</bool>\r
- </property>\r
- </widget>\r
- </item>\r
- </layout>\r
- </item>\r
- <item>\r
- <widget class="QPlainTextEdit" name="messageIn_SM">\r
- <property name="toolTip">\r
- <string>Enter the message you want to sign here</string>\r
- </property>\r
- </widget>\r
- </item>\r
- <item>\r
- <layout class="QHBoxLayout" name="horizontalLayout_2_SM">\r
- <property name="spacing">\r
- <number>0</number>\r
- </property>\r
- <item>\r
- <widget class="QLineEdit" name="signatureOut_SM">\r
- <property name="font">\r
- <font>\r
- <italic>true</italic>\r
- </font>\r
- </property>\r
- <property name="readOnly">\r
- <bool>true</bool>\r
- </property>\r
- </widget>\r
- </item>\r
- <item>\r
- <widget class="QPushButton" name="copySignatureButton_SM">\r
- <property name="toolTip">\r
- <string>Copy the current signature to the system clipboard</string>\r
- </property>\r
- <property name="text">\r
- <string/>\r
- </property>\r
- <property name="icon">\r
- <iconset resource="../bitcoin.qrc">\r
- <normaloff>:/icons/editcopy</normaloff>:/icons/editcopy</iconset>\r
- </property>\r
- <property name="autoDefault">\r
- <bool>false</bool>\r
- </property>\r
- </widget>\r
- </item>\r
- </layout>\r
- </item>\r
- <item>\r
- <layout class="QHBoxLayout" name="horizontalLayout_3_SM">\r
- <item>\r
- <widget class="QPushButton" name="signMessageButton_SM">\r
- <property name="toolTip">\r
- <string>Sign the message to prove you own this NovaCoin address</string>\r
- </property>\r
- <property name="text">\r
- <string>&Sign Message</string>\r
- </property>\r
- <property name="icon">\r
- <iconset resource="../bitcoin.qrc">\r
- <normaloff>:/icons/edit</normaloff>:/icons/edit</iconset>\r
- </property>\r
- <property name="autoDefault">\r
- <bool>false</bool>\r
- </property>\r
- </widget>\r
- </item>\r
- <item>\r
- <widget class="QPushButton" name="clearButton_SM">\r
- <property name="toolTip">\r
- <string>Reset all sign message fields</string>\r
- </property>\r
- <property name="text">\r
- <string>Clear &All</string>\r
- </property>\r
- <property name="icon">\r
- <iconset resource="../bitcoin.qrc">\r
- <normaloff>:/icons/remove</normaloff>:/icons/remove</iconset>\r
- </property>\r
- <property name="autoDefault">\r
- <bool>false</bool>\r
- </property>\r
- </widget>\r
- </item>\r
- <item>\r
- <spacer name="horizontalSpacer_1_SM">\r
- <property name="orientation">\r
- <enum>Qt::Horizontal</enum>\r
- </property>\r
- <property name="sizeHint" stdset="0">\r
- <size>\r
- <width>40</width>\r
- <height>48</height>\r
- </size>\r
- </property>\r
- </spacer>\r
- </item>\r
- <item>\r
- <widget class="QLabel" name="statusLabel_SM">\r
- <property name="font">\r
- <font>\r
- <weight>75</weight>\r
- <bold>true</bold>\r
- </font>\r
- </property>\r
- <property name="text">\r
- <string/>\r
- </property>\r
- <property name="wordWrap">\r
- <bool>true</bool>\r
- </property>\r
- </widget>\r
- </item>\r
- <item>\r
- <spacer name="horizontalSpacer_2_SM">\r
- <property name="orientation">\r
- <enum>Qt::Horizontal</enum>\r
- </property>\r
- <property name="sizeHint" stdset="0">\r
- <size>\r
- <width>40</width>\r
- <height>48</height>\r
- </size>\r
- </property>\r
- </spacer>\r
- </item>\r
- </layout>\r
- </item>\r
- </layout>\r
- </widget>\r
- <widget class="QWidget" name="tabVerifyMessage">\r
- <attribute name="title">\r
- <string>&Verify Message</string>\r
- </attribute>\r
- <layout class="QVBoxLayout" name="verticalLayout_VM">\r
- <item>\r
- <widget class="QLabel" name="infoLabel_VM">\r
- <property name="text">\r
- <string>Enter the signing address, message (ensure you copy line breaks, spaces, tabs, etc. exactly) and signature below to verify the message. Be careful not to read more into the signature than what is in the signed message itself, to avoid being tricked by a man-in-the-middle attack.</string>\r
- </property>\r
- <property name="textFormat">\r
- <enum>Qt::PlainText</enum>\r
- </property>\r
- <property name="alignment">\r
- <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>\r
- </property>\r
- <property name="wordWrap">\r
- <bool>true</bool>\r
- </property>\r
- </widget>\r
- </item>\r
- <item>\r
- <layout class="QHBoxLayout" name="horizontalLayout_1_VM">\r
- <property name="spacing">\r
- <number>0</number>\r
- </property>\r
- <item>\r
- <widget class="QValidatedLineEdit" name="addressIn_VM">\r
- <property name="toolTip">\r
- <string>The address the message was signed with (e.g. 4Zo1ga6xuKuQ7JV7M9rGDoxdbYwV5zgQJ5)</string>\r
- </property>\r
- <property name="maxLength">\r
- <number>34</number>\r
- </property>\r
- </widget>\r
- </item>\r
- <item>\r
- <widget class="QPushButton" name="addressBookButton_VM">\r
- <property name="toolTip">\r
- <string>Choose an address from the address book</string>\r
- </property>\r
- <property name="text">\r
- <string/>\r
- </property>\r
- <property name="icon">\r
- <iconset resource="../bitcoin.qrc">\r
- <normaloff>:/icons/address-book</normaloff>:/icons/address-book</iconset>\r
- </property>\r
- <property name="shortcut">\r
- <string>Alt+A</string>\r
- </property>\r
- <property name="autoDefault">\r
- <bool>false</bool>\r
- </property>\r
- </widget>\r
- </item>\r
- </layout>\r
- </item>\r
- <item>\r
- <widget class="QPlainTextEdit" name="messageIn_VM"/>\r
- </item>\r
- <item>\r
- <widget class="QValidatedLineEdit" name="signatureIn_VM"/>\r
- </item>\r
- <item>\r
- <layout class="QHBoxLayout" name="horizontalLayout_2_VM">\r
- <item>\r
- <widget class="QPushButton" name="verifyMessageButton_VM">\r
- <property name="toolTip">\r
- <string>Verify the message to ensure it was signed with the specified NovaCoin address</string>\r
- </property>\r
- <property name="text">\r
- <string>&Verify Message</string>\r
- </property>\r
- <property name="icon">\r
- <iconset resource="../bitcoin.qrc">\r
- <normaloff>:/icons/transaction_0</normaloff>:/icons/transaction_0</iconset>\r
- </property>\r
- <property name="autoDefault">\r
- <bool>false</bool>\r
- </property>\r
- </widget>\r
- </item>\r
- <item>\r
- <widget class="QPushButton" name="clearButton_VM">\r
- <property name="toolTip">\r
- <string>Reset all verify message fields</string>\r
- </property>\r
- <property name="text">\r
- <string>Clear &All</string>\r
- </property>\r
- <property name="icon">\r
- <iconset resource="../bitcoin.qrc">\r
- <normaloff>:/icons/remove</normaloff>:/icons/remove</iconset>\r
- </property>\r
- <property name="autoDefault">\r
- <bool>false</bool>\r
- </property>\r
- </widget>\r
- </item>\r
- <item>\r
- <spacer name="horizontalSpacer_1_VM">\r
- <property name="orientation">\r
- <enum>Qt::Horizontal</enum>\r
- </property>\r
- <property name="sizeHint" stdset="0">\r
- <size>\r
- <width>40</width>\r
- <height>48</height>\r
- </size>\r
- </property>\r
- </spacer>\r
- </item>\r
- <item>\r
- <widget class="QLabel" name="statusLabel_VM">\r
- <property name="font">\r
- <font>\r
- <weight>75</weight>\r
- <bold>true</bold>\r
- </font>\r
- </property>\r
- <property name="text">\r
- <string/>\r
- </property>\r
- <property name="wordWrap">\r
- <bool>true</bool>\r
- </property>\r
- </widget>\r
- </item>\r
- <item>\r
- <spacer name="horizontalSpacer_2_VM">\r
- <property name="orientation">\r
- <enum>Qt::Horizontal</enum>\r
- </property>\r
- <property name="sizeHint" stdset="0">\r
- <size>\r
- <width>40</width>\r
- <height>48</height>\r
- </size>\r
- </property>\r
- </spacer>\r
- </item>\r
- </layout>\r
- </item>\r
- </layout>\r
- </widget>\r
- </widget>\r
- </item>\r
- </layout>\r
- </widget>\r
- <customwidgets>\r
- <customwidget>\r
- <class>QValidatedLineEdit</class>\r
- <extends>QLineEdit</extends>\r
- <header>qvalidatedlineedit.h</header>\r
- </customwidget>\r
- </customwidgets>\r
- <resources>\r
- <include location="../bitcoin.qrc"/>\r
- </resources>\r
- <connections/>\r
-</ui>\r
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>SignVerifyMessageDialog</class>
+ <widget class="QDialog" name="SignVerifyMessageDialog">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>700</width>
+ <height>380</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Signatures - Sign / Verify a Message</string>
+ </property>
+ <property name="modal">
+ <bool>true</bool>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <widget class="QTabWidget" name="tabWidget">
+ <property name="currentIndex">
+ <number>1</number>
+ </property>
+ <widget class="QWidget" name="tabSignMessage">
+ <attribute name="title">
+ <string>&Sign Message</string>
+ </attribute>
+ <layout class="QVBoxLayout" name="verticalLayout_SM">
+ <item>
+ <widget class="QLabel" name="infoLabel_SM">
+ <property name="text">
+ <string>You can sign messages with your addresses to prove you own them. Be careful not to sign anything vague, as phishing attacks may try to trick you into signing your identity over to them. Only sign fully-detailed statements you agree to.</string>
+ </property>
+ <property name="textFormat">
+ <enum>Qt::PlainText</enum>
+ </property>
+ <property name="wordWrap">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_1_SM">
+ <property name="spacing">
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QValidatedLineEdit" name="addressIn_SM">
+ <property name="toolTip">
+ <string>The address to sign the message with (e.g. 4Zo1ga6xuKuQ7JV7M9rGDoxdbYwV5zgQJ5)</string>
+ </property>
+ <property name="maxLength">
+ <number>34</number>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="addressBookButton_SM">
+ <property name="toolTip">
+ <string>Choose an address from the address book</string>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ <property name="icon">
+ <iconset resource="../bitcoin.qrc">
+ <normaloff>:/icons/address-book</normaloff>:/icons/address-book</iconset>
+ </property>
+ <property name="shortcut">
+ <string>Alt+A</string>
+ </property>
+ <property name="autoDefault">
+ <bool>false</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="pasteButton_SM">
+ <property name="toolTip">
+ <string>Paste address from clipboard</string>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ <property name="icon">
+ <iconset resource="../bitcoin.qrc">
+ <normaloff>:/icons/editpaste</normaloff>:/icons/editpaste</iconset>
+ </property>
+ <property name="shortcut">
+ <string>Alt+P</string>
+ </property>
+ <property name="autoDefault">
+ <bool>false</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <widget class="QPlainTextEdit" name="messageIn_SM">
+ <property name="toolTip">
+ <string>Enter the message you want to sign here</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_2_SM">
+ <property name="spacing">
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QLineEdit" name="signatureOut_SM">
+ <property name="font">
+ <font>
+ <italic>true</italic>
+ </font>
+ </property>
+ <property name="readOnly">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="copySignatureButton_SM">
+ <property name="toolTip">
+ <string>Copy the current signature to the system clipboard</string>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ <property name="icon">
+ <iconset resource="../bitcoin.qrc">
+ <normaloff>:/icons/editcopy</normaloff>:/icons/editcopy</iconset>
+ </property>
+ <property name="autoDefault">
+ <bool>false</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_3_SM">
+ <item>
+ <widget class="QPushButton" name="signMessageButton_SM">
+ <property name="toolTip">
+ <string>Sign the message to prove you own this NovaCoin address</string>
+ </property>
+ <property name="text">
+ <string>&Sign Message</string>
+ </property>
+ <property name="icon">
+ <iconset resource="../bitcoin.qrc">
+ <normaloff>:/icons/edit</normaloff>:/icons/edit</iconset>
+ </property>
+ <property name="autoDefault">
+ <bool>false</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="clearButton_SM">
+ <property name="toolTip">
+ <string>Reset all sign message fields</string>
+ </property>
+ <property name="text">
+ <string>Clear &All</string>
+ </property>
+ <property name="icon">
+ <iconset resource="../bitcoin.qrc">
+ <normaloff>:/icons/remove</normaloff>:/icons/remove</iconset>
+ </property>
+ <property name="autoDefault">
+ <bool>false</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer_1_SM">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>48</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QLabel" name="statusLabel_SM">
+ <property name="font">
+ <font>
+ <weight>75</weight>
+ <bold>true</bold>
+ </font>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ <property name="wordWrap">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer_2_SM">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>48</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QWidget" name="tabVerifyMessage">
+ <attribute name="title">
+ <string>&Verify Message</string>
+ </attribute>
+ <layout class="QVBoxLayout" name="verticalLayout_VM">
+ <item>
+ <widget class="QLabel" name="infoLabel_VM">
+ <property name="text">
+ <string>Enter the signing address, message (ensure you copy line breaks, spaces, tabs, etc. exactly) and signature below to verify the message. Be careful not to read more into the signature than what is in the signed message itself, to avoid being tricked by a man-in-the-middle attack.</string>
+ </property>
+ <property name="textFormat">
+ <enum>Qt::PlainText</enum>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
+ </property>
+ <property name="wordWrap">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_1_VM">
+ <property name="spacing">
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QValidatedLineEdit" name="addressIn_VM">
+ <property name="toolTip">
+ <string>The address the message was signed with (e.g. 4Zo1ga6xuKuQ7JV7M9rGDoxdbYwV5zgQJ5)</string>
+ </property>
+ <property name="maxLength">
+ <number>34</number>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="addressBookButton_VM">
+ <property name="toolTip">
+ <string>Choose an address from the address book</string>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ <property name="icon">
+ <iconset resource="../bitcoin.qrc">
+ <normaloff>:/icons/address-book</normaloff>:/icons/address-book</iconset>
+ </property>
+ <property name="shortcut">
+ <string>Alt+A</string>
+ </property>
+ <property name="autoDefault">
+ <bool>false</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <widget class="QPlainTextEdit" name="messageIn_VM"/>
+ </item>
+ <item>
+ <widget class="QValidatedLineEdit" name="signatureIn_VM"/>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_2_VM">
+ <item>
+ <widget class="QPushButton" name="verifyMessageButton_VM">
+ <property name="toolTip">
+ <string>Verify the message to ensure it was signed with the specified NovaCoin address</string>
+ </property>
+ <property name="text">
+ <string>&Verify Message</string>
+ </property>
+ <property name="icon">
+ <iconset resource="../bitcoin.qrc">
+ <normaloff>:/icons/transaction_0</normaloff>:/icons/transaction_0</iconset>
+ </property>
+ <property name="autoDefault">
+ <bool>false</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="clearButton_VM">
+ <property name="toolTip">
+ <string>Reset all verify message fields</string>
+ </property>
+ <property name="text">
+ <string>Clear &All</string>
+ </property>
+ <property name="icon">
+ <iconset resource="../bitcoin.qrc">
+ <normaloff>:/icons/remove</normaloff>:/icons/remove</iconset>
+ </property>
+ <property name="autoDefault">
+ <bool>false</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer_1_VM">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>48</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QLabel" name="statusLabel_VM">
+ <property name="font">
+ <font>
+ <weight>75</weight>
+ <bold>true</bold>
+ </font>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ <property name="wordWrap">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer_2_VM">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>48</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <customwidgets>
+ <customwidget>
+ <class>QValidatedLineEdit</class>
+ <extends>QLineEdit</extends>
+ <header>qvalidatedlineedit.h</header>
+ </customwidget>
+ </customwidgets>
+ <resources>
+ <include location="../bitcoin.qrc"/>
+ </resources>
+ <connections/>
+</ui>
<translation>&Backup Wallet...</translation>
</message>
<message>
+ <location line="+4"/>
+ <source>&Dump Wallet...</source>
+ <translation>&Dump Wallet...</translation>
+ </message>
+ <message>
+ <location line="+20"/>
+ <source>Dump Wallet</source>
+ <translation>Dump Wallet</translation>
+ </message>
+ <message>
+ <location line="+22"/>
+ <source>Import Wallet</source>
+ <translation>Import Wallet</translation>
+ </message>
+ <message>
+ <location line="+22"/>
+ <source>Error</source>
+ <translation>Error</translation>
+ </message>
+ <message>
+ <location line="+22"/>
+ <source>Warning</source>
+ <translation>Warning</translation>
+ </message>
+ <message>
+ <location line="+22"/>
+ <source>Information</source>
+ <translation>Information</translation>
+ </message>
+ <message>
+ <location line="+22"/>
+ <source>Dump failed</source>
+ <translation>Dump failed</translation>
+ </message>
+ <message>
+ <location line="+22"/>
+ <source>Import failed</source>
+ <translation>Import failed</translation>
+ </message>
+ <message>
+ <location line="+22"/>
+ <source>Dump successful</source>
+ <translation>Dump successful</translation>
+ </message>
+ <message>
+ <location line="+22"/>
+ <source>Import successful</source>
+ <translation>Import successful</translation>
+ </message>
+ <message>
+ <location line="+22"/>
+ <source>An error happened while trying to import the keys.
+Some or all keys from:
+ %1,
+ were not imported into your wallet.</source>
+ <translation>An error happened while trying to import the keys.
+Some or all keys from:
+ %1,
+ were not imported into your wallet.</translation>
+ </message>
+ <message>
+ <location line="+22"/>
+ <source>Keys were saved to this file:
+%2</source>
+ <translation>Keys were saved to this file:
+%2</translation>
+ </message>
+ <message>
+ <location line="+22"/>
+ <source>All keys from:
+ %1,
+ were imported into your wallet.</source>
+ <translation>All keys from:
+ %1,
+ were imported into your wallet.</translation>
+ </message>
+ <message>
+ <location line="+22"/>
+ <source>An error happened while trying to save the keys to your location.
+Keys were not saved.</source>
+ <translation>An error happened while trying to save the keys to your location.
+Keys were not saved.</translation>
+ </message>
+ <message>
+ <location line="+23"/>
+ <source>Wallet dump (*.txt)</source>
+ <translation>Wallet dump (*.txt)</translation>
+ </message>
+ <message>
+ <location line="+5"/>
+ <source>&Import Wallet...</source>
+ <translation>&Import Wallet...</translation>
+ </message>
+ <message>
<location line="+2"/>
<source>&Change Passphrase...</source>
<translation>&Change Passphrase...</translation>
</message>
+ <message>
+ <location line="+8"/>
+ <source>Dump keys to a text file</source>
+ <translation>Dump keys to a text file</translation>
+ </message>
+ <message>
+ <location line="+11"/>
+ <source>Import keys into a wallet</source>
+ <translation>Import keys into a wallet</translation>
+ </message>
<message numerus="yes">
<location line="+241"/>
<source>~%n block(s) remaining</source>
<translation>Last received block was generated %1.</translation>
</message>
<message>
+ <location line="+12"/>
+ <source>Wallet is offline</source>
+ <translation>Wallet is offline</translation>
+ </message>
+ <message>
+ <location line="+13"/>
+ <source>Wallet is locked</source>
+ <translation>Wallet is locked</translation>
+ </message>
+ <message>
+ <location line="+15"/>
+ <source>Blockchain download is in progress</source>
+ <translation>Blockchain download is in progress</translation>
+ </message>
+ <message>
+ <location line="+18"/>
+ <source>Stake miner is active
+Your current stake weight is %1
+Network weight is %2</source>
+ <translation>Stake miner is active
+Your current stake weight is %1
+Network weight is %2</translation>
+ </message>
+ <message>
+ <location line="+22"/>
+ <source>No suitable inputs were found</source>
+ <translation>No suitable inputs were found</translation>
+ </message>
+ <message>
+ <location line="+23"/>
+ <source>Unlo&ck wallet</source>
+ <translation>Unlo&ck wallet</translation>
+ </message>
+ <message>
+ <location line="+26"/>
+ <source>Unlock wallet</source>
+ <translation>Unlock wallet</translation>
+ </message>
+ <message>
+ <location line="+27"/>
+ <source>Lock wallet</source>
+ <translation>Lock wallet</translation>
+ </message>
+ <message>
+ <location line="+30"/>
+ <source>&Lock wallet</source>
+ <translation>&Lock wallet</translation>
+ </message>
+ <message>
+ <location line="+31"/>
+ <source>Unlo&ck wallet for mining</source>
+ <translation>Unlo&ck wallet for mining</translation>
+ </message>
+ <message>
+ <location line="+34"/>
+ <source>Unlock wallet for mining</source>
+ <translation>Unlock wallet for mining</translation>
+ </message>
+ <message>
+ <location line="+37"/>
+ <source>&Wallet security</source>
+ <translation>&Wallet security</translation>
+ </message>
+ <message>
<location line="+59"/>
<source>This transaction is over the size limit. You can still send it for a fee of %1, which goes to the nodes that process your transaction and helps to support the network. Do you want to pay the fee?</source>
<translation type="unfinished"></translation>
</message>
<message>
<location line="+10"/>
- <source>This label turns red, if the transaction size is bigger than 10000 bytes.
+ <source>This label turns red, if the transaction size is bigger than 1000 bytes.
This means a fee of at least %1 per kb is required.
This means a fee of at least %2 is required.
- Amounts below 0.546 times the minimum relay fee are shown as DUST.</source>
+ Amounts below the minimum fee are shown as DUST.</source>
<translation type="unfinished"></translation>
</message>
<message>
</message>
<message>
<source>Specify wallet file (within data directory)</source>
- <translation type="obsolete">Specify wallet file (within data directory)</translation>
+ <translation>Specify wallet file (within data directory)</translation>
</message>
<message>
<location line="-1"/>
</message>
<message>
<location line="+4"/>
- <source>Find peers using DNS lookup (default: 0)</source>
- <translation type="unfinished">Find peers using DNS lookup (default: 1) {0)?}</translation>
+ <source>Find peers using DNS lookup (default: 1)</source>
+ <translation>Find peers using DNS lookup (default: 1)</translation>
+ </message>
+ <message>
+ <source>Sync checkpoints policy (default: strict)</source>
+ <translation>Sync checkpoints policy (default: strict)</translation>
</message>
<message>
<location line="+5"/>
<translation>Failed to listen on any port. Use -listen=0 if you want this.</translation>
</message>
<message>
- <source>Find peers using DNS lookup (default: 1)</source>
- <translation type="obsolete">Find peers using DNS lookup (default: 1)</translation>
- </message>
- <message>
- <source>Sync checkpoints policy (default: strict)</source>
- <translation type="obsolete">Sync checkpoints policy (default: strict)</translation>
- </message>
- <message>
<location line="+12"/>
<source>Invalid -tor address: '%s'</source>
<translation>Invalid -tor address: '%s'</translation>
<translation>Upgrade wallet to latest format</translation>
</message>
<message>
+ <location line="+120"/>
+ <source>Require a confirmations for change (default: 0)</source>
+ <translation>Require a confirmations for change (default: 0)</translation>
+ </message>
+ <message>
+ <location line="+121"/>
+ <source>Enforce transaction scripts to use canonical PUSH operators (default: 1)</source>
+ <translation>Enforce transaction scripts to use canonical PUSH operators (default: 1)</translation>
+ </message>
+ <message>
<location line="-16"/>
<source>Set key pool size to <n> (default: 100)</source>
<translation>Set key pool size to <n> (default: 100)</translation>
<translation>Fee per KB to add to transactions you send</translation>
</message>
<message>
+ <location line="-3"/>
+ <source>When creating transactions, ignore inputs with value less than this (default: %s)</source>
+ <translation>When creating transactions, ignore inputs with value less than this (default: %s)</translation>
+ </message>
+ <message>
<location line="+19"/>
<source>Loading wallet...</source>
<translation>Loading wallet...</translation>
<translation>&Сделать резервную копию бумажника</translation>
</message>
<message>
+ <location line="+4"/>
+ <source>&Dump Wallet...</source>
+ <translation>&Выгрузка ключей...</translation>
+ </message>
+ <message>
+ <location line="+20"/>
+ <source>Dump Wallet</source>
+ <translation>Выгрузка ключей</translation>
+ </message>
+ <message>
+ <location line="+22"/>
+ <source>Import Wallet</source>
+ <translation>Импорт ключей</translation>
+ </message>
+ <message>
+ <location line="+22"/>
+ <source>Dump failed</source>
+ <translation>Ошибка выгрузки</translation>
+ </message>
+ <message>
+ <location line="+22"/>
+ <source>Import failed</source>
+ <translation>Ошибка импорта</translation>
+ </message>
+ <message>
+ <location line="+22"/>
+ <source>All keys from:
+ %1,
+ were imported into your wallet.</source>
+ <translation>Все ключи из файла
+ %1,
+ были успешно импортированы.</translation>
+ </message>
+ <message>
+ <location line="+22"/>
+ <source>An error happened while trying to save the keys to your location.
+Keys were not saved.</source>
+ <translation>Произошла ошибка при попытке выгрузки ключей в указанный файл.
+Ключи не сохранены.</translation>
+ </message>
+ <message>
+ <location line="+22"/>
+ <source>Dump successful</source>
+ <translation>Выгрузка завершена</translation>
+ </message>
+ <message>
+ <location line="+22"/>
+ <source>Import successful</source>
+ <translation>Импорт завершен</translation>
+ </message>
+ <message>
+ <location line="+22"/>
+ <source>Error</source>
+ <translation>Ошибка</translation>
+ </message>
+ <message>
+ <location line="+22"/>
+ <source>Warning</source>
+ <translation>Предупреждение</translation>
+ </message>
+ <message>
+ <location line="+22"/>
+ <source>Information</source>
+ <translation>Сообщение</translation>
+ </message>
+ <message>
+ <location line="+22"/>
+ <source>Keys were saved to this file:
+%2</source>
+ <translation>Ключи сохранены в
+%2</translation>
+ </message>
+ <message>
+ <location line="+22"/>
+ <source>An error happened while trying to import the keys.
+Some or all keys from:
+ %1,
+ were not imported into your wallet.</source>
+ <translation>При попытке импорта ключей произошла ошибка.
+Некоторые, либо все ключи из
+ %1,
+ не были импортированы.</translation>
+ </message>
+ <message>
+ <location line="+23"/>
+ <source>Wallet dump (*.txt)</source>
+ <translation>Файл с ключами (*.txt)</translation>
+ </message>
+ <message>
+ <location line="+5"/>
+ <source>&Import Wallet...</source>
+ <translation>&Импорт ключей...</translation>
+ </message>
+ <message>
+ <location line="+8"/>
+ <source>Dump keys to a text file</source>
+ <translation>Выгрузить ключи в текстовый файл</translation>
+ </message>
+ <message>
+ <location line="+11"/>
+ <source>Import keys into a wallet</source>
+ <translation>Импортировать ключи из текстового файла</translation>
+ </message>
+ <message>
<location line="+2"/>
<source>&Change Passphrase...</source>
<translation>&Изменить пароль</translation>
<translation>Последний полученный блок был сгенерирован %1.</translation>
</message>
<message>
+ <location line="+12"/>
+ <source>Wallet is offline</source>
+ <translation>Бумажник не в сети</translation>
+ </message>
+ <message>
+ <location line="+13"/>
+ <source>Wallet is locked</source>
+ <translation>Бумажник заблокирован</translation>
+ </message>
+ <message>
+ <location line="+15"/>
+ <source>Blockchain download is in progress</source>
+ <translation>Загрузка цепочки блоков ещё не завершена</translation>
+ </message>
+ <message>
+ <location line="+18"/>
+ <source>Stake miner is active
+Your current stake weight is %1
+Network weight is %2</source>
+ <translation>Proof-of-Stake майнер активен
+Текущий вес %1
+Текущий вес сети %2</translation>
+ </message>
+ <message>
+ <location line="+22"/>
+ <source>No suitable inputs were found</source>
+ <translation>Нет подходящих транзакций</translation>
+ </message>
+ <message>
+ <location line="+23"/>
+ <source>Unlo&ck wallet</source>
+ <translation>Разб&локировать бумажник</translation>
+ </message>
+ <message>
+ <location line="+26"/>
+ <source>Unlock wallet</source>
+ <translation>Разблокировать бумажник</translation>
+ </message>
+ <message>
+ <location line="+27"/>
+ <source>Lock wallet</source>
+ <translation>Заблокировать бумажник</translation>
+ </message>
+ <message>
+ <location line="+30"/>
+ <source>&Lock wallet</source>
+ <translation>&Заблокировать бумажник</translation>
+ </message>
+ <message>
+ <location line="+31"/>
+ <source>Unlo&ck wallet for mining</source>
+ <translation>Ра&зблокировать для майнинга</translation>
+ </message>
+ <message>
+ <location line="+34"/>
+ <source>Unlock wallet for mining</source>
+ <translation>Разблокировать для майнинга</translation>
+ </message>
+ <message>
+ <location line="+37"/>
+ <source>&Wallet security</source>
+ <translation>&Безопасность</translation>
+ </message>
+ <message>
<location line="+59"/>
<source>This transaction is over the size limit. You can still send it for a fee of %1, which goes to the nodes that process your transaction and helps to support the network. Do you want to pay the fee?</source>
<translation>Данная транзакция превышает предельно допустимый размер. Но Вы можете всё равно совершить её, добавив комиссию в %1, которая отправится тем узлам, которые обработают Вашу транзакцию, и поможет поддержать сеть. Вы хотите добавить комиссию?</translation>
<message>
<location line="+3"/>
<source>Copy transaction ID</source>
- <translation type="unfinished">Скопировать ID транзакции</translation>
+ <translation>Скопировать ID транзакции</translation>
</message>
<message>
<location line="+24"/>
<message>
<location line="+319"/>
<source>highest</source>
- <translation type="unfinished"></translation>
+ <translation></translation>
</message>
<message>
<location line="+1"/>
<source>high</source>
- <translation type="unfinished"></translation>
+ <translation></translation>
</message>
<message>
<location line="+1"/>
<source>medium-high</source>
- <translation type="unfinished"></translation>
+ <translation></translation>
</message>
<message>
<location line="+1"/>
<source>medium</source>
- <translation type="unfinished"></translation>
+ <translation></translation>
</message>
<message>
<location line="+4"/>
<source>low-medium</source>
- <translation type="unfinished"></translation>
+ <translation></translation>
</message>
<message>
<location line="+1"/>
<source>low</source>
- <translation type="unfinished"></translation>
+ <translation></translation>
</message>
<message>
<location line="+1"/>
<source>lowest</source>
- <translation type="unfinished"></translation>
+ <translation></translation>
</message>
<message>
<location line="+155"/>
<source>DUST</source>
- <translation type="unfinished"></translation>
+ <translation></translation>
</message>
<message>
<location line="+10"/>
- <source>This label turns red, if the transaction size is bigger than 10000 bytes.
+ <source>This label turns red, if the transaction size is bigger than 1000 bytes.
This means a fee of at least %1 per kb is required.
Can vary +/- 1 Byte per input.</source>
- <translation type="unfinished"></translation>
+ <translation>Помечается красным, если размер транзакции превышает 1000 байт.
+
+ Это означает, что требуется комиссия как минимум %1 за 1кб.</translation>
</message>
<message>
<location line="+1"/>
This label turns red, if the priority is smaller than "medium".
This means a fee of at least %1 per kb is required.</source>
- <translation type="unfinished"></translation>
+ <translation>Транзакции с более высоким приоритетом с большей вероятностью попадут в блок.
+
+Помечается красным, если приоритет ниже "medium".
+
+ Это означает, что будет требоваться комиссия как минимум %2.</translation>
</message>
<message>
<location line="+1"/>
This means a fee of at least %2 is required.
- Amounts below 0.546 times the minimum relay fee are shown as DUST.</source>
- <translation type="unfinished"></translation>
+ Amounts below the minimum fee are shown as DUST.</source>
+ <translation>Помечается красным, если какому-либо из получателей будет отправлено менее чем %1.
+
+ Это означает, что будет требоваться комиссия как минимум %2.
+
+ Суммы ниже минимальной комиссии отображаются как DUST.</translation>
</message>
<message>
<location line="+1"/>
<source>This label turns red, if the change is smaller than %1.
This means a fee of at least %2 is required.</source>
- <translation type="unfinished"></translation>
+ <translation>Помечается красным, если сдача менее чем %1.
+
+ Это означает, что будет требоваться комиссия как минимум %2.</translation>
</message>
<message>
<location line="+37"/>
<location line="+66"/>
<source>(no label)</source>
- <translation type="unfinished">[нет метки]</translation>
+ <translation>[нет метки]</translation>
</message>
<message>
<location line="-9"/>
<source>change from %1 (%2)</source>
- <translation type="unfinished"></translation>
+ <translation></translation>
</message>
<message>
<location line="+1"/>
<source>(change)</source>
- <translation type="unfinished"></translation>
+ <translation></translation>
</message>
<message>
<location line="-593"/>
<message>
<location line="+5"/>
<source>Copy low output</source>
- <translation type="unfinished"></translation>
+ <translation></translation>
</message>
<message>
<location line="+1"/>
<translation>Приоритет</translation>
</message>
<message>
+ <location line="+344"/>
+ <source>Weight</source>
+ <translation>Вес</translation>
+ </message>
+ <message>
<location line="-23"/>
<source>Label</source>
<translation>Метка</translation>
<location line="+86"/>
<location line="+38"/>
<source>0.00 NVC</source>
- <translation type="unfinished"></translation>
+ <translation>0.00 NVC</translation>
</message>
<message>
<location line="+131"/>
<message>
<location line="+77"/>
<source>Quantity:</source>
- <translation type="unfinished">Количество:</translation>
+ <translation>Количество:</translation>
</message>
<message>
<location line="+22"/>
<location line="+35"/>
<source>0</source>
- <translation type="unfinished"></translation>
+ <translation>0</translation>
</message>
<message>
<location line="-19"/>
<source>Bytes:</source>
- <translation type="unfinished">Размер:</translation>
+ <translation>Размер:</translation>
</message>
<message>
<location line="+51"/>
<source>Amount:</source>
- <translation type="unfinished"></translation>
+ <translation>Сумма:</translation>
</message>
<message>
<location line="+22"/>
<location line="+86"/>
<location line="+86"/>
<location line="+32"/>
- <source>0.00 BTC</source>
- <translation type="unfinished">123.456 BTC {0.00 ?}</translation>
+ <source>0.00 NVC</source>
+ <translation>0.00 NVC</translation>
</message>
<message>
<location line="-191"/>
<source>Priority:</source>
- <translation type="unfinished">Приоритет:</translation>
+ <translation>Приоритет:</translation>
</message>
<message>
<location line="+19"/>
<source>medium</source>
- <translation type="unfinished"></translation>
+ <translation>medium</translation>
</message>
<message>
<location line="+32"/>
<source>Fee:</source>
- <translation type="unfinished">Комиссия:</translation>
+ <translation>Комиссия:</translation>
</message>
<message>
<location line="+35"/>
<source>Low Output:</source>
- <translation type="unfinished">Мелкие входы:</translation>
+ <translation>Мелкие выходы:</translation>
</message>
<message>
<location line="+19"/>
<source>no</source>
- <translation type="unfinished">нет</translation>
+ <translation>нет</translation>
</message>
<message>
<location line="+32"/>
<source>After Fee:</source>
- <translation type="unfinished">С комиссией:</translation>
+ <translation>С комиссией:</translation>
</message>
<message>
<location line="+35"/>
<source>Change</source>
- <translation type="unfinished"></translation>
+ <translation>Сдача</translation>
</message>
<message>
<location line="+50"/>
</message>
<message>
<source>Specify wallet file (within data directory)</source>
- <translation type="obsolete">Указать файл кошелька (в пределах DATA директории)</translation>
+ <translation>Указать файл кошелька (в пределах DATA директории)</translation>
</message>
<message>
<location line="-1"/>
</message>
<message>
<location line="+23"/>
- <source>Find peers using DNS lookup (default: 0)</source>
- <translation type="unfinished">Искать узлы с помощью DNS (по умолчанию: 1) {0)?}</translation>
+ <source>Find peers using DNS lookup (default: 1)</source>
+ <translation>Искать узлы с помощью DNS (по умолчанию: 1)</translation>
+ </message>
+ <message>
+ <source>Sync checkpoints policy (default: strict)</source>
+ <translation>Политика синхронизированных меток (по умолчанию: strict)</translation>
</message>
<message>
<location line="+5"/>
<translation>Не удалось начать прослушивание на порту. Используйте -listen=0 если вас это устраивает.</translation>
</message>
<message>
- <source>Find peers using DNS lookup (default: 1)</source>
- <translation type="obsolete">Искать узлы с помощью DNS (по умолчанию: 1)</translation>
- </message>
- <message>
- <source>Sync checkpoints policy (default: strict)</source>
- <translation type="obsolete">Политика синхронизированных меток (по умолчанию: strict)</translation>
- </message>
- <message>
<location line="+12"/>
<source>Invalid -tor address: '%s'</source>
<translation>Неверный адрес -tor: '%s'</translation>
<translation>Обновить бумажник до последнего формата</translation>
</message>
<message>
+ <location line="+120"/>
+ <source>Require a confirmations for change (default: 0)</source>
+ <translation>Требовать подтверждения для сдачи (по умолчанию: 0)</translation>
+ </message>
+ <message>
+ <location line="+121"/>
+ <source>Enforce transaction scripts to use canonical PUSH operators (default: 1)</source>
+ <translation>Требовать от скриптов использования стандартных PUSH операторов (по умолчанию: 1)</translation>
+ </message>
+ <message>
<location line="-16"/>
<source>Set key pool size to <n> (default: 100)</source>
<translation>Установить размер запаса ключей в <n> (по умолчанию: 100)</translation>
<translation>Комиссия на килобайт, добавляемая к вашим транзакциям</translation>
</message>
<message>
+ <location line="-3"/>
+ <source>When creating transactions, ignore inputs with value less than this (default: %s)</source>
+ <translation>При создании транзакций игнорировать входы с суммой ниже указанной (по умолчанию: %s)</translation>
+ </message>
+ <message>
<location line="+19"/>
<source>Loading wallet...</source>
<translation>Загрузка бумажника...</translation>
filter->setSourceModel(model->getTransactionTableModel());
filter->setLimit(NUM_ITEMS);
filter->setDynamicSortFilter(true);
- filter->setSortRole(Qt::EditRole);
+// filter->setSortRole(Qt::EditRole);
+ filter->setSortRole(TransactionTableModel::DateRole);
filter->sort(TransactionTableModel::Status, Qt::DescendingOrder);
ui->listTransactions->setModel(filter);
ui->lineEditCoinControlChange->setFont(GUIUtil::bitcoinAddressFont());
connect(ui->pushButtonCoinControl, SIGNAL(clicked()), this, SLOT(coinControlButtonClicked()));
connect(ui->checkBoxCoinControlChange, SIGNAL(stateChanged(int)), this, SLOT(coinControlChangeChecked(int)));
- connect(ui->lineEditCoinControlChange, SIGNAL(textEdited(const QString &)), this, SLOT(coinControlChangeEdited(const QString &)));
// Coin Control: clipboard actions
QAction *clipboardQuantityAction = new QAction(tr("Copy quantity"), this);
if(!model)
return;
+ if (ui->lineEditCoinControlChange->isEnabled())
+ {
+ if(!ui->lineEditCoinControlChange->hasAcceptableInput() ||
+ (model && !model->validateAddress(ui->lineEditCoinControlChange->text())))
+ {
+ ui->lineEditCoinControlChange->setValid(false);
+ valid = false;
+ }
+ }
+
for(int i = 0; i < ui->entries->count(); ++i)
{
SendCoinsEntry *entry = qobject_cast<SendCoinsEntry*>(ui->entries->itemAt(i)->widget());
}
ui->lineEditCoinControlChange->setEnabled((state == Qt::Checked));
- ui->labelCoinControlChangeLabel->setEnabled((state == Qt::Checked));
+// ui->labelCoinControlChangeLabel->setEnabled((state == Qt::Checked));
+ ui->addressBookButton->setEnabled((state == Qt::Checked));
+ ui->pasteButton->setEnabled((state == Qt::Checked));
}
-// Coin Control: custom change address changed
-void SendCoinsDialog::coinControlChangeEdited(const QString & text)
+void SendCoinsDialog::on_pasteButton_clicked()
{
- if (model)
- {
- CoinControlDialog::coinControl->destChange = CBitcoinAddress(text.toStdString()).Get();
+ // Paste text from clipboard into recipient field
+ ui->lineEditCoinControlChange->setText(QApplication::clipboard()->text());
+}
- // label for the change address
- ui->labelCoinControlChangeLabel->setStyleSheet("QLabel{color:black;}");
- if (text.isEmpty())
- ui->labelCoinControlChangeLabel->setText("");
- else if (!CBitcoinAddress(text.toStdString()).IsValid())
- {
- ui->labelCoinControlChangeLabel->setStyleSheet("QLabel{color:red;}");
- ui->labelCoinControlChangeLabel->setText(tr("WARNING: Invalid Bitcoin address"));
- }
- else
- {
- QString associatedLabel = model->getAddressTableModel()->labelForAddress(text);
- if (!associatedLabel.isEmpty())
- ui->labelCoinControlChangeLabel->setText(associatedLabel);
- else
- {
- CPubKey pubkey;
- CKeyID keyid;
- CBitcoinAddress(text.toStdString()).GetKeyID(keyid);
- if (model->getPubKey(keyid, pubkey))
- ui->labelCoinControlChangeLabel->setText(tr("(no label)"));
- else
- {
- ui->labelCoinControlChangeLabel->setStyleSheet("QLabel{color:red;}");
- ui->labelCoinControlChangeLabel->setText(tr("WARNING: unknown change address"));
- }
- }
- }
+void SendCoinsDialog::on_addressBookButton_clicked()
+{
+ if(!model)
+ return;
+ AddressBookPage dlg(AddressBookPage::ForSending, AddressBookPage::SendingTab, this);
+ dlg.setModel(model->getAddressTableModel());
+ if(dlg.exec())
+ {
+ ui->lineEditCoinControlChange->setText(dlg.getReturnValue());
}
}
void updateRemoveEnabled();
void setBalance(qint64 balance, qint64 stake, qint64 unconfirmedBalance, qint64 immatureBalance);
+ void on_addressBookButton_clicked();
+ void on_pasteButton_clicked();
+
private:
Ui::SendCoinsDialog *ui;
WalletModel *model;
void coinControlFeatureChanged(bool);
void coinControlButtonClicked();
void coinControlChangeChecked(int);
- void coinControlChangeEdited(const QString &);
void coinControlUpdateLabels();
void coinControlClipboardQuantity();
void coinControlClipboardAmount();
transactionProxyModel->setSortCaseSensitivity(Qt::CaseInsensitive);
transactionProxyModel->setFilterCaseSensitivity(Qt::CaseInsensitive);
- transactionProxyModel->setSortRole(Qt::EditRole);
+// transactionProxyModel->setSortRole(Qt::EditRole);
+ transactionProxyModel->setSortRole(TransactionTableModel::DateRole);
transactionView->setModel(transactionProxyModel);
transactionView->setAlternatingRowColors(true);
return retval;
}
+void WalletModel::getStakeWeight(uint64& nMinWeight, uint64& nMaxWeight, uint64& nWeight)
+{
+ wallet->GetStakeWeight(*wallet, nMinWeight, nMaxWeight, nWeight);
+}
+
+void WalletModel::getStakeWeightFromValue(const int64& nTime, const int64& nValue, uint64& nWeight)
+{
+ wallet->GetStakeWeightFromValue(nTime, nValue, nWeight);
+}
+
+bool WalletModel::dumpWallet(const QString &filename)
+{
+ return DumpWallet(wallet, filename.toLocal8Bit().data());
+}
+
+bool WalletModel::importWallet(const QString &filename)
+{
+ return ImportWallet(wallet, filename.toLocal8Bit().data());
+}
+
bool WalletModel::backupWallet(const QString &filename)
{
return BackupWallet(*wallet, filename.toLocal8Bit().data());
// Wallet backup
bool backupWallet(const QString &filename);
+ bool dumpWallet(const QString &filename);
+ bool importWallet(const QString &filename);
+
+ void getStakeWeight(quint64& nMinWeight, quint64& nMaxWeight, quint64& nWeight);
+ void getStakeWeightFromValue(const qint64& nTime, const qint64& nValue, quint64& nWeight);
+
// RAI object for unlocking wallet, returned by requestUnlock()
class UnlockContext
{
if (fHelp || params.size() < 1 || params.size() > 1 || AmountFromValue(params[0]) < MIN_TX_FEE)
throw runtime_error(
"settxfee <amount>\n"
- "<amount> is a real and is rounded to the nearest 0.01");
+ "<amount> is a real and is rounded to the nearest " + FormatMoney(MIN_TX_FEE));
nTransactionFee = AmountFromValue(params[0]);
- nTransactionFee = (nTransactionFee / CENT) * CENT; // round to cent
+ nTransactionFee = (nTransactionFee / MIN_TX_FEE) * MIN_TX_FEE; // round to minimum fee
return true;
}
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#include <iostream>
-#include <fstream>
-
#include "init.h" // for pwalletMain
#include "bitcoinrpc.h"
#include "ui_interface.h"
#include "base58.h"
-#include <boost/date_time/posix_time/posix_time.hpp>
-#include <boost/lexical_cast.hpp>
-#include <boost/variant/get.hpp>
-#include <boost/algorithm/string.hpp>
-
#define printf OutputDebugStringF
using namespace json_spirit;
void EnsureWalletIsUnlocked();
-namespace bt = boost::posix_time;
-
-// Extended DecodeDumpTime implementation, see this page for details:
-// http://stackoverflow.com/questions/3786201/parsing-of-date-time-from-string-boost
-const std::locale formats[] = {
- std::locale(std::locale::classic(),new bt::time_input_facet("%Y-%m-%dT%H:%M:%SZ")),
- std::locale(std::locale::classic(),new bt::time_input_facet("%Y-%m-%d %H:%M:%S")),
- std::locale(std::locale::classic(),new bt::time_input_facet("%Y/%m/%d %H:%M:%S")),
- std::locale(std::locale::classic(),new bt::time_input_facet("%d.%m.%Y %H:%M:%S")),
- std::locale(std::locale::classic(),new bt::time_input_facet("%Y-%m-%d"))
-};
-
-const size_t formats_n = sizeof(formats)/sizeof(formats[0]);
-
-std::time_t pt_to_time_t(const bt::ptime& pt)
-{
- bt::ptime timet_start(boost::gregorian::date(1970,1,1));
- bt::time_duration diff = pt - timet_start;
- return diff.ticks()/bt::time_duration::rep_type::ticks_per_second;
-}
-
-int64 DecodeDumpTime(const std::string& s)
-{
- bt::ptime pt;
-
- for(size_t i=0; i<formats_n; ++i)
- {
- std::istringstream is(s);
- is.imbue(formats[i]);
- is >> pt;
- if(pt != bt::ptime()) break;
- }
-
- return pt_to_time_t(pt);
-}
-
-std::string static EncodeDumpTime(int64 nTime) {
- return DateTimeStrFormat("%Y-%m-%dT%H:%M:%SZ", nTime);
-}
-
-std::string static EncodeDumpString(const std::string &str) {
- std::stringstream ret;
- BOOST_FOREACH(unsigned char c, str) {
- if (c <= 32 || c >= 128 || c == '%') {
- ret << '%' << HexStr(&c, &c + 1);
- } else {
- ret << c;
- }
- }
- return ret.str();
-}
-
-std::string DecodeDumpString(const std::string &str) {
- std::stringstream ret;
- for (unsigned int pos = 0; pos < str.length(); pos++) {
- unsigned char c = str[pos];
- if (c == '%' && pos+2 < str.length()) {
- c = (((str[pos+1]>>6)*9+((str[pos+1]-'0')&15)) << 4) |
- ((str[pos+2]>>6)*9+((str[pos+2]-'0')&15));
- pos += 2;
- }
- ret << c;
- }
- return ret.str();
-}
-
class CTxDump
{
public:
if (fHelp || params.size() != 1)
throw runtime_error(
"importwallet <filename>\n"
- "Imports keys from a wallet dump file (see dumpwallet).");
+ "Imports keys from a wallet dump file (see dumpwallet)."
+ + HelpRequiringPassphrase());
EnsureWalletIsUnlocked();
- ifstream file;
- file.open(params[0].get_str().c_str());
- if (!file.is_open())
- throw JSONRPCError(RPC_INVALID_PARAMETER, "Cannot open wallet dump file");
-
- int64 nTimeBegin = pindexBest->nTime;
-
- bool fGood = true;
-
- while (file.good()) {
- std::string line;
- std::getline(file, line);
- if (line.empty() || line[0] == '#')
- continue;
-
- std::vector<std::string> vstr;
- boost::split(vstr, line, boost::is_any_of(" "));
- if (vstr.size() < 2)
- continue;
- CBitcoinSecret vchSecret;
- if (!vchSecret.SetString(vstr[0]))
- continue;
-
- bool fCompressed;
- CKey key;
- CSecret secret = vchSecret.GetSecret(fCompressed);
- key.SetSecret(secret, fCompressed);
- CKeyID keyid = key.GetPubKey().GetID();
-
- if (pwalletMain->HaveKey(keyid)) {
- printf("Skipping import of %s (key already present)\n", CBitcoinAddress(keyid).ToString().c_str());
- continue;
- }
- int64 nTime = DecodeDumpTime(vstr[1]);
- std::string strLabel;
- bool fLabel = true;
- for (unsigned int nStr = 2; nStr < vstr.size(); nStr++) {
- if (boost::algorithm::starts_with(vstr[nStr], "#"))
- break;
- if (vstr[nStr] == "change=1")
- fLabel = false;
- if (vstr[nStr] == "reserve=1")
- fLabel = false;
- if (boost::algorithm::starts_with(vstr[nStr], "label=")) {
- strLabel = DecodeDumpString(vstr[nStr].substr(6));
- fLabel = true;
- }
- }
- printf("Importing %s...\n", CBitcoinAddress(keyid).ToString().c_str());
- if (!pwalletMain->AddKey(key)) {
- fGood = false;
- continue;
- }
- pwalletMain->mapKeyMetadata[keyid].nCreateTime = nTime;
- if (fLabel)
- pwalletMain->SetAddressBookName(keyid, strLabel);
- nTimeBegin = std::min(nTimeBegin, nTime);
- }
- file.close();
-
- CBlockIndex *pindex = pindexBest;
- while (pindex && pindex->pprev && pindex->nTime > nTimeBegin - 7200)
- pindex = pindex->pprev;
-
- printf("Rescanning last %i blocks\n", pindexBest->nHeight - pindex->nHeight + 1);
- pwalletMain->ScanForWalletTransactions(pindex);
- pwalletMain->ReacceptWalletTransactions();
- pwalletMain->MarkDirty();
-
- if (!fGood)
- throw JSONRPCError(RPC_WALLET_ERROR, "Error adding some keys to wallet");
+ if(!ImportWallet(pwalletMain, params[0].get_str().c_str()))
+ throw JSONRPCError(RPC_WALLET_ERROR, "Error adding some keys to wallet");
return Value::null;
}
-
Value dumpprivkey(const Array& params, bool fHelp)
{
if (fHelp || params.size() != 1)
if (fHelp || params.size() != 1)
throw runtime_error(
"dumpwallet <filename>\n"
- "Dumps all wallet keys in a human-readable format.");
+ "Dumps all wallet keys in a human-readable format."
+ + HelpRequiringPassphrase());
EnsureWalletIsUnlocked();
- ofstream file;
- file.open(params[0].get_str().c_str());
- if (!file.is_open())
- throw JSONRPCError(RPC_INVALID_PARAMETER, "Cannot open wallet dump file");
-
- std::map<CKeyID, int64> mapKeyBirth;
-
- std::set<CKeyID> setKeyPool;
-
- pwalletMain->GetKeyBirthTimes(mapKeyBirth);
+ if(!DumpWallet(pwalletMain, params[0].get_str().c_str() ))
+ throw JSONRPCError(RPC_WALLET_ERROR, "Error dumping wallet keys to file");
- pwalletMain->GetAllReserveKeys(setKeyPool);
-
- // sort time/key pairs
- std::vector<std::pair<int64, CKeyID> > vKeyBirth;
- for (std::map<CKeyID, int64>::const_iterator it = mapKeyBirth.begin(); it != mapKeyBirth.end(); it++) {
- vKeyBirth.push_back(std::make_pair(it->second, it->first));
- }
- mapKeyBirth.clear();
- std::sort(vKeyBirth.begin(), vKeyBirth.end());
-
- // produce output
- file << strprintf("# Wallet dump created by NovaCoin %s (%s)\n", CLIENT_BUILD.c_str(), CLIENT_DATE.c_str());
- file << strprintf("# * Created on %s\n", EncodeDumpTime(GetTime()).c_str());
- file << strprintf("# * Best block at time of backup was %i (%s),\n", nBestHeight, hashBestChain.ToString().c_str());
- file << strprintf("# mined on %s\n", EncodeDumpTime(pindexBest->nTime).c_str());
- file << "\n";
- for (std::vector<std::pair<int64, CKeyID> >::const_iterator it = vKeyBirth.begin(); it != vKeyBirth.end(); it++) {
- const CKeyID &keyid = it->second;
- std::string strTime = EncodeDumpTime(it->first);
- std::string strAddr = CBitcoinAddress(keyid).ToString();
- bool IsCompressed;
-
- CKey key;
- if (pwalletMain->GetKey(keyid, key)) {
- if (pwalletMain->mapAddressBook.count(keyid)) {
- CSecret secret = key.GetSecret(IsCompressed);
- file << strprintf("%s %s label=%s # addr=%s\n", CBitcoinSecret(secret, IsCompressed).ToString().c_str(), strTime.c_str(), EncodeDumpString(pwalletMain->mapAddressBook[keyid]).c_str(), strAddr.c_str());
- } else if (setKeyPool.count(keyid)) {
- CSecret secret = key.GetSecret(IsCompressed);
- file << strprintf("%s %s reserve=1 # addr=%s\n", CBitcoinSecret(secret, IsCompressed).ToString().c_str(), strTime.c_str(), strAddr.c_str());
- } else {
- CSecret secret = key.GetSecret(IsCompressed);
- file << strprintf("%s %s change=1 # addr=%s\n", CBitcoinSecret(secret, IsCompressed).ToString().c_str(), strTime.c_str(), strAddr.c_str());
- }
- }
- }
- file << "\n";
- file << "# End of dump\n";
- file.close();
return Value::null;
}
if (fHelp || params.size() < 2 || params.size() > 4)
throw runtime_error(
"sendtoaddress <novacoinaddress> <amount> [comment] [comment-to]\n"
- "<amount> is a real and is rounded to the nearest 0.000001"
+ "<amount> is a real and is rounded to the nearest " + FormatMoney(MIN_TXOUT_AMOUNT)
+ HelpRequiringPassphrase());
CBitcoinAddress address(params[0].get_str());
if (fHelp || params.size() < 3 || params.size() > 6)
throw runtime_error(
"sendfrom <fromaccount> <tonovacoinaddress> <amount> [minconf=1] [comment] [comment-to]\n"
- "<amount> is a real and is rounded to the nearest 0.000001"
+ "<amount> is a real and is rounded to the nearest " + FormatMoney(MIN_TXOUT_AMOUNT)
+ HelpRequiringPassphrase());
string strAccount = AccountFromValue(params[0]);
case TX_PUBKEYHASH: return "pubkeyhash";
case TX_SCRIPTHASH: return "scripthash";
case TX_MULTISIG: return "multisig";
+ case TX_NULL_DATA: return "nulldata";
}
return NULL;
}
// Sender provides N pubkeys, receivers provides M signatures
mTemplates.insert(make_pair(TX_MULTISIG, CScript() << OP_SMALLINTEGER << OP_PUBKEYS << OP_SMALLINTEGER << OP_CHECKMULTISIG));
+
+ // Empty, provably prunable, data-carrying output
+ mTemplates.insert(make_pair(TX_NULL_DATA, CScript() << OP_RETURN << OP_SMALLDATA));
}
// Shortcut for pay-to-script-hash, which are more constrained than the other types:
else
break;
}
+ else if (opcode2 == OP_SMALLDATA)
+ {
+ // small pushdata, <= 80 bytes
+ if (vch1.size() > 80)
+ break;
+ }
else if (opcode1 != opcode2 || vch1 != vch2)
{
// Others must match exactly
switch (whichTypeRet)
{
case TX_NONSTANDARD:
+ case TX_NULL_DATA:
return false;
case TX_PUBKEY:
keyID = CPubKey(vSolutions[0]).GetID();
{
case TX_NONSTANDARD:
return -1;
+ case TX_NULL_DATA:
+ return 1;
case TX_PUBKEY:
return 1;
case TX_PUBKEYHASH:
return -1;
}
-bool IsStandard(const CScript& scriptPubKey)
+bool IsStandard(const CScript& scriptPubKey, txnouttype& whichType)
{
vector<valtype> vSolutions;
- txnouttype whichType;
if (!Solver(scriptPubKey, whichType, vSolutions))
return false;
switch (whichType)
{
case TX_NONSTANDARD:
+ case TX_NULL_DATA:
return false;
case TX_PUBKEY:
keyID = CPubKey(vSolutions[0]).GetID();
vector<valtype> vSolutions;
if (!Solver(scriptPubKey, typeRet, vSolutions))
return false;
+ if (typeRet == TX_NULL_DATA)
+ return true;
if (typeRet == TX_MULTISIG)
{
switch (txType)
{
case TX_NONSTANDARD:
+ case TX_NULL_DATA:
// Don't know anything about this, assume bigger one is correct:
if (sigs1.size() >= sigs2.size())
return PushAll(sigs1);
TX_PUBKEYHASH,
TX_SCRIPTHASH,
TX_MULTISIG,
+ TX_NULL_DATA,
};
class CNoDestination {
// template matching params
+ OP_SMALLDATA = 0xf9,
OP_SMALLINTEGER = 0xfa,
OP_PUBKEYS = 0xfb,
OP_PUBKEYHASH = 0xfd,
bool EvalScript(std::vector<std::vector<unsigned char> >& stack, const CScript& script, const CTransaction& txTo, unsigned int nIn, int nHashType);
bool Solver(const CScript& scriptPubKey, txnouttype& typeRet, std::vector<std::vector<unsigned char> >& vSolutionsRet);
int ScriptSigArgsExpected(txnouttype t, const std::vector<std::vector<unsigned char> >& vSolutions);
-bool IsStandard(const CScript& scriptPubKey);
+bool IsStandard(const CScript& scriptPubKey, txnouttype& whichType);
bool IsMine(const CKeyStore& keystore, const CScript& scriptPubKey);
bool IsMine(const CKeyStore& keystore, const CTxDestination &dest);
void ExtractAffectedKeys(const CKeyStore &keystore, const CScript& scriptPubKey, std::vector<CKeyID> &vKeys);
--- /dev/null
+#ifndef BITCOIN_TIMESTAMPS_H
+#define BITCOIN_TIMESTAMPS_H
+
+static const unsigned int ENTROPY_SWITCH_TIME = 1362791041; // Sat, 09 Mar 2013 01:04:01 GMT
+static const unsigned int STAKE_SWITCH_TIME = 1371686400; // Thu, 20 Jun 2013 00:00:00 GMT
+static const unsigned int TARGETS_SWITCH_TIME = 1374278400; // Sat, 20 Jul 2013 00:00:00 GMT
+static const unsigned int CHAINCHECKS_SWITCH_TIME = 1379635200; // Fri, 20 Sep 2013 00:00:00 GMT
+static const unsigned int STAKECURVE_SWITCH_TIME = 1382227200; // Sun, 20 Oct 2013 00:00:00 GMT
+static const unsigned int FEE_SWITCH_TIME = 1405814400; // Sun, 20 Jul 2014 00:00:00 GMT
+
+static const unsigned int VALIDATION_SWITCH_TIME = 1408492800; // Wed, 20 Aug 2014 00:00:00 GMT
+
+#endif
return Write(string("strCheckpointPubKey"), strPubKey);
}
+bool CTxDB::ReadModifierUpgradeTime(unsigned int& nUpgradeTime)
+{
+ return Read(string("nUpgradeTime"), nUpgradeTime);
+}
+
+bool CTxDB::WriteModifierUpgradeTime(const unsigned int& nUpgradeTime)
+{
+ return Write(string("nUpgradeTime"), nUpgradeTime);
+}
+
static CBlockIndex *InsertBlockIndex(uint256 hash)
{
if (hash == 0)
bool WriteSyncCheckpoint(uint256 hashCheckpoint);
bool ReadCheckpointPubKey(std::string& strPubKey);
bool WriteCheckpointPubKey(const std::string& strPubKey);
+ bool ReadModifierUpgradeTime(unsigned int& nUpgradeTime);
+ bool WriteModifierUpgradeTime(const unsigned int& nUpgradeTime);
bool LoadBlockIndex();
private:
bool LoadBlockIndexGuts();
MORE = 0x00010000,
SETUP = 0x00020000,
// Force blocking, modal message box dialog (not just OS notification)
- MODAL = 0x00040000
+ MODAL = 0x00040000,
+
+ /** Predefined combinations for certain default usage cases */
+ MSG_INFORMATION = ICON_INFORMATION,
+ MSG_WARNING = (ICON_WARNING | OK | MODAL),
+ MSG_ERROR = (ICON_ERROR | OK | MODAL)
+
};
/** Show message box. */
#include <boost/program_options/parsers.hpp>
#include <boost/filesystem.hpp>
#include <boost/filesystem/fstream.hpp>
+
+#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/foreach.hpp>
#include <boost/thread.hpp>
#include <openssl/crypto.h>
using namespace std;
+namespace bt = boost::posix_time;
map<string, string> mapArgs;
map<string, vector<string> > mapMultiArgs;
CMedianFilter<int64> vTimeOffsets(200,0);
bool fReopenDebugLog = false;
+// Extended DecodeDumpTime implementation, see this page for details:
+// http://stackoverflow.com/questions/3786201/parsing-of-date-time-from-string-boost
+const std::locale formats[] = {
+ std::locale(std::locale::classic(),new bt::time_input_facet("%Y-%m-%dT%H:%M:%SZ")),
+ std::locale(std::locale::classic(),new bt::time_input_facet("%Y-%m-%d %H:%M:%S")),
+ std::locale(std::locale::classic(),new bt::time_input_facet("%Y/%m/%d %H:%M:%S")),
+ std::locale(std::locale::classic(),new bt::time_input_facet("%d.%m.%Y %H:%M:%S")),
+ std::locale(std::locale::classic(),new bt::time_input_facet("%Y-%m-%d"))
+};
+
+const size_t formats_n = sizeof(formats)/sizeof(formats[0]);
+
+std::time_t pt_to_time_t(const bt::ptime& pt)
+{
+ bt::ptime timet_start(boost::gregorian::date(1970,1,1));
+ bt::time_duration diff = pt - timet_start;
+ return diff.ticks()/bt::time_duration::rep_type::ticks_per_second;
+}
+
// Init OpenSSL library multithreading support
static CCriticalSection** ppmutexOpenSSL;
void locking_callback(int mode, int i, const char* file, int line)
}
+int64 DecodeDumpTime(const std::string& s)
+{
+ bt::ptime pt;
+
+ for(size_t i=0; i<formats_n; ++i)
+ {
+ std::istringstream is(s);
+ is.imbue(formats[i]);
+ is >> pt;
+ if(pt != bt::ptime()) break;
+ }
+
+ return pt_to_time_t(pt);
+}
+
+std::string EncodeDumpTime(int64 nTime) {
+ return DateTimeStrFormat("%Y-%m-%dT%H:%M:%SZ", nTime);
+}
+
+std::string EncodeDumpString(const std::string &str) {
+ std::stringstream ret;
+ BOOST_FOREACH(unsigned char c, str) {
+ if (c <= 32 || c >= 128 || c == '%') {
+ ret << '%' << HexStr(&c, &c + 1);
+ } else {
+ ret << c;
+ }
+ }
+ return ret.str();
+}
+
+std::string DecodeDumpString(const std::string &str) {
+ std::stringstream ret;
+ for (unsigned int pos = 0; pos < str.length(); pos++) {
+ unsigned char c = str[pos];
+ if (c == '%' && pos+2 < str.length()) {
+ c = (((str[pos+1]>>6)*9+((str[pos+1]-'0')&15)) << 4) |
+ ((str[pos+2]>>6)*9+((str[pos+2]-'0')&15));
+ pos += 2;
+ }
+ ret << c;
+ }
+ return ret.str();
+}
+
bool WildcardMatch(const char* psz, const char* mask)
{
while (true)
std::string DecodeBase32(const std::string& str);
std::string EncodeBase32(const unsigned char* pch, size_t len);
std::string EncodeBase32(const std::string& str);
+std::string EncodeDumpTime(int64 nTime);
+int64 DecodeDumpTime(const std::string& s);
+std::string EncodeDumpString(const std::string &str);
+std::string DecodeDumpString(const std::string &str);
void ParseParameters(int argc, const char*const argv[]);
bool WildcardMatch(const char* psz, const char* mask);
bool WildcardMatch(const std::string& str, const std::string& mask);
// if sub-cent change is required, the fee must be raised to at least MIN_TX_FEE
// or until nChange becomes zero
// NOTE: this depends on the exact behaviour of GetMinFee
- if (nFeeRet < MIN_TX_FEE && nChange > 0 && nChange < CENT)
+ if (wtxNew.nTime < FEE_SWITCH_TIME && !fTestNet)
{
- int64 nMoveToFee = min(nChange, MIN_TX_FEE - nFeeRet);
- nChange -= nMoveToFee;
- nFeeRet += nMoveToFee;
- }
+ if (nFeeRet < MIN_TX_FEE && nChange > 0 && nChange < CENT)
+ {
+ int64 nMoveToFee = min(nChange, MIN_TX_FEE - nFeeRet);
+ nChange -= nMoveToFee;
+ nFeeRet += nMoveToFee;
+ }
- // ppcoin: sub-cent change is moved to fee
- if (nChange > 0 && nChange < MIN_TXOUT_AMOUNT)
- {
- nFeeRet += nChange;
- nChange = 0;
+ // sub-cent change is moved to fee
+ if (nChange > 0 && nChange < CENT)
+ {
+ nFeeRet += nChange;
+ nChange = 0;
+ }
}
if (nChange > 0)
// Check that enough fee is included
int64 nPayFee = nTransactionFee * (1 + (int64)nBytes / 1000);
- int64 nMinFee = wtxNew.GetMinFee(1, false, GMF_SEND, nBytes);
+ bool fAllowFree = CTransaction::AllowFree(dPriority);
+
+ // Disable free transactions until 1 July 2014
+ if (!fTestNet && wtxNew.nTime < FEE_SWITCH_TIME)
+ {
+ fAllowFree = false;
+ }
+
+ int64 nMinFee = wtxNew.GetMinFee(1, fAllowFree, GMF_SEND, nBytes);
if (nFeeRet < max(nPayFee, nMinFee))
{
return CreateTransaction(vecSend, wtxNew, reservekey, nFeeRet, coinControl);
}
+void CWallet::GetStakeWeightFromValue(const int64& nTime, const int64& nValue, uint64& nWeight)
+{
+ int64 nTimeWeight = GetWeight(nTime, (int64)GetTime());
+
+ // If time weight is lower or equal to zero then weight is zero.
+ if (nTimeWeight <= 0)
+ {
+ nWeight = 0;
+ return;
+ }
+
+ CBigNum bnCoinDayWeight = CBigNum(nValue) * nTimeWeight / COIN / (24 * 60 * 60);
+ nWeight = bnCoinDayWeight.getuint64();
+}
+
+
// NovaCoin: get current stake weight
bool CWallet::GetStakeWeight(const CKeyStore& keystore, uint64& nMinWeight, uint64& nMaxWeight, uint64& nWeight)
{
return error("CreateCoinStake : exceeded coinstake size limit");
// Check enough fee is paid
- if (nMinFee < txNew.GetMinFee() - MIN_TX_FEE)
+ if (nMinFee < txNew.GetMinFee(1, false, GMF_BLOCK, nBytes) - CENT)
{
- nMinFee = txNew.GetMinFee() - MIN_TX_FEE;
+ nMinFee = txNew.GetMinFee(1, false, GMF_BLOCK, nBytes) - CENT;
continue; // try signing again
}
else
pcoin->WriteToDisk();
}
}
+
+ }
+
+ if(IsMine((CTransaction)*pcoin) && (pcoin->IsCoinBase() || pcoin->IsCoinStake()) && pcoin->GetDepthInMainChain() == 0)
+ {
+ printf("FixSpentCoins %s tx %s\n", fCheckOnly ? "found" : "removed", pcoin->GetHash().ToString().c_str());
+ if (!fCheckOnly)
+ {
+ EraseFromWallet(pcoin->GetHash());
+ }
}
}
}
bool CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey);
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);
std::string SendMoney(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, bool fAskFee=false);
#include "walletdb.h"
#include "wallet.h"
+
+#include <iostream>
+#include <fstream>
+
#include <boost/version.hpp>
#include <boost/filesystem.hpp>
+#include <boost/algorithm/string.hpp>
+
+#include <boost/date_time/posix_time/posix_time.hpp>
+#include <boost/lexical_cast.hpp>
+#include <boost/variant/get.hpp>
+#include <boost/algorithm/string.hpp>
using namespace std;
using namespace boost;
return false;
}
+bool DumpWallet(CWallet* pwallet, const string& strDest)
+{
+
+ if (!pwallet->fFileBacked)
+ return false;
+ while (!fShutdown)
+ {
+ // Populate maps
+ std::map<CKeyID, int64> mapKeyBirth;
+ std::set<CKeyID> setKeyPool;
+ pwallet->GetKeyBirthTimes(mapKeyBirth);
+ pwallet->GetAllReserveKeys(setKeyPool);
+
+ // sort time/key pairs
+ std::vector<std::pair<int64, CKeyID> > vKeyBirth;
+ for (std::map<CKeyID, int64>::const_iterator it = mapKeyBirth.begin(); it != mapKeyBirth.end(); it++) {
+ vKeyBirth.push_back(std::make_pair(it->second, it->first));
+ }
+ mapKeyBirth.clear();
+ std::sort(vKeyBirth.begin(), vKeyBirth.end());
+
+ // open outputfile as a stream
+ ofstream file;
+ file.open(strDest.c_str());
+ if (!file.is_open())
+ return false;
+
+ // produce output
+ file << strprintf("# Wallet dump created by NovaCoin %s (%s)\n", CLIENT_BUILD.c_str(), CLIENT_DATE.c_str());
+ file << strprintf("# * Created on %s\n", EncodeDumpTime(GetTime()).c_str());
+ file << strprintf("# * Best block at time of backup was %i (%s),\n", nBestHeight, hashBestChain.ToString().c_str());
+ file << strprintf("# mined on %s\n", EncodeDumpTime(pindexBest->nTime).c_str());
+ file << "\n";
+ for (std::vector<std::pair<int64, CKeyID> >::const_iterator it = vKeyBirth.begin(); it != vKeyBirth.end(); it++) {
+ const CKeyID &keyid = it->second;
+ std::string strTime = EncodeDumpTime(it->first);
+ std::string strAddr = CBitcoinAddress(keyid).ToString();
+ bool IsCompressed;
+
+ CKey key;
+ if (pwallet->GetKey(keyid, key)) {
+ if (pwallet->mapAddressBook.count(keyid)) {
+ CSecret secret = key.GetSecret(IsCompressed);
+ file << strprintf("%s %s label=%s # addr=%s\n",
+ CBitcoinSecret(secret, IsCompressed).ToString().c_str(),
+ strTime.c_str(),
+ EncodeDumpString(pwallet->mapAddressBook[keyid]).c_str(),
+ strAddr.c_str());
+ } else if (setKeyPool.count(keyid)) {
+ CSecret secret = key.GetSecret(IsCompressed);
+ file << strprintf("%s %s reserve=1 # addr=%s\n",
+ CBitcoinSecret(secret, IsCompressed).ToString().c_str(),
+ strTime.c_str(),
+ strAddr.c_str());
+ } else {
+ CSecret secret = key.GetSecret(IsCompressed);
+ file << strprintf("%s %s change=1 # addr=%s\n",
+ CBitcoinSecret(secret, IsCompressed).ToString().c_str(),
+ strTime.c_str(),
+ strAddr.c_str());
+ }
+ }
+ }
+ file << "\n";
+ file << "# End of dump\n";
+ file.close();
+ return true;
+ }
+ return false;
+}
+
+
+bool ImportWallet(CWallet *pwallet, const string& strLocation)
+{
+
+ if (!pwallet->fFileBacked)
+ return false;
+ while (!fShutdown)
+ {
+ // open inputfile as stream
+ ifstream file;
+ file.open(strLocation.c_str());
+ if (!file.is_open())
+ return false;
+
+ int64 nTimeBegin = pindexBest->nTime;
+
+ bool fGood = true;
+
+ // read through input file checking and importing keys into wallet.
+ while (file.good()) {
+ std::string line;
+ std::getline(file, line);
+ if (line.empty() || line[0] == '#')
+ continue;
+
+ std::vector<std::string> vstr;
+ boost::split(vstr, line, boost::is_any_of(" "));
+ if (vstr.size() < 2)
+ continue;
+ CBitcoinSecret vchSecret;
+ if (!vchSecret.SetString(vstr[0]))
+ continue;
+
+ bool fCompressed;
+ CKey key;
+ CSecret secret = vchSecret.GetSecret(fCompressed);
+ key.SetSecret(secret, fCompressed);
+ CKeyID keyid = key.GetPubKey().GetID();
+
+ if (pwallet->HaveKey(keyid)) {
+ printf("Skipping import of %s (key already present)\n", CBitcoinAddress(keyid).ToString().c_str());
+ continue;
+ }
+ int64 nTime = DecodeDumpTime(vstr[1]);
+ std::string strLabel;
+ bool fLabel = true;
+ for (unsigned int nStr = 2; nStr < vstr.size(); nStr++) {
+ if (boost::algorithm::starts_with(vstr[nStr], "#"))
+ break;
+ if (vstr[nStr] == "change=1")
+ fLabel = false;
+ if (vstr[nStr] == "reserve=1")
+ fLabel = false;
+ if (boost::algorithm::starts_with(vstr[nStr], "label=")) {
+ strLabel = DecodeDumpString(vstr[nStr].substr(6));
+ fLabel = true;
+ }
+ }
+ printf("Importing %s...\n", CBitcoinAddress(keyid).ToString().c_str());
+ if (!pwallet->AddKey(key)) {
+ fGood = false;
+ continue;
+ }
+ pwallet->mapKeyMetadata[keyid].nCreateTime = nTime;
+ if (fLabel)
+ pwallet->SetAddressBookName(keyid, strLabel);
+ nTimeBegin = std::min(nTimeBegin, nTime);
+ }
+ file.close();
+
+ // rescan block chain looking for coins from new keys
+ CBlockIndex *pindex = pindexBest;
+ while (pindex && pindex->pprev && pindex->nTime > nTimeBegin - 7200)
+ pindex = pindex->pprev;
+
+ printf("Rescanning last %i blocks\n", pindexBest->nHeight - pindex->nHeight + 1);
+ pwallet->ScanForWalletTransactions(pindex);
+ pwallet->ReacceptWalletTransactions();
+ pwallet->MarkDirty();
+
+ return fGood;
+
+ }
+
+ return false;
+
+}
+
+
//
// Try to (very carefully!) recover wallet.dat if there is a problem.
//