Merge remote-tracking branch 'janko33bd/Blackcoin-Lore' into rpc-updates-0.13
This commit is contained in:
@@ -15,7 +15,6 @@ fi
|
||||
|
||||
DESC=""
|
||||
SUFFIX=""
|
||||
LAST_COMMIT_DATE=""
|
||||
if [ -e "$(which git 2>/dev/null)" -a "$(git rev-parse --is-inside-work-tree 2>/dev/null)" = "true" ]; then
|
||||
# clean 'dirty' status of touched files that haven't been modified
|
||||
git diff >/dev/null 2>/dev/null
|
||||
@@ -29,9 +28,6 @@ if [ -e "$(which git 2>/dev/null)" -a "$(git rev-parse --is-inside-work-tree 2>/
|
||||
# otherwise generate suffix from git, i.e. string like "59887e8-dirty"
|
||||
SUFFIX=$(git rev-parse --short HEAD)
|
||||
git diff-index --quiet HEAD -- || SUFFIX="$SUFFIX-dirty"
|
||||
|
||||
# get a string like "2012-04-10 16:27:19 +0200"
|
||||
LAST_COMMIT_DATE="$(git log -n 1 --format="%ci")"
|
||||
fi
|
||||
|
||||
if [ -n "$DESC" ]; then
|
||||
@@ -45,7 +41,4 @@ fi
|
||||
# only update build.h if necessary
|
||||
if [ "$INFO" != "$NEWINFO" ]; then
|
||||
echo "$NEWINFO" >"$FILE"
|
||||
if [ -n "$LAST_COMMIT_DATE" ]; then
|
||||
echo "#define BUILD_DATE \"$LAST_COMMIT_DATE\"" >> "$FILE"
|
||||
fi
|
||||
fi
|
||||
|
||||
@@ -67,16 +67,7 @@ const std::string CLIENT_NAME("Satoshi");
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef BUILD_DATE
|
||||
#ifdef GIT_COMMIT_DATE
|
||||
#define BUILD_DATE GIT_COMMIT_DATE
|
||||
#else
|
||||
#define BUILD_DATE __DATE__ ", " __TIME__
|
||||
#endif
|
||||
#endif
|
||||
|
||||
const std::string CLIENT_BUILD(BUILD_DESC CLIENT_VERSION_SUFFIX);
|
||||
const std::string CLIENT_DATE(BUILD_DATE);
|
||||
|
||||
static std::string FormatVersion(int nVersion)
|
||||
{
|
||||
|
||||
@@ -59,7 +59,6 @@ static const int CLIENT_VERSION =
|
||||
|
||||
extern const std::string CLIENT_NAME;
|
||||
extern const std::string CLIENT_BUILD;
|
||||
extern const std::string CLIENT_DATE;
|
||||
|
||||
|
||||
std::string FormatFullVersion();
|
||||
|
||||
@@ -252,7 +252,7 @@ static std::string RequestMethodString(HTTPRequest::RequestMethod m)
|
||||
/** HTTP request callback */
|
||||
static void http_request_cb(struct evhttp_request* req, void* arg)
|
||||
{
|
||||
std::auto_ptr<HTTPRequest> hreq(new HTTPRequest(req));
|
||||
std::unique_ptr<HTTPRequest> hreq(new HTTPRequest(req));
|
||||
|
||||
LogPrint("http", "Received a %s request for %s from %s\n",
|
||||
RequestMethodString(hreq->GetRequestMethod()), hreq->GetURI(), hreq->GetPeer().ToString());
|
||||
@@ -288,7 +288,7 @@ static void http_request_cb(struct evhttp_request* req, void* arg)
|
||||
|
||||
// Dispatch to worker thread
|
||||
if (i != iend) {
|
||||
std::auto_ptr<HTTPWorkItem> item(new HTTPWorkItem(hreq.release(), path, i->handler));
|
||||
std::unique_ptr<HTTPWorkItem> item(new HTTPWorkItem(hreq.release(), path, i->handler));
|
||||
assert(workQueue);
|
||||
if (workQueue->Enqueue(item.get()))
|
||||
item.release(); /* if true, queue took ownership */
|
||||
|
||||
@@ -758,7 +758,7 @@ void InitLogging()
|
||||
fLogIPs = GetBoolArg("-logips", DEFAULT_LOGIPS);
|
||||
|
||||
LogPrintf("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n");
|
||||
LogPrintf("Bitcoin version %s (%s)\n", FormatFullVersion(), CLIENT_DATE);
|
||||
LogPrintf("Bitcoin version %s\n", FormatFullVersion());
|
||||
}
|
||||
|
||||
/** Initialize bitcoin.
|
||||
|
||||
71
src/main.cpp
71
src/main.cpp
@@ -48,6 +48,10 @@
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <boost/filesystem/fstream.hpp>
|
||||
#include <boost/math/distributions/poisson.hpp>
|
||||
#include <boost/multi_index_container.hpp>
|
||||
#include <boost/multi_index/member.hpp>
|
||||
#include <boost/multi_index/ordered_index.hpp>
|
||||
#include <boost/multi_index/sequenced_index.hpp>
|
||||
#include <boost/thread.hpp>
|
||||
|
||||
using namespace std;
|
||||
@@ -1883,9 +1887,32 @@ void UpdateCoins(const CTransaction& tx, CValidationState &state, CCoinsViewCach
|
||||
UpdateCoins(tx, state, inputs, txundo, nHeight);
|
||||
}
|
||||
|
||||
class CachingTransactionSignatureCheckerWithBlockReader : public CachingTransactionSignatureChecker, public BaseBlockReader {
|
||||
class CachingTransactionSignatureCheckerWithBlockReader : public CachingTransactionSignatureChecker, public BaseBlockReader
|
||||
{
|
||||
typedef std::pair<uint256, CTransaction> CoinbaseCacheItem;
|
||||
typedef boost::multi_index_container<
|
||||
CoinbaseCacheItem,
|
||||
boost::multi_index::indexed_by<
|
||||
boost::multi_index::sequenced<>,
|
||||
boost::multi_index::ordered_unique<
|
||||
boost::multi_index::member<CoinbaseCacheItem, uint256, &CoinbaseCacheItem::first>
|
||||
>
|
||||
>
|
||||
> CoinbaseCacheContainer;
|
||||
|
||||
int nHeight;
|
||||
uint256 hash;
|
||||
|
||||
mutable boost::mutex mutexCache;
|
||||
mutable CoinbaseCacheContainer cacheCoinbase; // block hash -> block coinbase
|
||||
|
||||
void UpdateCache(const CoinbaseCacheItem& coinbase) const;
|
||||
|
||||
CTransaction ReadBlockCoinbase(CBlockIndex* pblockindex) const;
|
||||
|
||||
public:
|
||||
const unsigned int MAX_COUNT_ACKS_CACHE = 1000;
|
||||
|
||||
public:
|
||||
virtual int GetBlockNumber() const;
|
||||
|
||||
@@ -1893,12 +1920,14 @@ public:
|
||||
|
||||
virtual bool CountAcks(const std::vector<unsigned char>& chainId, int periodAck, int periodLiveness, int& positive, int& negative) const;
|
||||
|
||||
CachingTransactionSignatureCheckerWithBlockReader(const CTransaction* txToIn, unsigned int nInIn, const CAmount& amount, bool storeIn, int height)
|
||||
:CachingTransactionSignatureChecker(txToIn, nInIn, storeIn), nHeight(height), hash(txToIn->GetHash())
|
||||
{
|
||||
}
|
||||
CachingTransactionSignatureCheckerWithBlockReader(const CTransaction* txToIn, unsigned int nInIn, bool storeIn, int height);
|
||||
};
|
||||
|
||||
CachingTransactionSignatureCheckerWithBlockReader::CachingTransactionSignatureCheckerWithBlockReader(const CTransaction* txToIn, unsigned int nInIn, bool storeIn, int height)
|
||||
: CachingTransactionSignatureChecker(txToIn, nInIn, storeIn), nHeight(height), hash(txToIn->GetHash())
|
||||
{
|
||||
}
|
||||
|
||||
int CachingTransactionSignatureCheckerWithBlockReader::GetBlockNumber() const
|
||||
{
|
||||
return nHeight;
|
||||
@@ -1913,13 +1942,30 @@ CTransaction CachingTransactionSignatureCheckerWithBlockReader::GetBlockCoinbase
|
||||
return CTransaction();
|
||||
|
||||
CBlockIndex* pblockindex = chainActive[nHeight];
|
||||
|
||||
{
|
||||
boost::lock_guard<boost::mutex> lock(mutexCache);
|
||||
CoinbaseCacheContainer::nth_index<1>::type::iterator it = cacheCoinbase.get<1>().find(*pblockindex->phashBlock);
|
||||
if (it != cacheCoinbase.get<1>().end())
|
||||
return it->second;
|
||||
}
|
||||
|
||||
CTransaction coinbase = ReadBlockCoinbase(pblockindex);
|
||||
if (!coinbase.IsNull())
|
||||
UpdateCache(std::make_pair(*pblockindex->phashBlock, coinbase));
|
||||
|
||||
return coinbase;
|
||||
}
|
||||
|
||||
CTransaction CachingTransactionSignatureCheckerWithBlockReader::ReadBlockCoinbase(CBlockIndex* pblockindex) const
|
||||
{
|
||||
|
||||
CBlock block;
|
||||
|
||||
if (fHavePruned && !(pblockindex->nStatus & BLOCK_HAVE_DATA) && pblockindex->nTx > 0)
|
||||
return CTransaction();
|
||||
|
||||
if(!ReadBlockFromDisk(block, pblockindex, Params().GetConsensus()))
|
||||
if (!ReadBlockFromDisk(block, pblockindex, Params().GetConsensus()))
|
||||
return CTransaction();
|
||||
|
||||
if (block.vtx.empty())
|
||||
@@ -1931,6 +1977,17 @@ CTransaction CachingTransactionSignatureCheckerWithBlockReader::GetBlockCoinbase
|
||||
return block.vtx[0];
|
||||
}
|
||||
|
||||
void CachingTransactionSignatureCheckerWithBlockReader::UpdateCache(const CachingTransactionSignatureCheckerWithBlockReader::CoinbaseCacheItem& coinbase) const
|
||||
{
|
||||
boost::lock_guard<boost::mutex> lock(mutexCache);
|
||||
std::pair<CoinbaseCacheContainer::iterator, bool> result = cacheCoinbase.push_front(coinbase);
|
||||
if (!result.second) {
|
||||
cacheCoinbase.relocate(cacheCoinbase.begin(), result.first);
|
||||
} else if (cacheCoinbase.size() > MAX_COUNT_ACKS_CACHE) {
|
||||
cacheCoinbase.pop_back();
|
||||
}
|
||||
}
|
||||
|
||||
bool CachingTransactionSignatureCheckerWithBlockReader::CountAcks(const std::vector<unsigned char>& chainId, int periodAck, int periodLiveness, int& positiveAcks, int& negativeAcks) const
|
||||
{
|
||||
std::vector<unsigned char> hashSpend(hash.begin(), hash.end());
|
||||
@@ -1939,7 +1996,7 @@ bool CachingTransactionSignatureCheckerWithBlockReader::CountAcks(const std::vec
|
||||
|
||||
bool CScriptCheck::operator()() {
|
||||
const CScript &scriptSig = ptxTo->vin[nIn].scriptSig;
|
||||
if (!VerifyScript(scriptSig, scriptPubKey, nFlags, CachingTransactionSignatureChecker(ptxTo, nIn, nHeight, cacheStore), &error)) {
|
||||
if (!VerifyScript(scriptSig, scriptPubKey, nFlags, CachingTransactionSignatureChecker(ptxTo, nIn, cacheStore), &error)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
||||
@@ -96,7 +96,7 @@ int64_t GetMaxTransactionTime(CBlock* pblock)
|
||||
CBlockTemplate* CreateNewBlock(const CChainParams& chainparams, const CScript& scriptPubKeyIn, int64_t* pFees, bool fProofOfStake)
|
||||
{
|
||||
// Create new block
|
||||
auto_ptr<CBlockTemplate> pblocktemplate(new CBlockTemplate());
|
||||
std::unique_ptr<CBlockTemplate> pblocktemplate(new CBlockTemplate());
|
||||
if(!pblocktemplate.get())
|
||||
return NULL;
|
||||
CBlock *pblock = &pblocktemplate->block; // pointer for convenience
|
||||
|
||||
@@ -162,7 +162,7 @@ UniValue generate(const UniValue& params, bool fHelp)
|
||||
UniValue blockHashes(UniValue::VARR);
|
||||
while (nHeight < nHeightEnd)
|
||||
{
|
||||
auto_ptr<CBlockTemplate> pblocktemplate(CreateNewBlock(Params(), coinbaseScript->reserveScript, 0, false));
|
||||
std::unique_ptr<CBlockTemplate> pblocktemplate(CreateNewBlock(Params(), coinbaseScript->reserveScript, 0, false));
|
||||
if (!pblocktemplate.get())
|
||||
throw JSONRPCError(RPC_INTERNAL_ERROR, "Couldn't create new block");
|
||||
CBlock *pblock = &pblocktemplate->block;
|
||||
|
||||
@@ -12,9 +12,52 @@
|
||||
#include <tuple>
|
||||
#include <utility>
|
||||
|
||||
#define LIMITED_VECTOR(obj, n) REF(MakeLimitedVector<n>(obj))
|
||||
|
||||
const unsigned char ACK_LABEL[] = {0x41, 0x43, 0x4B, 0x3A}; // "ACK:"
|
||||
const size_t ACK_LABEL_LENGTH = sizeof(ACK_LABEL);
|
||||
|
||||
template <size_t Limit, typename U>
|
||||
class LimitedVector
|
||||
{
|
||||
protected:
|
||||
std::vector<U>& vec;
|
||||
|
||||
public:
|
||||
LimitedVector(std::vector<U>& vec) : vec(vec) {}
|
||||
|
||||
template <typename Stream>
|
||||
void Unserialize(Stream& s, int, int = 0)
|
||||
{
|
||||
size_t size = ReadCompactSize(s);
|
||||
if (size > Limit) {
|
||||
throw std::ios_base::failure("String length limit exceeded");
|
||||
}
|
||||
vec.resize(size);
|
||||
if (size != 0)
|
||||
s.read((char*)&vec[0], size);
|
||||
}
|
||||
|
||||
template <typename Stream>
|
||||
void Serialize(Stream& s, int, int = 0) const
|
||||
{
|
||||
WriteCompactSize(s, vec.size());
|
||||
if (!vec.empty())
|
||||
s.write((char*)&vec[0], vec.size());
|
||||
}
|
||||
|
||||
unsigned int GetSerializeSize(int, int = 0) const
|
||||
{
|
||||
return GetSizeOfCompactSize(vec.size()) + vec.size();
|
||||
}
|
||||
};
|
||||
|
||||
template <size_t N, typename U>
|
||||
LimitedVector<N, U> MakeLimitedVector(std::vector<U>& obj)
|
||||
{
|
||||
return LimitedVector<N, U>(obj);
|
||||
}
|
||||
|
||||
class Ack
|
||||
{
|
||||
public:
|
||||
@@ -28,26 +71,28 @@ public:
|
||||
{
|
||||
uint64_t nPayload = 0;
|
||||
if (!ser_action.ForRead())
|
||||
nPayload = CalcPayloadSize();
|
||||
nPayload = CalcPayloadSize(nType, nVersion);
|
||||
READWRITE(COMPACTSIZE(nPayload));
|
||||
READWRITE(prefix);
|
||||
if (nPayload == 0)
|
||||
throw std::runtime_error("Not valid ACK");
|
||||
READWRITE(LIMITED_VECTOR(prefix, 32));
|
||||
// Empty preimage should not be serialized
|
||||
if (ser_action.ForRead()) {
|
||||
uint64_t nPrefix = prefix.size();
|
||||
nPrefix += GetSizeOfCompactSize(nPrefix);
|
||||
if (nPayload > nPrefix)
|
||||
READWRITE(preimage);
|
||||
if (CalcPayloadSize() != nPayload)
|
||||
READWRITE(LIMITED_VECTOR(preimage, 32));
|
||||
if (CalcPayloadSize(nType, nVersion) != nPayload)
|
||||
throw std::runtime_error("Not valid ACK");
|
||||
} else {
|
||||
if (preimage.size() > 0)
|
||||
READWRITE(preimage);
|
||||
READWRITE(LIMITED_VECTOR(preimage, 32));
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t CalcPayloadSize() const
|
||||
unsigned int CalcPayloadSize(int nType, int nVersion) const
|
||||
{
|
||||
uint64_t nPayload = 0;
|
||||
unsigned int nPayload = 0;
|
||||
nPayload += GetSizeOfCompactSize(prefix.size());
|
||||
nPayload += prefix.size();
|
||||
// Empty preimage should not be serialized
|
||||
@@ -58,12 +103,6 @@ public:
|
||||
return nPayload;
|
||||
}
|
||||
|
||||
uint64_t CalcSize() const
|
||||
{
|
||||
uint64_t nPayload = CalcPayloadSize();
|
||||
return GetSizeOfCompactSize(nPayload) + nPayload;
|
||||
}
|
||||
|
||||
Ack() {}
|
||||
Ack(std::vector<unsigned char> prefix, std::vector<unsigned char> preimage = std::vector<unsigned char>())
|
||||
: prefix(prefix), preimage(preimage)
|
||||
@@ -83,14 +122,14 @@ public:
|
||||
{
|
||||
uint64_t sizePayload = 0;
|
||||
if (!ser_action.ForRead())
|
||||
sizePayload = CalcPayloadSize();
|
||||
sizePayload = CalcPayloadSize(nType, nVersion);
|
||||
READWRITE(COMPACTSIZE(sizePayload));
|
||||
if (ser_action.ForRead()) {
|
||||
uint64_t read = 0;
|
||||
unsigned int read = 0;
|
||||
while (read < sizePayload) {
|
||||
Ack ack;
|
||||
READWRITE(ack);
|
||||
read += ack.CalcSize();
|
||||
read += ack.GetSerializeSize(nType, nVersion);
|
||||
vAck.push_back(ack);
|
||||
}
|
||||
if (read != sizePayload)
|
||||
@@ -102,24 +141,15 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t CalcPayloadSize() const
|
||||
unsigned int CalcPayloadSize(int nType, int nVersion) const
|
||||
{
|
||||
uint64_t nPayload = 0;
|
||||
unsigned int nPayload = 0;
|
||||
for (const Ack& ack : vAck) {
|
||||
nPayload += ack.CalcSize();
|
||||
nPayload += ack.GetSerializeSize(nType, nVersion);
|
||||
}
|
||||
return nPayload;
|
||||
}
|
||||
|
||||
uint64_t CalcSize() const
|
||||
{
|
||||
uint64_t nSize = 0;
|
||||
uint64_t nPayloadSize = CalcPayloadSize();
|
||||
nSize += GetSizeOfCompactSize(nPayloadSize);
|
||||
nSize += nPayloadSize;
|
||||
return nSize;
|
||||
}
|
||||
|
||||
AckList() {}
|
||||
AckList(std::vector<Ack> acks) : vAck(acks) {}
|
||||
};
|
||||
@@ -137,32 +167,23 @@ public:
|
||||
{
|
||||
uint64_t nPayload = 0;
|
||||
if (!ser_action.ForRead())
|
||||
nPayload = CalcPayloadSize();
|
||||
nPayload = CalcPayloadSize(nType, nVersion);
|
||||
READWRITE(COMPACTSIZE(nPayload));
|
||||
READWRITE(chainId);
|
||||
READWRITE(LIMITED_VECTOR(chainId, 20));
|
||||
READWRITE(ackList);
|
||||
if (ser_action.ForRead() && nPayload != CalcPayloadSize())
|
||||
if (ser_action.ForRead() && nPayload != CalcPayloadSize(nType, nVersion))
|
||||
throw std::runtime_error("Not valid CHAIN ACK LIST");
|
||||
}
|
||||
|
||||
uint64_t CalcPayloadSize() const
|
||||
unsigned int CalcPayloadSize(int nType, int nVersion) const
|
||||
{
|
||||
uint64_t nPayload = 0;
|
||||
unsigned int nPayload = 0;
|
||||
nPayload += GetSizeOfCompactSize(chainId.size());
|
||||
nPayload += chainId.size();
|
||||
nPayload += ackList.CalcSize();
|
||||
nPayload += ackList.GetSerializeSize(nType, nVersion);
|
||||
return nPayload;
|
||||
}
|
||||
|
||||
uint64_t CalcSize() const
|
||||
{
|
||||
uint64_t nSize = 0;
|
||||
uint64_t nPayloadSize = CalcPayloadSize();
|
||||
nSize += GetSizeOfCompactSize(nPayloadSize);
|
||||
nSize += nPayloadSize;
|
||||
return nSize;
|
||||
}
|
||||
|
||||
ChainAckList& operator<<(Ack ack)
|
||||
{
|
||||
ackList.vAck.push_back(ack);
|
||||
@@ -185,14 +206,14 @@ public:
|
||||
{
|
||||
uint64_t sizePayload = 0;
|
||||
if (!ser_action.ForRead())
|
||||
sizePayload = CalcPayloadSize();
|
||||
sizePayload = CalcPayloadSize(nType, nVersion);
|
||||
READWRITE(COMPACTSIZE(sizePayload));
|
||||
if (ser_action.ForRead()) {
|
||||
uint64_t read = 0;
|
||||
while (read < sizePayload) {
|
||||
ChainAckList chainAcks;
|
||||
READWRITE(chainAcks);
|
||||
read += chainAcks.CalcSize();
|
||||
read += chainAcks.GetSerializeSize(nType, nVersion);
|
||||
vChainAcks.push_back(chainAcks);
|
||||
}
|
||||
if (read != sizePayload)
|
||||
@@ -204,24 +225,15 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t CalcPayloadSize() const
|
||||
unsigned int CalcPayloadSize(int nType, int nVersion) const
|
||||
{
|
||||
uint64_t nPayloadSize = 0;
|
||||
unsigned int nPayloadSize = 0;
|
||||
for (const auto& chainAcks : vChainAcks) {
|
||||
nPayloadSize += chainAcks.CalcSize();
|
||||
nPayloadSize += chainAcks.GetSerializeSize(nType, nVersion);
|
||||
}
|
||||
return nPayloadSize;
|
||||
}
|
||||
|
||||
uint64_t CalcSize() const
|
||||
{
|
||||
uint64_t nSize = 0;
|
||||
uint64_t nPayloadSize = CalcPayloadSize();
|
||||
nSize += GetSizeOfCompactSize(nPayloadSize);
|
||||
nSize += nPayloadSize;
|
||||
return nSize;
|
||||
}
|
||||
|
||||
FullAckList& operator<<(Ack ack)
|
||||
{
|
||||
if (!vChainAcks.empty()) {
|
||||
|
||||
@@ -51,6 +51,9 @@ typedef enum ScriptError_t
|
||||
|
||||
/* softfork safeness */
|
||||
SCRIPT_ERR_DISCOURAGE_UPGRADABLE_NOPS,
|
||||
|
||||
/* count acks */
|
||||
SCRIPT_ERR_COUNT_ACKS_INVALID_PARAM,
|
||||
|
||||
SCRIPT_ERR_ERROR_COUNT
|
||||
} ScriptError;
|
||||
|
||||
@@ -116,7 +116,7 @@ BOOST_AUTO_TEST_CASE(sign)
|
||||
{
|
||||
CScript sigSave = txTo[i].vin[0].scriptSig;
|
||||
txTo[i].vin[0].scriptSig = txTo[j].vin[0].scriptSig;
|
||||
bool sigOK = CScriptCheck(CCoins(txFrom, 0), txTo[i], 0, SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_STRICTENC, false)();
|
||||
bool sigOK = CScriptCheck(CCoins(txFrom, 0), txTo[i], 0, SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_STRICTENC, false, -1)();
|
||||
if (i == j)
|
||||
BOOST_CHECK_MESSAGE(sigOK, strprintf("VerifySignature %d %d", i, j));
|
||||
else
|
||||
|
||||
@@ -485,7 +485,7 @@ UniValue dumpwallet(const UniValue& params, bool fHelp)
|
||||
std::sort(vKeyBirth.begin(), vKeyBirth.end());
|
||||
|
||||
// produce output
|
||||
file << strprintf("# Wallet dump created by Bitcoin %s (%s)\n", CLIENT_BUILD, CLIENT_DATE);
|
||||
file << strprintf("# Wallet dump created by Bitcoin %s\n", CLIENT_BUILD);
|
||||
file << strprintf("# * Created on %s\n", EncodeDumpTime(GetTime()));
|
||||
file << strprintf("# * Best block at time of backup was %i (%s),\n", chainActive.Height(), chainActive.Tip()->GetBlockHash().ToString());
|
||||
file << strprintf("# mined on %s\n", EncodeDumpTime(chainActive.Tip()->GetBlockTime()));
|
||||
|
||||
Reference in New Issue
Block a user