[Dev] Documenting Feathercoin Specific Software settings - Part 1
-
Bringing Feathercoin up to Bitcoin Head
Ideally we need a method where 0.9.6.1 updates can be extracted, checked (against 0.6, 0.8.7 and 0.11) documented, then applied as a FTC settings commit to Bitcoin Head.
ToDo :
Investigate Cherry Pick
Investigate / document git and difference tools.The test and check of 0.6 is to ensure no Litecoin specific changes are required, subsequent to the move to Bitcoin core.
-
By “Bitcoin Head” do we mean the most up-to-date Bitcoin branch ?
I’m just thinking about things like OpenSSL version and how Bitcoin removed their Bignum.h stuff i after v 0.9
-
Exactly, we get up to date with head, then auto build from there.
These additional settings can be added to the FTC settings commit mechanism. Needs some work to set up, like the auto build, it would be a place to store zxing, ssl etc for our specific usage in FTC.(At least as an option while we remove / alter our stuff)
Once we are up to head, the FTC settings (system / guide / docs) will be used to remove, or adjust new Bitcoin options, we don’t need.
-
Feathercoin specific changes made to convert Bitcoin to FTC 0.9.6
Update configure.ac
https://github.com/FeatherCoin/Feathercoin/commit/b54262ee3a81a0a14204f306aebc9ce89623fba1
Contains following changes and additions :
+define(_CLIENT_VERSION_IS_RELEASE, true)
(Currently) This line is set to false during development, and is changed to true for the release version.
+AC_INIT([Feathercoin Core],[_CLIENT_VERSION_MAJOR._CLIENT_VERSION_MINOR._CLIENT_VERSION_REVISION],[[email protected]],[feathercoin])
In this line, the feathercoin address has incorrectly been set to china, needs urgent fix / check.
Note : Work done on this by @Aciddude & @Wellenreiter , need open source email / ticket system, email address to forum / forum add-on auto ticket / support@feathercoin / investigate possible automatic solution ideas.
Github Issues intergration, redmine / ticketing / option on forum drop down to se support emails.
https://zapier.com/zapbook/email/github/
+AC_ARG_ENABLE([glibc-back-compat], [AS_HELP_STRING([--enable-glibc-back-compat], [enable backwards compatibility with glibc and libstdc++])], [use_glibc_compat=$enableval], [use_glibc_compat=no])
Back compatibility included for an FTC specific add-on (which and why?)
+# detect POSIX or GNU variant of strerror_r AC_FUNC_STRERROR_R
Variable included for library compatibility check.
if test x$use_glibc_compat != xno; then Plus : Lines 323 to 329
Block of code is included to do the “If test” of glib compatibility.
Bitcoin :
AC_MSG_ERROR(No working boost sleep implementation found. If on ubuntu 13.10 with libboost1.54-all-dev remove libboost.1.54-all-dev and use libboost1.53-all-dev)
In Feathercoin :
AC_MSG_ERROR(No working boost sleep implementation found.)
The error message for incorrect boost version is changed.
AC_ARG_WITH([daemon], [AS_HELP_STRING([--with-daemon], [with daemon (default is yes)])], [build_feathercoind=$withval], [build_feathercoind=yes])
Changed from build_bitcoincoind to build_feathercoind , name change
BITCOIN_QT_PATH_PROGS([PROTOC], [protoc],$protoc_bin_path) AC_MSG_CHECKING([whether to build feathercoind]) AM_CONDITIONAL([BUILD_BITCOIND], [test x$build_feathercoind = xyes]) AC_MSG_RESULT($build_feathercoind)
Check wither to build feathercoind , name change
if test x$use_ipv6 = xyes; then lines 542 to 562
A block of code that defines what happens if ipv6 is enabled is removed.
dnl enable ipv6 support line 591 to 626
A block of code enabling ipv6 is removed
if test x$TARGET_OS = xwindows; then if test x$TARGET_OS = xwindows; then -CPPFLAGS="$CPPFLAGS -DSTATICLIB" +CPPFLAGS="$CPPFLAGS -DMINIUPNP_STATICLIB"
An “interface” change is made DSTATICLIB is replaced by DMINIUPNP_STATICLIB for windows builds.
-if test "x$use_tests$build_bitcoind$use_qt" = "xnonono"; then +if test "x$use_tests$build_feathercoind$use_qt" = "xnonono"; then
change due to (unnecessary?) variable name change earlier?
-AC_SUBST(USE_IPV6)
line to use ipv6 removed, why was this removed and not just switched off? why not use ipv6? etc … etc …
-
Feathercoin specific changes made to convert Bitcoin to FTC 0.9.6
Update Makefile.am
https://github.com/FeatherCoin/Feathercoin/commit/dc86a5f1ba025c2490fd6981cc015b60900362f3
Quite a few changes made, mostly name change related. Have a FTC specific version of makefile?
-rm -rf test_bitcoin.coverage/ total.coverage/ +rm -rf test_bitcoin.coverage/ total.coverage/ $(OSX_APP)
This line appears to be a clean up bug fix that should have gone up stream.
-
Feathercoin specific changes made to convert Bitcoin to FTC 0.9.6
chainparams.cpp
https://github.com/FeatherCoin/Feathercoin/commit/82440fcfdc1598bef263ec39d13906d354645e14
From - How to make an altcoin: https://bitcointalk.org/index.php?topic=1030365.0
In chainparams.cpp, edit the checkpoints
*Get your favorite programming editor, go to the newcoin/src/ directory, and open up chainparams.cpp.
Search for the string ‘mapCheckpoints’ and it will take you immediately to line 55, which sets a static variable named mapCheckpoints to a list of pairs – the first member of each pair is the block height, and the second is the hash of that block. The Bitcoin client uses these as it verifies the Bitcoin block chain. So if you leave those in, the newcoin client will be looking for blocks that don’t exist in the newcoin block chain. So get rid of ‘em, and put a place holder for your genesis block in instead. This place holder will be wrong, but we can’t fix it until after we mine a genesis block. After your edit, it should look like this:
Update chainparams.cpp
As it can be seen by the description, this file contains the infamous
+unsigned int pnSeed[] = and pchMessageStart[0]
- nuff said at moment.
Best way forward, maintain FTC version of chainparams.cpp,chainparams.cpp. FTC build uses FTC specific chainsparams etc ?? .
Other Notable changes :
const char* pszTimestamp = "NY Times 05/Oct/2011 Steve Jobs, Apple's Visionary, Dies at 56";
same as Litecoin, can’t change as is part of genesis block.
nDefaultPort = 19336; nRPCPort = 19337;
Here is where the default ports are set for communication over the internet.
genesis.nTime = 1396255061; genesis.nNonce = 3250989159; assert(hashGenesisBlock == uint256("0x8e8b634d2f2800398261b7adcfbb6ace490e1746e62123ec2bf8010f9fc98b17"));
FTC specific genesis parameters.
// Boost sucks, and should not be used. Workaround for Boost not being compatible with C++11;
At last … FTC or LTC specific documentation!
+ //static CRegTestParams regTestParams;
remove a Test variable.
case CChainParams::REGTEST: - pCurrentParams = ®TestParams; + //pCurrentParams = ®TestParams; + pCurrentParams = &testNetParams; break;
Change the test interface (break!)
chainparams.cpp
Second commit to chainparams.cpp
- const char* pszTimestamp = "NY Times 05/Oct/2011 Steve Jobs, Apple's Visionary, Dies at 56"; + const char* pszTimestamp = "NY Times 05/Oct/2011 Steve Jobs, Apple’s Visionary, Dies at 56";
Is this a change?
+ //vSeeds.push_back(CDNSSeedData("bitcoin.petertodd.org", "testnet-seed.bitcoin.petertodd.org")); + //vSeeds.push_back(CDNSSeedData("bluematt.me", "testnet-seed.bluematt.me"));
Comment out some seed stuff.
-
Feathercoin specific changes made to convert Bitcoin to FTC 0.9.6
https://github.com/FeatherCoin/Feathercoin/commit/d5913b435afedddd67da68416dc2dc8985e64f92
From - How to make an altcoin: https://bitcointalk.org/index.php?topic=1030365.0
main.cpp Part 1
What is main.cpp?
It just contains an apparently random collection of functions used by the program. It also declares some global structures such as the main lock, the transaction pool, orphan block tracking, and so on. It contains high-level block and transaction functions. Ironically, it does not contain the actual main function – that’s in init.cpp.+// Copyright (c) 2013-2014 The Feathercoin developers
name change in code description - copywrite dates, need update / check / how to deal with at head?
+#include "auxpow.h"
FTC (LTC?) specific variable added
+# error "Feathercoin cannot be compiled without assertions."
Name change from Bitcoin to Feathercoin in an error message
unsigned int nCoinCacheSize = 5000;
Note : possible un-optimised variable?
+// The 1st hard fork +const int nForkOne = 33000; +// The 2nd hard fork +const int nForkTwo = 87948; +// The 3rd hard fork +const int nForkThree = 204639;
Feathercoin specific information about which block forks are to / have occured on.
What is a Fork?
[Ref A:]
The word ‘fork’ in this context originates from open source software. Open source software is computer code, which is intended to be openly accessible and liberally used by anyone reading it. Open source software can be coded communally (such as with the GitHub platform), or alternatively can be copied locally and coded separately.
The development of software like this would allow to draw trees: each time the code was copied separately there would be a new branch. This would be called ‘forking’, since the same code would then develop in two parallel directions.
As we know, the Blockchain is decentralized, which by definition means there is no absolutely “correct” chain. Each node in the network downloads all the blocks to connect a chain, verifies them against the laws of math and Bitcoin and chooses the correct chain accordingly. For instance, if there is a block that has an invalid cryptographic signature, any chain including that block is invalid.A block will also be invalid if there is a violation of the Bitcoin rules such as, for instance, if a miner rewards themselves with 26 coins instead of 25 as per protocol. Either way, it is up to the individual to verify the validity of the blockchain. Therefore, it seems, if there are two conflicting chains, one is valid and the other is malicious.
[Ref A:] (https://blog.cex.io/bitcoin-dictionary/what-is-bitcoin-fork-14622)
int64_t CTransaction::nMinTxFee = 2000000; // Override with -mintxfee
Set the FTC value for minimum transaction fee, needs review procedure?
int64_t CTransaction::nMinRelayTxFee = 2000000;
Set the FTC value for minimum relay fee, needs review procedure?
What is a Relay fee
[Ref B:]
The transaction fee is a voluntary payment.
However, there are various limitations built into various common functionality. If you don’t pay an appropriate transaction fee, you can encounter problems with some of these limitations.
Under some circumstances, the Bitcoin Core wallet won’t broadcast its own transaction unless it has a large enough fee. This could be referred to as a minimum broadcast fee.
Under some circumstances, peer nodes running code based on BitcoinCore won’t relay a transaction unless it has a large enough fee. This could be referred to as a minimum relay fee.
Under some circumstances, some mining pools won’t confirm a transaction unless it has a large enough fee. This could be referred to as a minimum confirmation fee.
The point is, they are all just ways of talking about a minimum fee that a transaction must include if it is going to make it past a particular limitation.
If your wallet won’t broadcast the transaction, then nobody will ever know about it.
If your peers won’t relay your transaction, then your recipient might not see the transaction until it is confirmed, and it might not be confirmed for a very long time since many miners (and mining pools) won’t hear about it from their peers.
If many of the miners (and mining pools) won’t confirm it, then it may remain with 0 confirmations for a very long time. Depending on the wallet you are using, the transaction may expire if it isn’t confirmed, and the bitcoins could end up back in your wallet.
[Ref B:] DannyHamilton - (https://bitcointalk.org/index.php?topic=579460.0)
- map<uint256, CTransaction> mapOrphanTransactions; + struct COrphanTx { + CTransaction tx; + NodeId fromPeer; +}; + map<uint256, COrphanTx> mapOrphanTransactions; map<uint256, set<uint256> > mapOrphanTransactionsByPrev; + void EraseOrphansFor(NodeId peer);
Apparent interface change for orphan handling, from LTC? Required for scrypt element of FTC POW?
+ struct CBlockIndexWorkComparator line 89 to line 137
Is this just white space removal, can’t see change?
+ EraseOrphansFor(nodeid);
Line added from LTC?
+ mapOrphanTransactions[hash].tx = tx; + mapOrphanTransactions[hash].fromPeer = peer; line 465 to line 469
Block of code and Interface change to include scrypt requirements .
void EraseOrphansFor(NodeId peer) line 471 to line 487
Block of code and Interface change to include scrypt requirements .
- map<uint256, CTransaction>::iterator it = mapOrphanTransactions.lower_bound(randomhash); + map<uint256, COrphanTx>::iterator it = mapOrphanTransactions.lower_bound(randomhash);
There is a (LTC / scrypt?) interface change to COrphanTx.
+ AssertLockHeld(cs_main);
A lock is added
BOOST_FOREACH(const CTxIn& txin, tx.vin) { - // Biggest 'standard' txin is a 3-signature 3-of-3 CHECKMULTISIG - // pay-to-script-hash, which is 3 ~80-byte signatures, 3 - // ~65-byte public keys, plus a few script ops. - if (txin.scriptSig.size() > 500) { BOOST_FOREACH(const CTxIn& txin, tx.vin) { + // Biggest 'standard' txin is a 15-of-15 P2SH multisig with compressed + // keys. (remember the 520 byte limit on redeemScript size) That works + // out to a (15*(33+1))+3=513 byte redeemScript, 513+1+15*(73+1)=1624 + // bytes of scriptSig, which we round off to 1650 bytes for some minor + // future-proofing. That's also enough to spend a 20-of-20 + // CHECKMULTISIG scriptPubKey, though such a scriptPubKey is not + // considered standard) + if (txin.scriptSig.size() > 1650) {
Scrypt specific settings (LTC)
+ AssertLockHeld(cs_main);
A few more locks used in other functions.
- if (fAllowFree) + if (fAllowFree && mode != GMF_SEND)
Allow free block of code is removed, from LTC for scrypt?
BOOST_FOREACH(const CTxOut& txout, tx.vout) if (txout.nValue < CENT) - nMinFee = nBaseFee;
Block of code removed.
+ // Free transaction area + if (nBytes < 26000) + nMinFee = 0; + // Feathercoin + // To limit dust spam, add nBaseFee for each output less than DUST_SOFT_LIMIT + BOOST_FOREACH(const CTxOut& txout, tx.vout) + if (txout.nValue < DUST_SOFT_LIMIT) + nMinFee += nBaseFee;
Feathercoin code, dust soft limit.
Notes : ? How are dust levels min payments set ?
[FAQ] Where is Dust payment level set?
main.h /** Dust Soft Limit, allowed with additional fee per output / static const int64 DUST_SOFT_LIMIT = 100000; // 0.001 FTC /* Dust Hard Limit, ignored as wallet inputs (mininput default) */ static const int64 DUST_HARD_LIMIT = 1000; // 0.00001 FTC mininput - return error("%s : Deserialize or I/O error - %s", __PRETTY_FUNCTION__, e.what()); + return error("%s : Deserialize or I/O error - %s", __func__, e.what());
Interface change to __PRETTY_FUNCTION (LTC?)
fseek(file, postx.nTxOffset, SEEK_CUR); file >> txOut; file >> txOut; } catch (std::exception &e) { } catch (std::exception &e) { - return error("%s : Deserialize or I/O error - %s", __PRETTY_FUNCTION__, e.what()); + return error("%s : Deserialize or I/O error - %s", __func__, e.what());
Here the updated error message interface, shows a message when a seek through the database fails. This section contains further locks, which will be database write locks.
-
Feathercoin specific changes made to convert Bitcoin to FTC 0.9.6
https://github.com/FeatherCoin/Feathercoin/commit/d5913b435afedddd67da68416dc2dc8985e64f92
main.cpp Part 2
// Check the header - if (!CheckProofOfWork(block.GetHash(), block.nBits)) + if (!block.CheckProofOfWork(mapBlockIndex[block.GetHash()]->nHeight)) return error("ReadBlockFromDisk : Errors in block header"); return true;
This code checks the header, returns error, the new error interface is used for FTC.
These errors may write to the debug file, (which has a name change, hence interface change - check?)int64_t GetBlockValue(int nHeight, int64_t nFees) - int64_t nSubsidy = 50 * COIN; + int64_t nSubsidy = 200 * COIN; - int halvings = nHeight / Params().SubsidyHalvingInterval(); + if(nHeight >= nForkThree || (TestNet())) - // Force block reward to zero when right shift is undefined. + nSubsidy = 80 * COIN;
This is where the Block miners transaction fee is initially set.
// Subsidy is cut in half every 2100000 blocks, which will occur approximately every 4 years - nSubsidy >>= halvings; + nSubsidy >>= (nHeight / 1799985); // 200,010 blocks at 200FTC and 1,599,975 at 80FTC return nSubsidy + nFees;
In this section the halving criteria is set.
[FAQ] What is the halving?
[Ref C:]
Of all the rules in bitcoin’s code, few are as revered as the hard limit of bitcoin production.
The code dictates that 21 million coins will be released over the course of bitcoin’s lifecycle. By limiting the total amount of bitcoins that could be created, Satoshi Nakamoto was able to establish a defined amount of available data, a revolutionary accomplishment in and of itself.
The limited production of bitcoins was, in a way, aimed at counteracting the endless printing of paper currencies.
Nakamoto compared it to the discovery and mining of gold in the original Bitcoin white paper, writing:
“By convention, the first transaction in a block is a special transaction that starts a new coin owned by the creator of the block. This adds an incentive for nodes to support the network, and provides a way to initially distribute coins into circulation, since there is no central authority to issue them. The steady addition of a constant of amount of new coins is analogous to gold miners expending resources to add gold to circulation. In our case, it is CPU time and electricity that is expended.”
But in the actual code, there is actually no “constant of amount of new coin.”
Instead, there are rules in place that dictate how much bitcoin will be released and when and how that supply is reduced overtime, ultimately leading to a time during which there will be no new bitcoins released.
Each time a new block is added to the bitcoin network, freshly minted bitcoins are rewarded to whichever miner discovered the valid block. This reward, initially set to 50 BTC, fell to 25 BTC in late 2012. Sometime next month, this number is expected to fall to 12.5 BTC. This event is known as a “halving”.
[Ref C:] http://www.coindesk.com/making-sense-bitcoins-halving/
-
Feathercoin specific changes made to convert Bitcoin to FTC 0.9.6
https://github.com/FeatherCoin/Feathercoin/commit/d5913b435afedddd67da68416dc2dc8985e64f92
main.cpp Part 3
enhanced Hash Rate Compensation eHRC
This section of main.cpp calculates the difficulty to give the next block.
Change block time to one minute blocks
+// Feathercoin: eHRC -static const int64_t nTargetSpacing = 10 * 60; +int64_t nTargetTimespan = 60; // Feathercoin: 1 minute +static const int64_t nTargetTimespanNEW = 60 ; // Feathercoin: unused +int64_t nTargetSpacing = 60; // Feathercoin: 1 minute static const int64_t nInterval = nTargetTimespan / nTargetSpacing; static const int64_t nInterval = nTargetTimespan / nTargetSpacing;
Define blocks Fork is at for block time and difficulty
+static const int64_t nDiffChangeTarget = 145000; // Feathercoin: unused ,Patch effective @ block 145000 +static const int64_t nTestnetResetTargetFix = 157500; // Feathercoin: unused ,Testnet enables target reset at block 157500
Include the eHRC testnet block (not needed?) and change over block number.
Feathercoin specific difficulty calculation and blocks it effects
+ // The next block + int nHeight = pindexLast->nHeight + 1; + if (nHeight >= nForkOne) + nTargetTimespan = (7 * 24 * 60 * 60) / 8; // 7/8 days + + if (nHeight >= nForkTwo) + nTargetTimespan = (7 * 24 * 60 * 60) / 32; // 7/32 days + + if (nHeight >= nForkThree || TestNet()) { + nTargetTimespan = 60; // 1 minute timespan + nTargetSpacing = 60; // 1 minute block + } + // 2016 blocks initial, 504 after the 1st, 126 after the 2nd hard fork, 15 after the 3rd hard fork + int nInterval = nTargetTimespan / nTargetSpacing; + + bool fHardFork = (nHeight == nForkOne) || (nHeight == nForkTwo) || (nHeight == nForkThree); + if (TestNet()) fHardFork = false; + // Only change once per interval if ((pindexLast->nHeight+1) % nInterval != 0) + // Difficulty rules regular blocks + if((nHeight % nInterval != 0) && !(fHardFork) && (nHeight < nForkThree))
eHRC adds a short and long average of previous block times to the difficulty calculation. Preliminary.
+ // The 1st retarget after genesis + if(nInterval >= nHeight) nInterval = nHeight - 1;
FTC required to reset nInterval after Genesis Block.
Calculation of eHRC
+ //eHRC - if (nActualTimespan > nTargetTimespan*4) + // Additional averaging over 15, 120 and 480 block window - nActualTimespan = nTargetTimespan*4; + if((nHeight >= nForkThree) || TestNet()) { + + nInterval *= 480; + + int pindexFirstShortTime = 0; + int pindexFirstMediumTime = 0; + const CBlockIndex* pindexFirstLong = pindexLast; + for(int i = 0; pindexFirstLong && i < nInterval && i < nHeight - 1; i + +) { // i < nHeight - 1 special rule for testnet + pindexFirstLong = pindexFirstLong->pprev; + if (i == 14) { + pindexFirstShortTime = pindexFirstLong->GetBlockTime(); + } + if (i == 119) { + pindexFirstMediumTime = pindexFirstLong->GetBlockTime(); + } + } + + int nActualTimespanShort = + (pindexLast->GetBlockTime() - pindexFirstShortTime)/15; + + int nActualTimespanMedium = + (pindexLast->GetBlockTime() - pindexFirstMediumTime)/120; + + int nActualTimespanLong = + (pindexLast->GetBlockTime() - pindexFirstLong->GetBlockTime())/480; + + int nActualTimespanAvg = 0; + nActualTimespanAvg = (nActualTimespanShort + nActualTimespanMedium + nActualTimespanLong)/3; + + // Apply .25 damping + nActualTimespan = nActualTimespanAvg + 3*nTargetTimespan; + nActualTimespan /= 4; + + printf("RETARGET: nActualTimespanShort = %d, nActualTimespanMedium = %d, nActualTimespanLong = %d, nActualTimeSpanAvg = %d, nActualTimespan (damped) = %d\n", + nActualTimespanShort, nActualTimespanMedium, nActualTimespanLong, nActualTimespanAvg, nActualTimespan); + } + + // The initial settings (4.0 difficulty limiter) + int nActualTimespanMax = nTargetTimespan*4; + int nActualTimespanMin = nTargetTimespan/4; + + // The 1st hard fork (1.4142857 aka 41% difficulty limiter) + if(nHeight >= nForkOne) { + nActualTimespanMax = nTargetTimespan*99/70; + nActualTimespanMin = nTargetTimespan*70/99; + } + + // The 2nd hard fork (1.0905077 aka 9% difficulty limiter) + if(nHeight >= nForkTwo || TestNet()) { + nActualTimespanMax = nTargetTimespan*494/453; + nActualTimespanMin = nTargetTimespan*453/494; + } + + if(nActualTimespan < nActualTimespanMin) nActualTimespan = nActualTimespanMin; + if(nActualTimespan > nActualTimespanMax) nActualTimespan = nActualTimespanMax; + + printf("RETARGET: nActualTimespan = %d after bounds\n", nActualTimespan); + printf("RETARGET: nTargetTimespan = %d, nTargetTimespan/nActualTimespan = %.4f\n", nTargetTimespan, (float) nTargetTimespan/nActualTimespan); + // Retarget
Recalculate the required difficulty using eHRC, information of what to do for pre-fork blocks. Note, the difficulty change damping from previous forks was retained would need a fork to update.
maximum amount of blocks that other nodes claim to have
-// Return maximum amount of blocks that other nodes claim to have -int GetNumBlocksOfPeers() -{ - return std::max(cPeerBlockCounts.median(), Checkpoints::GetTotalBlocksEstimate()); -} -
@Lizhi Bitcoin Code removed, maximum amount of blocks. Currently unknown why.
-
Feathercoin specific changes made to convert Bitcoin to FTC 0.9.6
https://github.com/FeatherCoin/Feathercoin/commit/d5913b435afedddd67da68416dc2dc8985e64f92
main.cpp Part 4
+ LOCK(cs_main);
Additional database locks, possibly LTC scrypt / Neoscrypt related?
GetRequiredMaturityDepth
+int GetRequiredMaturityDepth(int nHeight) +{ + + if (nHeight >= COINBASE_MATURITY_SWITCH) + { + return COINBASE_MATURITY_NEW; + } + else + { + return COINBASE_MATURITY; + } +}
Additional code ? from LTC? to GetRequiredMaturityDepth
void ThreadScriptCheck() { - RenameThread("bitcoin-scriptch"); + RenameThread("feathercoin-scriptch"); scriptcheckqueue.Thread(); scriptcheckqueue.Thread(); }
Change a name of file (and supposedly the file?) from Bitcoin.
// Check it again in case a previous version let a bad block in - if (!CheckBlock(block, state, !fJustCheck, !fJustCheck)) + if (!CheckBlock(block, state, pindex->nHeight, !fJustCheck, !fJustCheck)) return false;
Further changes due to the Genesis block count problem pindex->nHeight, has to be included.
// initial block download. + bool fEnforceBIP30 = true;
Initial block handling updated.
+ // BIP16 was always active in Feathercoin - int64_t nBIP16SwitchTime = 1333238400; + bool fStrictPayToScriptHash = true;
A Bitcoin fork is removed because BIP16 was always active in FTC.
+ CBlockIndex* AddToBlockIndex(CBlockHeader& block) + std::map<uint256, CBlockIndex*>::iterator it = mapBlockIndex.find(hash); + if (it != mapBlockIndex.end())
Duplicate checking is modified for FTC (from LTC?).
+ pindexNew->RaiseValidity(BLOCK_VALID_TREE); + + return pindexNew; +} + +// Mark a block as having its data received and checked (up to BLOCK_VALID_TRANSACTIONS). +bool ReceivedBlockTransactions(const CBlock &block, CValidationState& state, CBlockIndex *pindexNew, const CDiskBlockPos& pos) +{ + pindexNew->nTx = block.vtx.size(); + if (pindexNew->pprev) { + // Not the genesis block. + if (pindexNew->pprev->nChainTx) { + // This parent's block's total number transactions is known, so compute outs. + pindexNew->nChainTx = pindexNew->pprev->nChainTx + pindexNew->nTx; + } else { + // The total number of transactions isn't known yet. + // We will compute it when the block is connected. + pindexNew->nChainTx = 0; + } + } else { + // Genesis block. + pindexNew->nChainTx = pindexNew->nTx; + }
pindexNew and nChainTx calculations are made for FTC - looks like due to Genesis block count issue.
+ pindexNew->nStatus |= BLOCK_HAVE_DATA; - setBlockIndexValid.insert(pindexNew); + + if (pindexNew->RaiseValidity(BLOCK_VALID_TRANSACTIONS)) + setBlockIndexValid.insert(pindexNew); + /* write both the immutible data (CDiskBlockIndex) and the mutable data (BlockIndex) */ + //if (!pblocktree->WriteDiskBlockIndex(CDiskBlockIndex(pindexNew, block.auxpow)) || !pblocktree->WriteBlockIndex(*pindexNew))
Another If statement to cover FTC specific pindexNew issue
Include Merged mining
+// to enable merged mining: +// - set a block from which it will be enabled +// - set a unique chain ID +// each merged minable scrypt_1024_1_1_256 coin should have a different one +// (if two have the same ID, they can't be merge mined together) +int GetAuxPowStartBlock() +{ + if (TestNet()) + return AUXPOW_START_TESTNET; + else + return AUXPOW_START_MAINNET; +} + +bool CBlockHeader::CheckProofOfWork(int nHeight) const +{ + if (!::CheckProofOfWork(GetPoWHash(), nBits)) + return error("CheckProofOfWork() : proof of work failed"); +}
Merged mining - Is this may required?
+bool CheckBlockHeader(const CBlockHeader& block, CValidationState& state, int nHeight, bool fCheckPOW) +{ + // Check proof of work matches claimed amount + if (fCheckPOW && !block.CheckProofOfWork(nHeight)) + return state.DoS(50, error("CheckBlockHeader() : proof of work failed"), + REJECT_INVALID, "high-hash"); + + // Check timestamp + if (block.GetBlockTime() > GetAdjustedTime() + 2 * 60 * 60) + return state.Invalid(error("CheckBlockHeader() : block timestamp too far in the future"), + REJECT_INVALID, "time-too-new"); + + CBlockIndex* pcheckpoint = Checkpoints::GetLastCheckpoint(mapBlockIndex); + if (pcheckpoint && block.hashPrevBlock != (chainActive.Tip() ? chainActive.Tip()->GetBlockHash() : uint256(0))) + { + // Extra checks to prevent "fill up memory by spamming with bogus blocks" + int64_t deltaTime = block.GetBlockTime() - pcheckpoint->nTime; + if (deltaTime < 0) + { + return state.DoS(100, error("CheckBlockHeader() : block with timestamp before last checkpoint"), + REJECT_CHECKPOINT, "time-too-old"); + } + CBigNum bnNewBlock; + bnNewBlock.SetCompact(block.nBits); + CBigNum bnRequired; + bnRequired.SetCompact(ComputeMinWork(pcheckpoint->nBits, deltaTime)); + if (bnNewBlock > bnRequired) + { + return state.DoS(100, error("CheckBlockHeader() : block with too little proof-of-work"), + REJECT_INVALID, "bad-diffbits"); + } + } + + return true; +} - bool CheckBlock(const CBlock& block, CValidationState& state, bool fCheckPOW, bool fCheckMerkleRoot) + bool CheckBlock(const CBlock& block, CValidationState& state, int nHeight, bool fCheckPOW, bool fCheckMerkleRoot) // These are checks that are independent of context // that can be verified before saving an orphan block. + if (!CheckBlockHeader(block, state, nHeight, fCheckPOW)) + return false;
Proof of work is checked for validity when mining a block FTC / LTC specific code included.
- // Check proof of work matches claimed amount - if (fCheckPOW && !CheckProofOfWork(block.GetHash(), block.nBits)) - return state.DoS(50, error("CheckBlock() : proof of work failed"), - REJECT_INVALID, "high -hash"); - - // Check timestamp - if (block.GetBlockTime() > GetAdjustedTime() + 2 * 60 * 60) - return state.Invalid(error("CheckBlock() : block timestamp too far in the future"), - REJECT_INVALID, "time -too -new");
The Bitcoin Proof of Work check is removed.
+bool AcceptBlockHeader(CBlockHeader& block, CValidationState& state, CBlockIndex** ppindex) { { + AssertLockHeld(cs_main); // Check for duplicate // Check for duplicate uint256 hash = block.GetHash(); uint256 hash = block.GetHash(); - if (mapBlockIndex.count(hash)) + std::map<uint256, CBlockIndex*>::iterator miSelf = mapBlockIndex.find(hash); return state.Invalid(error("AcceptBlock() : block already in mapBlockIndex"), 0, "duplicate"); + CBlockIndex *pindex = NULL; + if (miSelf != mapBlockIndex.end()) { + pindex = miSelf->second; + if (pindex->nStatus & BLOCK_FAILED_MASK) + return state.Invalid(error("AcceptBlock() : block is marked invalid"), 0, "duplicate"); + }
Accept block header code changed due to CblockIndex interface change / pindex ?
- // Check that all transactions are finalized - BOOST_FOREACH(const CTransaction& tx, block.vtx) - if (!IsFinalTx(tx, nHeight, block.GetBlockTime())) - return state.DoS(10, error("AcceptBlock() : contains a non -final transaction"), - REJECT_INVALID, "bad -txns -nonfinal");
Remove Bitcoin code checks transactions are finalised.
+ } - if (block.nVersion >= 2) + + if (pindex == NULL) + pindex = AddToBlockIndex(block); + + if (ppindex) + *ppindex = pindex; + + return true; +} + +bool AcceptBlock(CBlock& block, CValidationState& state, CBlockIndex** ppindex, CDiskBlockPos* dbp) +{ + AssertLockHeld(cs_main); + + CBlockIndex *&pindex = *ppindex; + + if (!AcceptBlockHeader(block, state, &pindex)) + return false; + + int nHeight = pindex->nHeight; + + if (!CheckBlock(block, state, nHeight)) { + if (state.Invalid() && !state.CorruptionPossible()) { + pindex->nStatus |= BLOCK_FAILED_VALID; + } + return false; + } + + uint256 hash = pindex->GetBlockHash(); + + // Check that all transactions are finalized + BOOST_FOREACH(const CTransaction& tx, block.vtx) + if (!IsFinalTx(tx, nHeight, block.GetBlockTime())) { + pindex->nStatus |= BLOCK_FAILED_VALID; + return state.DoS(10, error("AcceptBlock() : contains a non-final transaction"), + REJECT_INVALID, "bad-txns-nonfinal"); + }
FTC check transactions are finalised.
+ // Enforce block.nVersion=2 rule that the coinbase starts with serialized block height + if (block.nVersion >= 2) + { + // if 750 of the last 1,000 blocks are version 2 or greater (51/100 if testnet): + if ((!TestNet() && CBlockIndex::IsSuperMajority(2, pindex->pprev, 750, 1000)) || + (TestNet() && CBlockIndex::IsSuperMajority(2, pindex->pprev, 51, 100))) { { + CScript expect = CScript() << nHeight; + if (block.vtx[0].vin[0].scriptSig.size() < expect.size() || + !std::equal(expect.begin(), expect.end(), block.vtx[0].vin[0].scriptSig.begin())) { + pindex->nStatus |= BLOCK_FAILED_VALID; + return state.DoS(100, error("AcceptBlock() : block height mismatch in coinbase"), + REJECT_INVALID, "bad-cb-height");
Checking and enforcing the nVersion Number of block.
- if (!AddToBlockIndex(block, state, blockPos)) + if (!ReceivedBlockTransactions(block, state, pindex, blockPos)) - return error("AcceptBlock() : AddToBlockIndex failed"); + return error("AcceptBlock() : ReceivedBlockTransactions failed");
Interface change pindex is now passed and AddToBlockIndex now uses ReceivedBlockTransactions
+ // Feathercoin: temporarily disable v2 block lockin until we are ready for v2 transition + return false;
Feathercoin disables v2 block lockin by returning out of the function ?? needs review
-
Feathercoin specific changes made to convert Bitcoin to FTC 0.9.6
https://github.com/FeatherCoin/Feathercoin/commit/d5913b435afedddd67da68416dc2dc8985e64f92
main.cpp Part 5
+std::string CBlockIndex::ToString() const +{ + return strprintf("CBlockIndex(pprev=%p, nHeight=%d, merkle=%s, hashBlock=%s)", + pprev, nHeight, + hashMerkleRoot.ToString().substr(0,10).c_str(), + GetBlockHash().ToString().c_str()); +} + +std::string CDiskBlockIndex::ToString() const +{ + std::string str = "CDiskBlockIndex("; + str += CBlockIndex::ToString(); + str += strprintf("\n hashBlock=%s, hashPrev=%s, hashParentBlock=%s)", + GetBlockHash().ToString().c_str(), + hashPrev.ToString().c_str(), + //feathercoin unuse (auxpow.get() != NULL) ? auxpow->GetParentBlockHash().ToString().substr(0,20).c_str() : "-" + "0"); + return str; +}
nVersion and block header testing
+CBlockHeader CBlockIndex::GetBlockHeader() const +{ + CBlockHeader block; + + if (nVersion & BLOCK_VERSION_AUXPOW) { + CDiskBlockIndex diskblockindex; + // auxpow is not in memory, load CDiskBlockHeader + // from database to get it + + //Feathercoin unused + //pblocktree->ReadDiskBlockIndex(*phashBlock, diskblockindex); + //block.auxpow = diskblockindex.auxpow; + } + + block.nVersion = nVersion; + if (pprev) + block.hashPrevBlock = pprev->GetBlockHash(); + block.hashMerkleRoot = hashMerkleRoot; + block.nTime = nTime; + block.nBits = nBits; + block.nNonce = nNonce; + return block; +} +
nVersion and block header testing continued …
if (!CheckBlock(*pblock, state, INT_MAX)) { + if (state.CorruptionPossible()) + mapAlreadyAskedFor.erase(CInv(MSG_BLOCK, hash));
Check block code added.
- CBlockIndex* pcheckpoint = Checkpoints::GetLastCheckpoint(mapBlockIndex); - if (pcheckpoint && pblock ->hashPrevBlock != (chainActive.Tip() ? chainActive.Tip() ->GetBlockHash() : uint256(0))) - { - // Extra checks to prevent "fill up memory by spamming with bogus blocks" - int64_t deltaTime = pblock ->GetBlockTime() - pcheckpoint ->nTime; - if (deltaTime < 0) - { - return state.DoS(100, error("ProcessBlock() : block with timestamp before last checkpoint"), - REJECT_CHECKPOINT, "time -too -old"); - } - CBigNum bnNewBlock; - bnNewBlock.SetCompact(pblock ->nBits); - CBigNum bnRequired; - bnRequired.SetCompact(ComputeMinWork(pcheckpoint ->nBits, deltaTime)); - if (bnNewBlock > bnRequired) - { - return state.DoS(100, error("ProcessBlock() : block with too little proof -of -work"), - REJECT_INVALID, "bad -diffbits"); - }
Bitcoin checkbock code removed .
// If we don't already have its previous block (with full data), shunt it off to holding area until we get it + std::map<uint256, CBlockIndex*>::iterator it = mapBlockIndex.find(pblock ->hashPrevBlock); - if (pblock ->hashPrevBlock != 0 && !mapBlockIndex.count(pblock ->hashPrevBlock)) + if (pblock ->hashPrevBlock != 0 && (it == mapBlockIndex.end() || !(it ->second ->nStatus & BLOCK_HAVE_DATA)))
FTC / LTC specific block check included, Bitcoin code removed.
// Store to disk - if (!AcceptBlock(*pblock, state, dbp)) + CBlockIndex *pindex = NULL; + bool ret = AcceptBlock(*pblock, state, &pindex, dbp); + if (!ret)
Store to disk code modified.
- if (AcceptBlock(block, stateDummy)) + CBlockIndex *pindexChild = NULL; + if (AcceptBlock(block, stateDummy, &pindexChild))
Update the store to disk pindexChild code for FTC
- return error("VerifyDB() : *** ReadBlockFromDisk failed at %d, hash=%s", pindex->nHeight, pindex->GetBlockHash().ToString()); + return error("check level 0: VerifyDB() : *** ReadBlockFromDisk failed at %d, hash=%s", pindex->nHeight, pindex->GetBlockHash().ToString()); // check level 1: verify block validity // check level 1: verify block validity - if (nCheckLevel >= 1 && !CheckBlock(block, state)) + if (nCheckLevel >= 1 && !CheckBlock(block, state, pindex->nHeight)) - return error("VerifyDB() : *** found bad block at %d, hash=%s\n", pindex->nHeight, pindex->GetBlockHash().ToString()); + return error("check level 1: VerifyDB() : *** found bad block at %d, hash=%s\n", pindex->nHeight, pindex->GetBlockHash().ToString());
Modify the test when reading block from disk.
if (!ReadBlockFromDisk(block, pindex)) - return error("VerifyDB() : *** ReadBlockFromDisk failed at %d, hash=%s", pindex->nHeight, pindex->GetBlockHash().ToString()); + return error("check level 4: VerifyDB() : *** ReadBlockFromDisk failed at %d, hash=%s", pindex->nHeight, pindex->GetBlockHash().ToString());
Check level 4 instead of dB
- if (!AddToBlockIndex(block, state, blockPos)) + CBlockIndex *pindex = AddToBlockIndex(block); + if (!ReceivedBlockTransactions(block, state, pindex, blockPos))
Update due to pindex issues / interface change
- LogPrintf("%d (blk%05u.dat:0x%x) %s tx %"PRIszu"\n", + LogPrintf("%d (blk%05u.dat:0x%x) %s tx %u\n",
Change due to debug log printout interface.
-
Feathercoin specific changes made to convert Bitcoin to FTC 0.9.6
https://github.com/FeatherCoin/Feathercoin/commit/d5913b435afedddd67da68416dc2dc8985e64f92
main.cpp Part 6
// locate a header - unsigned char buf[4]; + unsigned char buf[MESSAGE_START_SIZE];
Changes preliminary to MESSAGE_START update?
blkdat >> FLATDATA(buf); - if (memcmp(buf, Params().MessageStart(), 4)) + if (memcmp(buf, Params().MessageStart(), MESSAGE_START_SIZE))
MESSAGE_START update? part of the Genesis block definition.
- LogPrintf("%s : Deserialize or I/O error - %s", __PRETTY_FUNCTION__, e.what()); + LogPrintf("%s : Deserialize or I/O error - %s", __func__, e.what());
Debug log printout update due to interface change
- LogPrint("net", "received: %s (%"PRIszu" bytes)\n", strCommand, vRecv.size()); + LogPrint("net", "received: %s (%u bytes)\n", strCommand, vRecv.size());
Debug log printout update due to interface change
- State(pfrom->GetId())->nLastBlockProcess = GetTimeMicros(); + { + LOCK(cs_main); + State(pfrom->GetId())->nLastBlockProcess = GetTimeMicros(); + }
Finalize the database locks -
if (!vRecv.empty()) { - vRecv >> pfrom->strSubVer; + vRecv >> LIMITED_STRING(pfrom->strSubVer, 256);
Update what happens if vRecv.empty empty?
- LOCK(cs_main); - cPeerBlockCounts.input(pfrom->nStartingHeight);
Remove the Bitcoin locking code
- return error("message addr size() = %"PRIszu"", vAddr.size()); + return error("message addr size() = %u", vAddr.size());
Some Debug write updates due to the interface change
+ if (pfrom->nSendSize > (SendBufferSize() * 2)) { + Misbehaving(pfrom->GetId(), 50); + return error("send buffer size() = %u", pfrom->nSendSize); + }
Code to increase the send buffer from LTC?
+ return error("message getdata size() = %u", vInv.size());
A set of error / return message changes due to the interface change
+ set<NodeId> setMisbehaving;
preliminary to map orphan changes
{ - uint256 hashPrev = vWorkQueue[i]; + map<uint256, set<uint256> >::iterator itByPrev = mapOrphanTransactionsByPrev.find(vWorkQueue[i]); - for (set<uint256>::iterator mi = mapOrphanTransactionsByPrev[hashPrev].begin(); + if (itByPrev == mapOrphanTransactionsByPrev.end()) - mi != mapOrphanTransactionsByPrev[hashPrev].end(); + continue; + for (set<uint256>::iterator mi = itByPrev->second.begin(); + mi != itByPrev->second.end(); ++mi)
map orphan changes
const uint256& orphanHash = *mi; - const CTransaction& orphanTx = mapOrphanTransactions[orphanHash]; + const CTransaction& orphanTx = mapOrphanTransactions[orphanHash].tx; NodeId fromPeer = mapOrphanTransactions[orphanHash].fromPeer;
map orphan changes continued …
+ vEraseQueue.push_back(orphanHash); + if (setMisbehaving.count(fromPeer)) + continue;
map orphan changes continued …
- vEraseQueue.push_back(orphanHash);
Bitcoin code removed map orphan changes continued …
- // invalid or too -little -fee orphan + int nDos = 0; - vEraseQueue.push_back(orphanHash); + if (stateDummy.IsInvalid(nDos) && nDos > 0) + { + // Punish peer that gave us an invalid orphan tx + Misbehaving(fromPeer, nDos); + setMisbehaving.insert(fromPeer); + LogPrint("mempool", " invalid orphan tx %s\n", orphanHash.ToString()); + } + // too -little -fee orphan
Adjust code for if fee to low orphan block
{ - AddOrphanTx(tx); + AddOrphanTx(tx, pfrom->GetId());
changed due to interface change
// DoS prevention: do not allow mapOrphanTransactions to grow unbounded - unsigned int nEvicted = LimitOrphanTxSize(MAX_ORPHAN_TRANSACTIONS); + unsigned int nMaxOrphanTx = (unsigned int)std::max((int64_t)0, GetArg("-maxorphantx", DEFAULT_MAX_ORPHAN_TRANSACTIONS)); + unsigned int nEvicted = LimitOrphanTxSize(nMaxOrphanTx);
Max orphan transactions updated (from LTC)
- LogPrint(“net”, “pong %s %s: %s, %x expected, %x received, %u bytes\n”,
additional log message updates — due to interface change
string strMsg; unsigned char ccode; string strReason; - vRecv >> strMsg >> ccode >> strReason; + vRecv >> LIMITED_STRING(strMsg, CMessageHeader::COMMAND_SIZE) >> ccode >> LIMITED_STRING(strReason, 111); ostringstream ss;
Changes to message header resulting from once being scrypt? Note : still need to decode original Scrypt blocks before Neoscrypt fork …
- // Truncate to reasonable length and sanitize before printing: + LogPrint("net", "Reject %s\n", SanitizeString(ss.str())); - string s = ss.str(); - if (s.size() > 111) s.erase(111, string::npos); - LogPrint("net", "Reject %s\n", SanitizeString(s));
Bitcoin Code removed with LTC? debug interface …
+ TRY_LOCK(cs_main, lockMain); // Acquire cs_main for IsInitialBlockDownload() and CNodeState() + if (!lockMain) + return true;
More changes due to the scrypt database type / interface change locking
mapOrphanTransactions.clear(); + mapOrphanTransactionsByPrev.clear();
Run the additional function (additional to Bitcoin code) : mapOrphanTransactionsByPrev.clear();
-
Feathercoin specific changes made to convert Bitcoin to FTC 0.9.6.*
https://github.com/FeatherCoin/Feathercoin/commit/412dfc58f714dab14edc7108be77b160d82efc01
main.h
Main header contains a number of important settings changes. May be worth maintaining our own and manually patching further changes.
+// Copyright (c) 2013-2014 The Feathercoin developers
Copyright needs updating. Automatic way to update Copyright? Add to release check list?
#include "core.h" #include "net.h" #include "script.h" + #include "scrypt.h" #include "sync.h" #include "txmempool.h" #include "uint256.h"
Here are all the header #includes, scrypt is added to main.h.
/** The maximum allowed size for a serialized block, in bytes (network rule) */ static const unsigned int MAX_BLOCK_SIZE = 1000000; /** Default for -blockmaxsize and -blockminsize, which control the range of sizes the mining code will create **/ - static const unsigned int DEFAULT_BLOCK_MAX_SIZE = 750000; + static const unsigned int DEFAULT_BLOCK_MAX_SIZE = 250000;
The MAX_BLOCK_SIZE is left the same as Bitcoin. DEFAULT_BLOCK_MAX_SIZE is reduced by 1/3 . Probably more in line with LTC. This was probably optimal when block times were 2.5 minute. Left at original (scrypt) value since changing it may cause blockchain issues, if altered after “Genesis” block.
static const unsigned int DEFAULT_BLOCK_MIN_SIZE = 0; /** Default for -blockprioritysize, maximum space for zero/low-fee transactions **/ - static const unsigned int DEFAULT_BLOCK_PRIORITY_SIZE = 50000; + static const unsigned int DEFAULT_BLOCK_PRIORITY_SIZE = 17000;
The DEFAULT_BLOCK_PRIORITY_SIZE is adjusted from 50000 to 17000
/** The maximum size for transactions we're willing to relay/mine */ static const unsigned int MAX_STANDARD_TX_SIZE = 100000; /** The maximum allowed number of signature check operations in a block (network rule) */
The maximum transfer size remains the unchanged from Bitcoin.
static const unsigned int MAX_BLOCK_SIGOPS = MAX_BLOCK_SIZE/50; - /** The maximum number of orphan transactions kept in memory */ + /** Default for -maxorphantx, maximum number of orphan transactions kept in memory */ - static const unsigned int MAX_ORPHAN_TRANSACTIONS = MAX_BLOCK_SIZE/100; + static const unsigned int DEFAULT_MAX_ORPHAN_TRANSACTIONS = 100; - /** The maximum number of orphan blocks kept in memory */ + /** Default for -maxorphanblocks, maximum number of orphan blocks kept in memory */ - static const unsigned int MAX_ORPHAN_BLOCKS = 750; + static const unsigned int DEFAULT_MAX_ORPHAN_BLOCKS = 750;
Here there is an interface change DEFAULT_MAX_ORPHAN_TRANSACTIONS is given a value instead of being calculated. Part of the (scrypt?) orphan interface change.
/** The maximum size of a blk?????.dat file (since 0.8) */ static const unsigned int MAX_BLOCKFILE_SIZE = 0x8000000; // 128 MiB static const unsigned int MAX_BLOCKFILE_SIZE = 0x8000000; // 128 MiB /** The pre-allocation chunk size for blk?????.dat files (since 0.8) */ /** The pre-allocation chunk size for blk?????.dat files (since 0.8) */ static const unsigned int BLOCKFILE_CHUNK_SIZE = 0x1000000; // 16 MiB static const unsigned int BLOCKFILE_CHUNK_SIZE = 0x1000000; // 16 MiB /** The pre-allocation chunk size for rev?????.dat files (since 0.8) */ /** The pre-allocation chunk size for rev?????.dat files (since 0.8) */ static const unsigned int UNDOFILE_CHUNK_SIZE = 0x100000; // 1 MiB static const unsigned int UNDOFILE_CHUNK_SIZE = 0x100000; // 1 MiB
This section defines the (blockchain) database files size and parameters. Unchanged for FTC.
+ /** Dust Soft Limit, allowed with additional fee per output */ + static const int64_t DUST_SOFT_LIMIT = COIN; + /** Dust Hard Limit, ignored as wallet inputs (mininput default) */ +static const int64_t DUST_HARD_LIMIT = 1000000;
DUST_SOFT_LIMIT is included and set to he variable COIN. ?? where is COIN defined?
/** Coinbase transaction outputs can only be spent after this number of new blocks (network rule) */ - static const int COINBASE_MATURITY = 100; + static const int COINBASE_MATURITY = 30; + /** Coinbase maturity after block 145000 **/ + static const int COINBASE_MATURITY_NEW = 60*4; + /** Block at which COINBASE_MATURITY_NEW comes into effect **/ + static const int COINBASE_MATURITY_SWITCH = 145000;
Scrypt coinbase interface change.
/** Threshold for nLockTime: below this value it is interpreted as block number, otherwise as UNIX timestamp. */ static const unsigned int LOCKTIME_THRESHOLD = 500000000; // Tue Nov 5 00:53:20 1985 UTC /** Maximum number of script-checking threads allowed */ @@ -67,6 +79,14 @@ (static const int MAX_BLOCKS_IN_TRANSIT_PER_PEER = 128;) /** Timeout in seconds before considering a block download peer unresponsive. */ static const unsigned int BLOCK_DOWNLOAD_TIMEOUT = 60;
This code remains similar. MAX_BLOCKS_IN_TRANSIT_PER_PEER removed because of scrypt interface?
+ /** AuxPow Block versions for sanity checks. */ + /** bare AuxPoW block version which will be modulated further. */ + static const int BLOCK_VERSION_AUXPOW_BARE = CBlockHeader::CURRENT_VERSION | (AUXPOW_CHAIN_ID * BLOCK_VERSION_CHAIN_START); + /** version when AuxPoW exists on the block */ + static const int BLOCK_VERSION_AUXPOW_WITH_AUX = BLOCK_VERSION_AUXPOW_BARE | BLOCK_VERSION_AUXPOW; + /** version when no AuxPoW exists on the block */ + static const int BLOCK_VERSION_AUXPOW_WITHOUT_AUX = BLOCK_VERSION_AUXPOW_BARE & ~BLOCK_VERSION_AUXPOW; +
Additional code for Scrypt AuxPOW - used for Dogecoin?
- /** Get the number of active peers */ - int GetNumBlocksOfPeers();
GetNumBlocksOfPeers is removed.
// Large (in bytes) low-priority (new, small-coin) transactions // need a fee. - return dPriority > COIN * 144 / 250; + return dPriority > 100 * COIN * 1440 / 250; // Feathercoin: 1440 blocks found a day. Priority cutoff is 100 feathercoin day / 250 bytes.
Alter dPriority to FTC settings.
+ /** Get the maturity depth for coinbase transactions at a given height. + @param[in] nHeight The height at which to check maturity for + @return the depth at which the coinbase transaction matures + */ + // Dogecoin specific implementation, standardizes checks for the hard maturity change at block 145k + int GetRequiredMaturityDepth(int nHeight);
Include Maturity depth for scrypt interface changes.
// Check whether all inputs of this transaction are valid (no double spends, scripts & sigs, amounts) // This does not modify the UTXO set. If pvChecks is not NULL, script checks are pushed onto it // instead of being performed inline. filein >> hashChecksum;
Here is where the transactions are checked, unchanged for FTC.
- return error("%s : Deserialize or I/O error - %s", __PRETTY_FUNCTION__, e.what()); + return error("%s : Deserialize or I/O error - %s", __func__, e.what());
Here is another error output interface fix.
+// Get the block at which AuxPoW is enabled for this network +int GetAuxPowStartBlock();
Code for Auxilliary POW (scrypt)
// Context-independent validity checks - bool CheckBlock(const CBlock& block, CValidationState& state, bool fCheckPOW = true, bool fCheckMerkleRoot = true); + bool CheckBlockHeader(const CBlockHeader& block, CValidationState& state, int nHeight, bool fCheckPOW = true); + bool CheckBlock(const CBlock& block, CValidationState& state, int nHeight, bool fCheckPOW = true, bool fCheckMerkleRoot = true);
Additional scrypt validity checks.
// Store block on disk // if dbp is provided, the file is known to already reside on disk - bool AcceptBlock(CBlock& block, CValidationState& state, CDiskBlockPos* dbp = NULL); + bool AcceptBlock(CBlock& block, CValidationState& state, CBlockIndex **pindex, CDiskBlockPos* dbp = NULL); + bool AcceptBlockHeader(CBlockHeader& block, CValidationState& state, CBlockIndex **ppindex= NULL); +
Block storage to disk is updated for scrypt interface.
+ CBlockHeader GetBlockHeader() const;
A block header function replaces the Bitcoin code.
- CBlockHeader GetBlockHeader() const - { - CBlockHeader block; - block.nVersion = nVersion; - if (pprev) - block.hashPrevBlock = pprev ->GetBlockHash(); - block.hashMerkleRoot = hashMerkleRoot; - block.nTime = nTime; - block.nBits = nBits; - block.nNonce = nNonce; - return block;
A block header function replaces the Bitcoin code .
- return CheckProofOfWork(GetBlockHash(), nBits); + /** Scrypt is used for block proof -of -work, but for purposes of performance the index internally uses sha256. + * This check was considered unneccessary given the other safeguards like the genesis and checkpoints. */ + return true; // return CheckProofOfWork(GetBlockHash(), nBits);
Scrypt POW
+ // Check whether this block index entry is valid up to the passed validity level. + bool IsValid(enum BlockStatus nUpTo = BLOCK_VALID_TRANSACTIONS) const + { + assert(!(nUpTo & ~BLOCK_VALID_MASK)); // Only validity flags allowed. + if (nStatus & BLOCK_FAILED_MASK) + return false; + return ((nStatus & BLOCK_VALID_MASK) >= nUpTo); + } + + // Raise the validity level of this block index entry. + // Returns true if the validity was changed. + bool RaiseValidity(enum BlockStatus nUpTo) + { + assert(!(nUpTo & ~BLOCK_VALID_MASK)); // Only validity flags allowed. + if (nStatus & BLOCK_FAILED_MASK) + return false; + if ((nStatus & BLOCK_VALID_MASK) < nUpTo) { + nStatus = (nStatus & ~BLOCK_VALID_MASK) | nUpTo; + return true; + } + return false;
Scrypt Validation code.
- std::string ToString() const + std::string ToString() const; // moved code to main.cpp - { - std::string str = "CDiskBlockIndex("; - str += CBlockIndex::ToString(); - str += strprintf("\n hashBlock=%s, hashPrev=%s)", - GetBlockHash().ToString().c_str(), - hashPrev.ToString().c_str()); - return str;
ToString() function moved o main.cpp
-
Feathercoin specific changes made to convert Bitcoin to FTC 0.9.6.*
https://github.com/FeatherCoin/Feathercoin/commit/1db406e12b2506d0ecf554f7eccdec30ba1f29af
alert.h
FTC Copyright needs update.
-
Feathercoin specific changes made to convert Bitcoin to FTC 0.9.6.*
https://github.com/FeatherCoin/Feathercoin/commit/55dacecae05dacfc1524c2e1be8847455af3499b
core.h
FTC Copyright needs update.
+ #include "scrypt.h"
Scrypt header included
+ class CAuxPow; + + template <typename Stream> + int ReadWriteAuxPow(Stream& s, const boost::shared_ptr<CAuxPow>& auxpow, int nType, int nVersion, CSerActionSerialize ser_action); + + template <typename Stream> + int ReadWriteAuxPow(Stream& s, boost::shared_ptr<CAuxPow>& auxpow, int nType, int nVersion, CSerActionUnserialize ser_action); + + template <typename Stream> + int ReadWriteAuxPow(Stream& s, const boost::shared_ptr<CAuxPow>& auxpow, int nType, int nVersion, CSerActionGetSerializeSize ser_action); + + // primary version, Feathercoin unuse + static const int BLOCK_VERSION_DEFAULT = (1 << 0); + static const int BLOCK_VERSION_AUXPOW = (1 << 8); + static const int BLOCK_VERSION_CHAIN_START = (1 << 16); + static const int BLOCK_VERSION_CHAIN_END = (1 << 30); + + // DogeCoin aux chain ID = 0x0062 (98), Feathercoin unuse + static const int AUXPOW_CHAIN_ID = 0x0062; + static const int AUXPOW_START_MAINNET = 371337; + static const int AUXPOW_START_TESTNET = 158100;
Scrypt Aux POW code and settings.
/** No amount larger than this (in satoshi) is valid */ - static const int64_t MAX_MONEY = 21000000 * COIN; + static const int64_t MAX_MONEY = 336000000 * COIN;
Largest valid amount changed.
/** An outpoint - a combination of a transaction hash and an index n into its vout */ class CTxOut // need a CTxIn of at least 148 bytes to spend, // need a CTxIn of at least 148 bytes to spend, // so dust is a txout less than 546 satoshis // so dust is a txout less than 546 satoshis // with default nMinRelayTxFee. // with default nMinRelayTxFee. - return ((nValue*1000)/(3*((int)GetSerializeSize(SER_DISK,0) + 148)) < nMinRelayTxFee); + //return ((nValue*1000)/(3*((int)GetSerializeSize(SER_DISK,0) + 148)) < nMinRelayTxFee); + + //Feathercoin IsDust() detection disabled + return false;
Define if it is a dust payment.
- std::string ToString() const; + std::string ToString() const;
Don’t know why this was done.
+ int GetChainID() const + { + return nVersion / BLOCK_VERSION_CHAIN_START; + } + + void SetAuxPow(CAuxPow* pow);
int GetChainID() included for scrypt interface.
+ + uint256 GetPoWHash() const + { + uint256 thash; + scrypt_1024_1_1_256(BEGIN(nVersion), BEGIN(thash)); + return thash; + }
GetPoWHash() include for scrypt interface changes.
+ bool CheckProofOfWork(int nHeight) const;
CheckProofOfWork included for scrypt interface changes.
+ uint256 GetPoWHash() const + { + uint256 thash; + scrypt_1024_1_1_256(BEGIN(nVersion), BEGIN(thash)); + return thash; + }
Scrypt interface changes
-
Feathercoin specific changes made to convert Bitcoin to FTC 0.9.6.*
https://github.com/FeatherCoin/Feathercoin/commit/e9b6b652993ef80ad020be3c8a4420f11199ee3f
rpcnet.cpp
if (!(stats.addrLocal.empty())) obj.push_back(Pair("addrlocal", stats.addrLocal)); obj.push_back(Pair("addrlocal", stats.addrLocal)); obj.push_back(Pair("services", strprintf("%08x", stats.nServices))); obj.push_back(Pair("services", strprintf("%08x", stats.nServices)));
These remain the same
- obj.push_back(Pair("lastsend", (boost::int64_t)stats.nLastSend)); - obj.push_back(Pair("lastrecv", (boost::int64_t)stats.nLastRecv)); - obj.push_back(Pair("bytessent", (boost::int64_t)stats.nSendBytes)); - obj.push_back(Pair("bytesrecv", (boost::int64_t)stats.nRecvBytes)); - obj.push_back(Pair("conntime", (boost::int64_t)stats.nTimeConnected));
Removed lines
+ obj.push_back(Pair("lastsend", stats.nLastSend)); + obj.push_back(Pair("lastrecv", stats.nLastRecv)); + obj.push_back(Pair("bytessent", stats.nSendBytes)); + obj.push_back(Pair("bytesrecv", stats.nRecvBytes)); + obj.push_back(Pair("conntime", stats.nTimeConnected));
Interface change from boost.
- + HelpExampleCli("addnode", "\"192.168.0.6:8333\" \"onetry\"") + + HelpExampleCli("addnode", "\"192.168.0.6:9336\" \"onetry\"") - + HelpExampleRpc("addnode", "\"192.168.0.6:8333\", \"onetry\"") + + HelpExampleRpc("addnode", "\"192.168.0.6:9336\", \"onetry\"")
These are the examples shown when using the Debug console, here for addnode. Adjusted for Feathercoins rpc Port.
+ " \"address\" : \"192.168.0.201:9336\", (string) The bitcoin server host and port\n"
Modify port number for FTC in Debug console. Bitcoin code removed. bitcoin reference (in code comment) has not been removed.
- obj.push_back(Pair("totalbytesrecv", static_cast< boost::uint64_t>(CNode::GetTotalBytesRecv()))); - obj.push_back(Pair("totalbytessent", static_cast<boost::uint64_t>(CNode::GetTotalBytesSent()))); - obj.push_back(Pair("timemillis", static_cast<boost::int64_t>(GetTimeMillis())));
Code removed.
+ obj.push_back(Pair("totalbytesrecv", CNode::GetTotalBytesRecv())); + obj.push_back(Pair("totalbytessent", CNode::GetTotalBytesSent())); + obj.push_back(Pair("timemillis", GetTimeMillis())); + return obj; +}
Adding the scrypt interface replacement.
+ Value getnetworkinfo(const Array& params, bool fHelp) + { + if (fHelp || params.size() != 0) + throw runtime_error( + "getnetworkinfo\n" + "Returns an object containing various state info regarding P2P networking.\n" + "\nResult:\n" + "{\n" + " \"version\": xxxxx, (numeric) the server version\n" + " \"protocolversion\": xxxxx, (numeric) the protocol version\n" + " \"timeoffset\": xxxxx, (numeric) the time offset\n" + " \"connections\": xxxxx, (numeric) the number of connections\n" + " \"proxy\": \"host:port\", (string, optional) the proxy used by the server\n" + " \"relayfee\": x.xxxx, (numeric) minimum relay fee for non-free transactions in btc/kb\n" + " \"localaddresses\": [, (array) list of local addresses\n" + " \"address\": \"xxxx\", (string) network address\n" + " \"port\": xxx, (numeric) network port\n" + " \"score\": xxx (numeric) relative score\n" + " ]\n" + "}\n" + "\nExamples:\n" + + HelpExampleCli("getnetworkinfo", "") + + HelpExampleRpc("getnetworkinfo", "") + ); + + proxyType proxy; + GetProxy(NET_IPV4, proxy); + + Object obj; + obj.push_back(Pair("version", (int)CLIENT_VERSION)); + obj.push_back(Pair("protocolversion",(int)PROTOCOL_VERSION)); + obj.push_back(Pair("timeoffset", GetTimeOffset())); + obj.push_back(Pair("connections", (int)vNodes.size())); + obj.push_back(Pair("proxy", (proxy.first.IsValid() ? proxy.first.ToStringIPPort() : string()))); + obj.push_back(Pair("relayfee", ValueFromAmount(CTransaction::nMinRelayTxFee))); + Array localAddresses; + { + LOCK(cs_mapLocalHost); + BOOST_FOREACH(const PAIRTYPE(CNetAddr, LocalServiceInfo) &item, mapLocalHost) + { + Object rec; + rec.push_back(Pair("address", item.first.ToString())); + rec.push_back(Pair("port", item.second.nPort)); + rec.push_back(Pair("score", item.second.nScore)); + localAddresses.push_back(rec); + } + } + obj.push_back(Pair("localaddresses", localAddresses));
getnetworkinfo replacement for scrypt.
-
Feathercoin specific changes made to convert Bitcoin to FTC 0.9.6.*
https://github.com/FeatherCoin/Feathercoin/commit/f4003712b2147b515c073d1a92985161d667cae9
rpcclient.cpp
rpcclient.cpp contains a number of scrypt interface change related settings such as Methods. FTC should maintain a separate file, or such as this could be over writen by changes at head (and pass auto build test).
+ if (strMethod == "setgenerate" && n > 1) ConvertTo<int64_t>(params[1]); - if (strMethod == "getnetworkhashps" && n > 0) ConvertTo<boost::int64_t>(params[0]); + if (strMethod == "getnetworkhashps" && n > 0) ConvertTo<int64_t>(params[0]); - if (strMethod == "getnetworkhashps" && n > 1) ConvertTo<boost::int64_t>(params[1]); + if (strMethod == "getnetworkhashps" && n > 1) ConvertTo<int64_t>(params[1]);
Note : Further similar Methods / see debug console, are defined .
- strUsage += " -conf=<file> " + _("Specify configuration file (default: bitcoin.conf)") + "\n"; + strUsage += " -conf=<file> " + _("Specify configuration file (default: feathercoin.conf)") + "\n";
Name change to .conf file.
- strUsage += " -rpcport=<port> " + _("Connect to JSON-RPC on <port> (default: 8332 or testnet: 18332)") + "\n"; + strUsage += " -rpcport=<port> " + _("Connect to JSON-RPC on <port> (default: 9337 or testnet: 19337)") + "\n";
Setting Feathercoin mining / rpc ports.
-
Feathercoin specific changes made to convert Bitcoin to FTC 0.9.6.*
https://github.com/FeatherCoin/Feathercoin/commit/d58d75a44a95b6b06147bd7f1419c36157d184fa
rpcserver.cpp
A short file with a number of settings changes. Consider build change to FTC version of file when move to head…
+ static std::vector< boost::shared_ptr<ip::tcp::acceptor> > rpc_acceptors;
added static for scrypt interface.
+ "\nStop Feathercoin server."); + return "Feathercoin server stopping";
Update close down messages to say Feathercoin.
/* P2P networking */ + { "getnetworkinfo", &getnetworkinfo, true, false, false },
Added getnetworkinfo for scrypt interface.
/* Block chain and UTXO */ + { "getblockchaininfo", &getblockchaininfo, true, false, false },
Added getblockchaininfo for scrypt interface.
- AcceptedConnection* conn, + boost::shared_ptr< AcceptedConnection > conn, - AcceptedConnectionImpl<Protocol>* conn = new AcceptedConnectionImpl<Protocol>(acceptor->get_io_service(), context, fUseSSL); + boost::shared_ptr< AcceptedConnectionImpl<Protocol> > conn(new AcceptedConnectionImpl<Protocol>(acceptor->get_io_service(), context, fUseSSL));
Updated AcceptedConnection for scrypt interface.
- boost::asio::placeholders::error)); + _1));
Updated Boost error to function?
- AcceptedConnection* conn, + boost::shared_ptr< AcceptedConnection > conn,
Updates to RPCAcceptHandler for the scrypt interface.
// Immediately start accepting new connections, except when we're cancelled or our socket is closed. if (error != asio::error::operation_aborted && acceptor->is_open()) RPCListen(acceptor, context, fUseSSL); - AcceptedConnectionImpl<ip::tcp>* tcp_conn = dynamic_cast< AcceptedConnectionImpl<ip::tcp>* >(conn); + AcceptedConnectionImpl<ip::tcp>* tcp_conn = dynamic_cast< AcceptedConnectionImpl<ip::tcp>* >(conn.get());
Updates to connection error interface.
if (error) { - delete conn; + // TODO: Actually handle errors + LogPrintf("%s: Error: %s\n", __func__, error.message()); }
Updates to connection error interface.
- delete conn; + conn->close(); - ServiceConnection(conn); + ServiceConnection(conn.get()); conn->close();
Further updates to connections handling.
- string strWhatAmI = "To use bitcoind"; + string strWhatAmI = "To use feathercoind";
strWhatAm updated to read feathercoin
- "rpcuser=bitcoinrpc\n" + "rpcuser=feathercoinrpc\n"
rpcuser name change to FTC
- "for example: alertnotify=echo %%s | mail -s \"Bitcoin Alert\" [email protected]\n"), + "for example: alertnotify=echo %%s | mail -s \"Feathercoin Alert\" [email protected]\n"),
name change to FTC, alert messages from admin.
- boost::shared_ptr<ip::tcp::acceptor> acceptor(new ip::tcp::acceptor(*rpc_io_service));
Remove Bitcoin Boost code. Was this moved?
+ rpc_acceptors.push_back(acceptor);
extra line added scrypt acceptance interface.
- acceptor.reset(new ip::tcp::acceptor(*rpc_io_service)); + boost::shared_ptr<ip::tcp::acceptor> acceptor(new ip::tcp::acceptor(*rpc_io_service));
connection interface change to scrypt
+ rpc_acceptors.push_back(acceptor);
additional rpc inspector for scrypt connection interface.
+ // First, cancel all timers and acceptors + // This is not done automatically by ->stop(), and in some cases the destructor of + // asio::io_service can hang if this is skipped. + boost::system::error_code ec; + BOOST_FOREACH(const boost::shared_ptr<ip::tcp::acceptor> &acceptor, rpc_acceptors) + { + acceptor->cancel(ec); + if (ec) + LogPrintf("%s: Warning: %s when cancelling acceptor", __func__, ec.message()); + } + rpc_acceptors.clear(); + BOOST_FOREACH(const PAIRTYPE(std::string, boost::shared_ptr<deadline_timer>) &timer, deadlineTimers) + { + timer.second->cancel(ec); + if (ec) + LogPrintf("%s: Warning: %s when cancelling timer", __func__, ec.message());
Main code of rpc interface change for scrypt.
- return "> bitcoin-cli " + methodname + " " + args + "\n"; + return "> feathercoin-cli " + methodname + " " + args + "\n";
Name change for the feathercoin-cli (replaces feathercoind
- "\"method\": \"" + methodname + "\", \"params\": [" + args + "] }' -H 'content-type: text/plain;' http://127.0.0.1:8332/\n"; + "\"method\": \"" + methodname + "\", \"params\": [" + args + "] }' -H 'content-type: text/plain;' http://127.0.0.1:9337/\n";
-
Feathercoin specific changes made to convert Bitcoin to FTC 0.9.6.*
https://github.com/FeatherCoin/Feathercoin/commit/d58d75a44a95b6b06147bd7f1419c36157d184fa
checkpoints.cpp
Probably should be maintained as FTC specific file. Contains dev included FTC checkpoints, or “know blocks”.
+ ( 1, uint256("0xfdbe99b90c90bae7505796461471d89ae8388ab953997aa06a355bbda8d915cb"))
Example of FTC checkpoint
static const CCheckpointData data = { &mapCheckpoints, - 1389047471, // * UNIX timestamp of last checkpoint block + 1372166807, // * UNIX timestamp of last checkpoint block - 30549816, // * total number of transactions between genesis and last checkpoint + 257285, // * total number of transactions between genesis and last checkpoint // (the tx=... number in the SetBestChain debug.log lines) - 60000.0 // * estimated number of transactions per day after checkpoint + 3450.0 // * estimated number of transactions per day after checkpoint
checkpoint settings customization.
+ if (TestNet()) return true; // Testnet has no checkpoints + if (TestNet()) return NULL; // Testnet has no checkpoints
Switch off checkpoints for testnet
-
Feathercoin specific changes made to convert Bitcoin to FTC 0.9.6.*
https://github.com/FeatherCoin/Feathercoin/commit/c86c18168555458aae830a4baa487184324adae3
util.cpp
Short file consisting of mostly feathercoin / scrypt specific settings. Consider maintaining seperate FTC file integrated at build going forward to head.
+ #include <boost/date_time/posix_time/posix_time.hpp>
Include Boost
- void ParseString(const string& str, char c, vector<string>& v) - { - if (str.empty()) - return; - string::size_type i1 = 0; - string::size_type i2; - while (true) - { - i2 = str.find(c, i1); - if (i2 == str.npos) - { - v.push_back(str.substr(i1)); - return; - } - v.push_back(str.substr(i1, i2 - i1)); - i1 = i2+1; - }
Remove Bitcoin ParseString() function.
- const char* pszModule = "bitcoin"; + const char* pszModule = "feathercoin"
Name change to Feathercoin.
+ // Windows < Vista: C:\Documents and Settings\Username\Application Data\Feathercoin + // Windows >= Vista: C:\Users\Username\AppData\Roaming\Feathercoin + // Mac: ~/Library/Application Support/Feathercoin
Name change directories.
+ return GetSpecialFolderPath(CSIDL_APPDATA) / "Feathercoin";
Name change application directories.
+ return pathRet / "Feathercoin";
Path change
+ return pathRet / ".feathercoin";
Path update name
+ boost::filesystem::path pathConfigFile(GetArg("-conf", "feathercoin.conf"));
Change Boost reference to feathercoin.
+ return; // No feathercoin.conf file is OK
name change in comments?
+ boost::filesystem::path pathPidFile(GetArg("-pid", "feathercoind.pid"));
name change feathercoind
+ void SetupEnvironment() + { + #ifndef WIN32 + try + { + #if BOOST_FILESYSTEM_VERSION == 3 + boost::filesystem::path::codecvt(); // Raises runtime error if current locale is invalid + #else // boost filesystem v2 + std::locale(); // Raises runtime error if current locale is invalid + #endif + } catch(std::runtime_error &e) + { + setenv("LC_ALL", "C", 1); // Force C locale + } + #endif + } + + std::string DateTimeStrFormat(const char* pszFormat, int64_t nTime) + { + // std::locale takes ownership of the pointer + std::locale loc(std::locale::classic(), new boost::posix_time::time_facet(pszFormat)); + std::stringstream ss; + ss.imbue(loc); + ss << boost::posix_time::from_time_t(nTime); + return ss.str();;
Include SetupEnvironment()
+ // First, cancel all timers and acceptors + // This is not done automatically by ->stop(), and in some cases the destructor of + // asio::io_service can hang if this is skipped. + boost::system::error_code ec; + BOOST_FOREACH(const boost::shared_ptr<ip::tcp::acceptor> &acceptor, rpc_acceptors) + { + acceptor->cancel(ec); + if (ec) + LogPrintf("%s: Warning: %s when cancelling acceptor", __func__, ec.message()); + } + rpc_acceptors.clear(); + BOOST_FOREACH(const PAIRTYPE(std::string, boost::shared_ptr<deadline_timer>) &timer, deadlineTimers) + { + timer.second->cancel(ec); + if (ec) + LogPrintf("%s: Warning: %s when cancelling timer", __func__, ec.message());