(2)修改创世块
源文件 chainparams.cpp
[cpp] view plain copy
/**
* Build the genesis block. Note that the output of the genesis coinbase cannot
* be spent as it did not originally exist in the database.
*
* CBlock(hash=000000000019d6, ver=1, hashPrevBlock=00000000000000, hashMerkleRoot=4a5e1e, nTime=1231006505, nBits=1d00ffff, nNonce=2083236893, vtx=1)
* CTransaction(hash=4a5e1e, ver=1, vin.size=1, vout.size=1, nLockTime=0)
* CTxIn(COutPoint(000000, -1), coinbase 04ffff001d0104455468652054696d65732030332f4a616e2f32303039204368616e63656c6c6f72206f6e206272696e6b206f66207365636f6e64206261696c6f757420666f722062616e6b73)
* CTxOut(nValue=50.00000000, scriptPubKey=0x5F1DF16B2B704C8A578D0B)
* vMerkleTree: 4a5e1e
*/
// HarryWu, generate genesis block by genesis.py as following:
//
// localhost genesis # python genesis.py \
// -t $(date +%s) \
// -z "shanghai stock index closed at 2343.57, on 24th Sept., 2014" \
// -a SHA256 \
// -p 049e02fa9aa3c19a3b112a58bab503c5caf797972f5cfe1006275aa5485a01b48f9f648bc5380ee1e82dc6f474c8e0f7e2f6bbd0de9355f92496e3ea327ccb19cc \
// -v 10000000000
// Raw block data: 04ffff001d01043b7368616e676861692073746f636b20696e64657820636c6f73656420617420323334332e35372c206f6e203234746820536570742e2c2032303134
// algorithm: SHA256
// merkle hash: 1c395aad7fab156523a095a869d3fcdf3249a8a97c8d7337adb4f33d826da32b
// pszTimestamp: shanghai stock index closed at 2343.57, on 24th Sept., 2014
// pubkey: 049e02fa9aa3c19a3b112a58bab503c5caf797972f5cfe1006275aa5485a01b48f9f648bc5380ee1e82dc6f474c8e0f7e2f6bbd0de9355f92496e3ea327ccb19cc
// time: 1411650667
// bits: 0x1d00ffff
// Searching for genesis hash..
//
// nonce: 1456993276
// genesis hash: 000000004df0288b461e17d9a20e557fd296861c604f1944eb9e2cca866af0a5
(3)修改网络协议魔数
源文件 chainparams.cpp
[cpp] view plain copy
class CMainParams : public CChainParams {
public:
CMainParams() {
networkID = CBaseChainParams::MAIN;
strNetworkID = "main";
/**
* The message start string is designed to be unlikely to occur in normal data.
* The characters are rarely used upper ASCII, not valid as UTF-8, and produce
* a large 4-byte int at any alignment.
*/
pchMessageStart[0] = 0x90;
pchMessageStart[1] = 0x0d;
pchMessageStart[2] = 0xf0;
pchMessageStart[3] = 0x0d;
(5)修改网络端口
源文件 chainparams.cpp
[cpp] view plain copy
class CMainParams : public CChainParams {
public:
CMainParams() {
networkID = CBaseChainParams::MAIN;
strNetworkID = "main";
/**
* The message start string is designed to be unlikely to occur in normal data.
* The characters are rarely used upper ASCII, not valid as UTF-8, and produce
* a large 4-byte int at any alignment.
*/
pchMessageStart[0] = 0x90;
pchMessageStart[1] = 0x0d;
pchMessageStart[2] = 0xf0;
pchMessageStart[3] = 0x0d;
vAlertPubKey = ParseHex("04e01590abdc5967eb550413fcf04bbd7cead46f13579b58d52ea2f08d71a1a94196c476cd4fa60c30b51737fe3d9c8c88a04a6bec2282ebb1f22286130a153b85");
nDefaultPort = 9999;
bnProofOfWorkLimit = ~uint256(0) >> 32;
(7)修改工作量机制
源文件 miner.cpp
比特币在函数ScanHash()里面搜索随机数,
[cpp] view plain copy
//
// ScanHash scans nonces looking for a hash with at least some zero bits.
// The nonce is usually preserved between calls, but periodically or if the
// nonce is 0xffff0000 or above, the block is rebuilt and nNonce starts over at
// zero.
//
bool static ScanHash(const CBlockHeader *pblock, uint32_t& nNonce, uint256 *phash)
{
// Write the first 76 bytes of the block header to a double-SHA256 state.
//CHash256 hasher;
//CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
//ss << *pblock;
//assert(ss.size() == 80);
//hasher.Write((unsigned char*)&ss[0], 76);
while (true) {
nNonce++;
// Write the last 4 bytes of the block header (the nonce) to a copy of
// the double-SHA256 state, and compute the result.
//CHash256(hasher).Write((unsigned char*)&nNonce, 4).Finalize((unsigned char*)phash);
*phash = pblock->ComputePowHash(nNonce);
// Return the nonce if the hash has at least some zero bits,
// caller will check if it has enough to reach the target
if (((uint16_t*)phash)[15] == 0)
return true;
// If nothing found after trying for a while, return -1
if ((nNonce & 0xffff) == 0)
return false;
if ((nNonce & 0xfff) == 0)
boost::this_thread::interruption_point();
}
}
在函数BitcoinMiner()里面创建新的block,设定时间戳(扰动1),获取mempool里面的最新交易(扰动2),调用ScanHash()搜索随机数(扰动3),直到找到满足条件的hash。
另外比特币的工作量证明的hash同时用作这个block的索引,litecoin里面这2个概念是区分的对待的(sha256的hash作为索引,scrypt出来的pow hash作为工作量证明)。
注意:设置独立挖矿的条件(chainparams.cpp里面设置)
[cpp] view plain copy
fMiningRequiresPeers = !true; // See BitcoinMiner() for details.
// Each thread has its own key and counter
CReserveKey reservekey(pwallet);
unsigned int nExtraNonce = 0;
try {
while (true) {
if (Params().MiningRequiresPeers()) {
// Busy-wait for the network to come online so we don't waste time mining
// on an obsolete chain. In regtest mode we expect to fly solo.
while (vNodes.empty())
MilliSleep(1000);
}
//
// Create new block
//
unsigned int nTransactionsUpdatedLast = mempool.GetTransactionsUpdated();
CBlockIndex* pindexPrev = chainActive.Tip();
auto_ptr<CBlockTemplate> pblocktemplate(CreateNewBlockWithKey(reservekey));
if (!pblocktemplate.get())
{
LogPrintf("Error in FastCoinMiner: Keypool ran out, please call keypoolrefill before restarting the mining thread\n");
return;
}
CBlock *pblock = &pblocktemplate->block;
IncrementExtraNonce(pblock, pindexPrev, nExtraNonce);
LogPrintf("Running FastCoinMiner with %u transactions in block (%u bytes)\n", pblock->vtx.size(),
::GetSerializeSize(*pblock, SER_NETWORK, PROTOCOL_VERSION));
博主稍作修改,设置了几个预置的hash算法(sha256,scrypt,keccak(即SHA3)),可以通过block的版本号区分,那么在scanhash里面调用ComputePowHash的时候,可以选择不同的pow算法,甚至你可以把这些算法串联起来,以增加算法被破解的方攻击性。
看代码吧:
[cpp] view plain copy
uint256 CBlockHeader::ComputePowHash(uint32_t nNonce) const
{
if (nVersion == 1 || nVersion == 2){
/**
* Use SHA256+SHA256 to make PoW
*/
// Write the first 76 bytes of the block header to a double-SHA256 state.
CDoubleSHA256Pow hasher; // TODO: Create a new PowHasher named CPowHash256
CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
ss << *this;
assert(ss.size() == 80);
hasher.Write((unsigned char*)&ss[0], 76);
uint256 powHash;
CDoubleSHA256Pow(hasher).Write((unsigned char*)&nNonce, 4).Finalize((unsigned char*)&powHash);
return powHash;
}else if (nVersion == 3){
/**
* Scrypt PoW
*/
CScryptHash256Pow hasher;
CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
ss << *this;
assert(ss.size() == 80);
hasher.Write((unsigned char*)&ss[0], 76);
uint256 powHash;
CScryptHash256Pow(hasher).Write((unsigned char*)&nNonce, 4).Finalize((unsigned char*)&powHash);
return powHash;
}else if (nVersion == 4){
/**
* Scrypt+SHA256 PoW
*/
}else if (nVersion == 5){
/**
* Keccak(1088,512,256) or Known as SHA3-256(fips202draft) Pow
*/
CKeccak_256 hasher;
CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
ss << *this;
assert(ss.size() == 80);
hasher.Write((unsigned char*)&ss[0], 76);
uint256 powHash;
CKeccak_256(hasher).Write((unsigned char*)&nNonce, 4).Finalize((unsigned char*)&powHash);
return powHash;
}else{
// Abort, unknown block version.
assert(false);
return ~(uint256)0;
}
}
(8)修改奖励机制
参考9.3
8.1) 修改挖矿奖励的成熟时间
源代码:main.h
[cpp] view plain copy
/** Coinbase transaction outputs can only be spent after this number of new blocks (network rule) */
static const int COINBASE_MATURITY = 14;
8.2) 修改交易确认块数推荐值
源代码 qt/transactionrecord.h
[cpp] view plain copy
/** UI model for a transaction. A core transaction can be represented by multiple UI transactions if it has
multiple outputs.
*/
class TransactionRecord
{
public:
enum Type
{
Other,
Generated,
SendToAddress,
SendToOther,
RecvWithAddress,
RecvFromOther,
SendToSelf
};
/** Number of confirmation recommended for accepting a transaction */
static const int RecommendedNumConfirmations = 2;
(9)修改难度配置
源文件 chainparams.cpp
[cpp] view plain copy
class CMainParams : public CChainParams {
public:
CMainParams() {
networkID = CBaseChainParams::MAIN;
strNetworkID = "main";
/**
* The message start string is designed to be unlikely to occur in normal data.
* The characters are rarely used upper ASCII, not valid as UTF-8, and produce
* a large 4-byte int at any alignment.
*/
pchMessageStart[0] = 0x90;
pchMessageStart[1] = 0x0d;
pchMessageStart[2] = 0xf0;
pchMessageStart[3] = 0x0d;
vAlertPubKey = ParseHex("04e01590abdc5967eb550413fcf04bbd7cead46f13579b58d52ea2f08d71a1a94196c476cd4fa60c30b51737fe3d9c8c88a04a6bec2282ebb1f22286130a153b85");
nDefaultPort = 9999;
bnProofOfWorkLimit = ~uint256(0) >> 32;
nSubsidyHalvingInterval = 210000;
nEnforceBlockUpgradeMajority = 750;
nRejectBlockOutdatedMajority = 950;
nToCheckBlockUpgradeMajority = 1000;
nMinerThreads = 1; // 0 for all available cpus.
nTargetTimespan = 60 * 60; // re-targeting every one hour
nTargetSpacing = 1 * 60; // do new pow every 1 minutes.
nGenesisSubsidy = 100;
a) bnProofOfWorkLimit=~uint256(0) >> 32;
是一个大整数(256bit)表示,前面32个位数是0,这个参数表示全网允许的最小难度,低于这个难度的block是不会被挖掘的。
b) nGenesisSubsidy = 100;
初始津贴,比特币的第一个块的奖励是50个btc。