Key:
altcoin generate, make altcoin, bitcoin, coingen
关键字:
制作山寨币,山寨币,比特币
源代码地址:
https://github.com/imharrywu/fastcoin
程序猿朋友可以自己动手编译生成安装包,有问题可以直接加群讨论 161928517(注明:csdn),也欢迎程序猿朋友PullRequest给我,只有知识共享才能促进比特币的繁荣。
可以支持任何算法(sha256,scrypt,x11,x13,nist,grostel,以及这些算法的串联)和参数定制。
目前预先内置了比特币的SHA256和莱特币的scypt,以及SHA3-256(KECCAK)。
在线编译目前提供三种安装包:
1,linux/unix的daemon程序(带钱包功能)
2,Mac钱包安装包
3,windows钱包安装包
如果看完此文您觉得有用,欢迎捐赠博主:
1MMkfgNEw96B83DQq3DFtL9WxcTN7keFPG
1、 截图预览
(1) 安装图1
![](http://img.e-com-net.com/image/info8/1d4b63238350460c9eaeea4db519de4d.jpg)
(2)安装图2
![](http://img.e-com-net.com/image/info8/71ada27fbc8748edbd5f2740c99c7735.jpg)
(3)安装图3
![](http://img.e-com-net.com/image/info8/8b926ceb6673491899ecd4089aacf4f3.jpg)
(4)安装图4
![](http://img.e-com-net.com/image/info8/bdbf47f3039547b5b022117be3987906.jpg)
(5)安装图5
![](http://img.e-com-net.com/image/info8/62cc7a8799484815b0fbd182a3a5cf06.jpg)
(6)概览图 已经挖到3个block 奖励了300个FTC
![](http://img.e-com-net.com/image/info8/3d783507058344649cc21eb5a75cd4a1.jpg)
(7)交易记录图
![](http://img.e-com-net.com/image/info8/47b4dccdd7304f37a6edd0b5c2b2c4d9.jpg)
(8)点击显示交易细节 显示为挖矿所得 并且还没有确认
![](http://img.e-com-net.com/image/info8/34cbfcbea6d7428998c6cfcf83ee6c63.jpg)
(9)版权页
![](http://img.e-com-net.com/image/info8/b4fadccff0f34013a875ef69a41d46f3.jpg)
(10)调试窗口
![](http://img.e-com-net.com/image/info8/02458660e8714394b31e3934004463bf.jpg)
(11)显示已经连接的p2p网络节点 一个在虚拟机里面运行的节点
![](http://img.e-com-net.com/image/info8/254ff2f20cb54105ae8fc12738b95143.jpg)
(12)2个节点构成的p2p通信网络
![](http://img.e-com-net.com/image/info8/3dcb6aa6b77a4293838097a3f5cf2b2f.jpg)
2、 山寨币修改步骤:
(1)迁出最新的比特币源代码
比特币官方代码: https://github.com/bitcoin/bitcoin
山寨币代码地址(紧跟bitcoin更新):https://github.com/imharrywu/fastcoin
git clone https://github.com/imharrywu/fastcoin
一下修改都是一些代码片段,请用eclipse打开迁出的代码,对照查看。
(2)修改创世块
源文件 chainparams.cpp
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- const char* pszTimestamp = "shanghai stock index closed at 2343.57, on 24th Sept., 2014";
- CMutableTransaction txNew;
- txNew.vin.resize(1);
- txNew.vout.resize(1);
- txNew.vin[0].scriptSig = CScript() << 0x1d00ffff << CScriptNum(4) << vectorchar>((const unsigned char*)pszTimestamp, (const unsigned char*)pszTimestamp + strlen(pszTimestamp));
- txNew.vout[0].nValue = nGenesisSubsidy * COIN;
- txNew.vout[0].scriptPubKey = CScript() << ParseHex("049e02fa9aa3c19a3b112a58bab503c5caf797972f5cfe1006275aa5485a01b48f9f648bc5380ee1e82dc6f474c8e0f7e2f6bbd0de9355f92496e3ea327ccb19cc") << OP_CHECKSIG;
- genesis.vtx.push_back(txNew);
- genesis.hashPrevBlock = 0;
- genesis.hashMerkleRoot = genesis.BuildMerkleTree();
- genesis.nVersion = 1;
- genesis.nTime = 1411666331;
- genesis.nBits = 0x1d00ffff;
- genesis.nNonce = 2056985438;
-
- hashGenesisBlock = genesis.GetHash();
- assert(hashGenesisBlock == uint256("0x0000000061b1aca334b059920fed7bace2336ea4d23d63428c7aee04da49e942"));
- assert(genesis.hashMerkleRoot == uint256("0x7bf229f629a6666596c1ce57117c28d1d29299e8a5303347929bd70847c49adb"));
(3)修改网络协议魔数
源文件 chainparams.cpp
- class CMainParams : public CChainParams {
- public:
- CMainParams() {
- networkID = CBaseChainParams::MAIN;
- strNetworkID = "main";
-
-
-
-
-
- pchMessageStart[0] = 0x90;
- pchMessageStart[1] = 0x0d;
- pchMessageStart[2] = 0xf0;
- pchMessageStart[3] = 0x0d;
0xgoodcafe(好咖啡的意思),大家可以自己选择,但是也有一些基本
建议,看上面那个英文注释就好了,就是和某些常用的字符集可用字段不要冲突。
另外:对应的修改TESTNET和REGTESTNET的参数
(4)修改地址前缀
源文件 chainparams.cpp
- base58Prefixes[PUBKEY_ADDRESS] = list_of(35);
- base58Prefixes[SCRIPT_ADDRESS] = list_of(65);
- base58Prefixes[SECRET_KEY] = list_of(45);
- base58Prefixes[EXT_PUBLIC_KEY] = list_of(0x04)(0x88)(0xEE)(0x35);
- base58Prefixes[EXT_SECRET_KEY] = list_of(0x04)(0x88)(0xEE)(0x45);
有一个 wiki的对照表可以用来悬在公钥和脚本地址的前缀,但是这个表不使用私钥等(因为长度不一样,规律不一样)。
(5)修改网络端口
源文件 chainparams.cpp
- class CMainParams : public CChainParams {
- public:
- CMainParams() {
- networkID = CBaseChainParams::MAIN;
- strNetworkID = "main";
-
-
-
-
-
- pchMessageStart[0] = 0x90;
- pchMessageStart[1] = 0x0d;
- pchMessageStart[2] = 0xf0;
- pchMessageStart[3] = 0x0d;
- vAlertPubKey = ParseHex("04e01590abdc5967eb550413fcf04bbd7cead46f13579b58d52ea2f08d71a1a94196c476cd4fa60c30b51737fe3d9c8c88a04a6bec2282ebb1f22286130a153b85");
- nDefaultPort = 9999;
- bnProofOfWorkLimit = ~uint256(0) >> 32;
修改了nDefaultPort=9999,比特币默认是8333
另外同时修改一下TESTNET和REGTESTNET的端口配置,一般加10000和20000即可
-
-
-
- class CTestNetParams : public CMainParams {
- public:
- CTestNetParams() {
- networkID = CBaseChainParams::TESTNET;
- strNetworkID = "test";
- pchMessageStart[0] = 0xC0;
- pchMessageStart[1] = 0x1d;
- pchMessageStart[2] = 0xf0;
- pchMessageStart[3] = 0x0d;
- vAlertPubKey = ParseHex("045d2d29beffb0a0cbea44f266286ff8b1d11c035538fbb4dadcf6b4073b08f318afea74f01d5a3782e72a22273fb01ab40e99d93adff488236585cc8031323e7c");
- nDefaultPort = 19999;
-
-
-
- class CRegTestParams : public CTestNetParams {
- public:
- CRegTestParams() {
- networkID = CBaseChainParams::REGTEST;
- strNetworkID = "regtest";
- pchMessageStart[0] = 0x0b;
- pchMessageStart[1] = 0xad;
- pchMessageStart[2] = 0xf0;
- pchMessageStart[3] = 0x0d;
- nDefaultPort = 29999;
- bnProofOfWorkLimit = ~uint256(0) >> 1;
(6)修改种子网络连接参数
源文件 chainparams.cpp
-
-
-
-
-
-
-
- base58Prefixes[PUBKEY_ADDRESS] = list_of(35);
- base58Prefixes[SCRIPT_ADDRESS] = list_of(65);
- base58Prefixes[SECRET_KEY] = list_of(45);
- base58Prefixes[EXT_PUBLIC_KEY] = list_of(0x04)(0x88)(0xEE)(0x35);
- base58Prefixes[EXT_SECRET_KEY] = list_of(0x04)(0x88)(0xEE)(0x45);
-
-
如果你有7x24在线的服务器运行节点,那么请在这里加入他们的地址,可以是dns也可以是ip地址(v4,v6,--enable-ipv6)。
如果没有的话,可以考虑和我一样暂时注释掉,在运行时候指定连接参数-addnoe=123.123.123.123 或者-dns -addnode=mynode.domain.com
对应的修改一下TESTNET和REGTESTNET的网络节点地址。
(7)修改工作量机制
源文件 miner.cpp
比特币在函数ScanHash()里面搜索随机数,
-
-
-
-
-
-
- bool static ScanHash(const CBlockHeader *pblock, uint32_t& nNonce, uint256 *phash)
- {
-
-
-
-
-
-
-
- while (true) {
- nNonce++;
-
-
-
-
-
- *phash = pblock->ComputePowHash(nNonce);
-
-
-
- if (((uint16_t*)phash)[15] == 0)
- return true;
-
-
- 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里面设置)
- fMiningRequiresPeers = !true;
挖矿代码:
- void static BitcoinMiner(CWallet *pwallet)
- {
- LogPrintf("FastCoinMiner started\n");
- SetThreadPriority(THREAD_PRIORITY_LOWEST);
- RenameThread("fastcoin-miner");
-
-
- CReserveKey reservekey(pwallet);
- unsigned int nExtraNonce = 0;
-
- try {
- while (true) {
- if (Params().MiningRequiresPeers()) {
-
-
- while (vNodes.empty())
- MilliSleep(1000);
- }
-
-
-
-
- unsigned int nTransactionsUpdatedLast = mempool.GetTransactionsUpdated();
- CBlockIndex* pindexPrev = chainActive.Tip();
-
- auto_ptr 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算法,甚至你可以把这些算法串联起来,以增加算法被破解的方攻击性。
看代码吧:
- uint256 CBlockHeader::ComputePowHash(uint32_t nNonce) const
- {
- if (nVersion == 1 || nVersion == 2){
-
-
-
-
- CDoubleSHA256Pow hasher;
- 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){
-
-
-
- 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){
-
-
-
- }else if (nVersion == 5){
-
-
-
- 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{
-
- assert(false);
- return ~(uint256)0;
- }
- }
(8)修改奖励机制
参考9.3
8.1) 修改挖矿奖励的成熟时间
源代码:main.h
-
- static const int COINBASE_MATURITY = 14;
8.2) 修改交易确认块数推荐值
源代码 qt/transactionrecord.h
-
-
-
- class TransactionRecord
- {
- public:
- enum Type
- {
- Other,
- Generated,
- SendToAddress,
- SendToOther,
- RecvWithAddress,
- RecvFromOther,
- SendToSelf
- };
-
-
- static const int RecommendedNumConfirmations = 2;
(9)修改难度配置
源文件 chainparams.cpp
- class CMainParams : public CChainParams {
- public:
- CMainParams() {
- networkID = CBaseChainParams::MAIN;
- strNetworkID = "main";
-
-
-
-
-
- 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;
- nTargetTimespan = 60 * 60;
- nTargetSpacing = 1 * 60;
- nGenesisSubsidy = 100;
a) bnProofOfWorkLimit=~uint256(0) >> 32;
是一个大整数(256bit)表示,前面32个位数是0,这个参数表示全网允许的最小难度,低于这个难度的block是不会被挖掘的。
b) nGenesisSubsidy = 100;
初始津贴,比特币的第一个块的奖励是50个btc。
c) nSubsidyHavlingInterval = 210000;
这个参数决定了多少个block以后比特币的奖励(补贴,挖矿奖励)会减半。这个参数结合初始奖励(比如比特币50)基本可以估算全网总的货币产量(比如比特币的2100万),这个初始津贴也是可以配置的,如2)所示。比如比特币,一个等比数列求和公式就可以计算货币总量 50(1/(1 - 0.5))*210000=2100万btc。
上面2个参数在查询区块奖励的时候用到,请查看main.cpp 的 GetBlockValue(height, fees)找到细节
- CAmount GetBlockValue(int nHeight, const CAmount& nFees)
- {
- CAmount nSubsidy = Params().GenesisSubsidy() * COIN;
-
- int halvings = nHeight / Params().SubsidyHalvingInterval();
-
-
- if (halvings >= 64)
- return nFees;
-
-
- nSubsidy >>= halvings;
-
- return nSubsidy + nFees;
- }
很多山寨比也是在这里修改货币分布的,比如 nHeight==1 的时候,奖励1000万个,其他块都不予奖励,这个即使预挖模式了吧。
另外,关于货币分布,这里satoshi同学可能已经考虑很多,他为什么设置到很多年以后才矿源枯竭,为什么采取递减的方式,可能都是出于保护区块链的目的(timestampserver)。
d)难度调节周期
nTargetTimespan = 60 * 60; // re-targeting every one hour
nTargetSpacing = 1 * 60; // do new pow every 1 minutes.
这里的设置是60分钟(3600秒),重新评估难度,下一个块的挖掘可能就要使用新的难度设置了。
区块挖掘超时设置,在网络算力足够的情况下,一个节点可以挖矿的时间是有限的,比如这里这是的1分钟(60秒),超过这个时间,要么提交目前已找到的block(nNonce),要放弃自己的挖掘结果(使用网络上其他节点找到的一个最优结果)来寻找下一个block。否则其他节点也已经开始寻找next了,不过这个前提是算力足够,比如btc网络(现在应该到78个0的位置了吧),你如果10分钟内找不到,那么好了,可以放弃了,用别人的block吧,赶紧进入下一个回合的挖掘,否则很可能是浪费时间。
比特币的调节周期是 2周/每10分钟,也就是 2 * 7 * 24 * 6 = 2016
参考:http://bitcoindifficulty.com/blog/
https://en.bitcoin.it/wiki/Difficulty
(10) 修改checkpoints检查
(11) 修改界面
github地址
TODO:
1)模板化的山寨币生成,可配置修改部分通过宏或者变量提取出来,用脚本批量替换修改。
2)矿池搭建与节点测试 P2pool &Poclbm
3)移动支付和网页支付
4)应用生态
5)交易备注
6)复杂交易应用(脚本,非标准交易)
备注:
1)记得加上-checkpoints=0 参数启动,否则,会导致daemon报错,“FastCoin is downloading blocks...”
转自:http://blog.csdn.net/hacode/article/details/40422535