From 0b646aed42d44a3e7f41bff590f00395d6e390c8 Mon Sep 17 00:00:00 2001 From: coblee Date: Thu, 6 Oct 2011 03:31:30 -0700 Subject: [PATCH] Litecoin: Protocol, genesis and parameters * 2.5 minute average between blocks * 3.5 days between diff changes * 84 million coin limit * Addresses begin with L --- contrib/testgen/gen_base58_test_vectors.py | 4 +- src/alert.cpp | 2 +- src/base58.h | 14 ++++-- src/bitcoinrpc.cpp | 2 +- src/main.cpp | 52 +++++++++++----------- src/main.h | 4 +- 6 files changed, 42 insertions(+), 36 deletions(-) diff --git a/contrib/testgen/gen_base58_test_vectors.py b/contrib/testgen/gen_base58_test_vectors.py index 1813436953..92dee87abf 100755 --- a/contrib/testgen/gen_base58_test_vectors.py +++ b/contrib/testgen/gen_base58_test_vectors.py @@ -15,11 +15,11 @@ import random from binascii import b2a_hex # key types -PUBKEY_ADDRESS = 0 +PUBKEY_ADDRESS = 48 SCRIPT_ADDRESS = 5 PUBKEY_ADDRESS_TEST = 111 SCRIPT_ADDRESS_TEST = 196 -PRIVKEY = 128 +PRIVKEY = 176 PRIVKEY_TEST = 239 metadata_keys = ['isPrivkey', 'isTestnet', 'addrType', 'isCompressed'] diff --git a/src/alert.cpp b/src/alert.cpp index 4b029840dd..ea9de70b8b 100644 --- a/src/alert.cpp +++ b/src/alert.cpp @@ -19,7 +19,7 @@ using namespace std; map mapAlerts; CCriticalSection cs_mapAlerts; -static const char* pszMainKey = "04fc9702847840aaf195de8442ebecedf5b095cdbb9bc716bda9110971b28a49e0ead8564ff0db22209e0374782c093bb899692d524e9d6a6956e7c5ecbcd68284"; +static const char* pszMainKey = "040184710fa689ad5023690c80f3a49c8f13f8d45b8c857fbcbc8bc4a8e4d3eb4b10f4d4604fa08dce601aaf0f470216fe1b51850b4acf21b179c45070ac7b03a9"; static const char* pszTestKey = "04302390343f91cc401d56d68b123028bf52e5fca1939df127f63c6467cdf9c8e2c14b61104cf817d0b780da337893ecc4aaff1309e536162dabbdb45200ca2b0a"; void CUnsignedAlert::SetNull() diff --git a/src/base58.h b/src/base58.h index be8a541f67..9f4b70c555 100644 --- a/src/base58.h +++ b/src/base58.h @@ -272,7 +272,7 @@ class CBitcoinAddress : public CBase58Data public: enum { - PUBKEY_ADDRESS = 0, + PUBKEY_ADDRESS = 48, // Litecoin addresses start with L SCRIPT_ADDRESS = 5, PUBKEY_ADDRESS_TEST = 111, SCRIPT_ADDRESS_TEST = 196, @@ -398,10 +398,16 @@ bool inline CBitcoinAddressVisitor::operator()(const CNoDestination &id) const { class CBitcoinSecret : public CBase58Data { public: + enum + { + PRIVKEY_ADDRESS = CBitcoinAddress::PUBKEY_ADDRESS + 128, + PRIVKEY_ADDRESS_TEST = CBitcoinAddress::PUBKEY_ADDRESS_TEST + 128, + }; + void SetSecret(const CSecret& vchSecret, bool fCompressed) { assert(vchSecret.size() == 32); - SetData(fTestNet ? 239 : 128, &vchSecret[0], vchSecret.size()); + SetData(fTestNet ? PRIVKEY_ADDRESS_TEST : PRIVKEY_ADDRESS, &vchSecret[0], vchSecret.size()); if (fCompressed) vchData.push_back(1); } @@ -420,10 +426,10 @@ public: bool fExpectTestNet = false; switch(nVersion) { - case 128: + case PRIVKEY_ADDRESS: break; - case 239: + case PRIVKEY_ADDRESS_TEST: fExpectTestNet = true; break; diff --git a/src/bitcoinrpc.cpp b/src/bitcoinrpc.cpp index 4e68b92ad1..44102e5a50 100644 --- a/src/bitcoinrpc.cpp +++ b/src/bitcoinrpc.cpp @@ -97,7 +97,7 @@ void RPCTypeCheck(const Object& o, int64 AmountFromValue(const Value& value) { double dAmount = value.get_real(); - if (dAmount <= 0.0 || dAmount > 21000000.0) + if (dAmount <= 0.0 || dAmount > 84000000.0) throw JSONRPCError(RPC_TYPE_ERROR, "Invalid amount"); int64 nAmount = roundint64(dAmount * COIN); if (!MoneyRange(nAmount)) diff --git a/src/main.cpp b/src/main.cpp index 4bed65a763..c316a4ab1f 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -31,8 +31,8 @@ CTxMemPool mempool; unsigned int nTransactionsUpdated = 0; map mapBlockIndex; -uint256 hashGenesisBlock("0x000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f"); -static CBigNum bnProofOfWorkLimit(~uint256(0) >> 32); +uint256 hashGenesisBlock("0x12a765e31ffd4059bada1e25190f6e98c99d9714d334efa41a195a7e7e04bfe2"); +static CBigNum bnProofOfWorkLimit(~uint256(0) >> 20); // Litecoin: starting difficulty is 1 / 2^12 CBlockIndex* pindexGenesisBlock = NULL; int nBestHeight = -1; uint256 nBestChainWork = 0; @@ -1072,14 +1072,14 @@ int64 static GetBlockValue(int nHeight, int64 nFees) { int64 nSubsidy = 50 * COIN; - // Subsidy is cut in half every 210000 blocks, which will occur approximately every 4 years - nSubsidy >>= (nHeight / 210000); + // Subsidy is cut in half every 840000 blocks, which will occur approximately every 4 years + nSubsidy >>= (nHeight / 840000); // Litecoin: 840k blocks in ~4 years return nSubsidy + nFees; } -static const int64 nTargetTimespan = 14 * 24 * 60 * 60; // two weeks -static const int64 nTargetSpacing = 10 * 60; +static const int64 nTargetTimespan = 3.5 * 24 * 60 * 60; // Litecoin: 3.5 days +static const int64 nTargetSpacing = 2.5 * 60; // Litecoin: 2.5 minutes static const int64 nInterval = nTargetTimespan / nTargetSpacing; // @@ -2710,11 +2710,11 @@ bool LoadBlockIndex() { if (fTestNet) { - pchMessageStart[0] = 0x0b; - pchMessageStart[1] = 0x11; - pchMessageStart[2] = 0x09; - pchMessageStart[3] = 0x07; - hashGenesisBlock = uint256("000000000933ea01ad0ee984209779baaec3ced90fa3f408719526f8d77f4943"); + pchMessageStart[0] = 0xfc; + pchMessageStart[1] = 0xc1; + pchMessageStart[2] = 0xb7; + pchMessageStart[3] = 0xdc; + hashGenesisBlock = uint256("0xf5ae71e26c74beacc88382716aced69cddf3dffff24f384e1808905e0188f68f"); } // @@ -2740,33 +2740,33 @@ bool InitBlockIndex() { // Only add the genesis block if not reindexing (in which case we reuse the one already on disk) if (!fReindex) { // Genesis Block: - // 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 + // CBlock(hash=12a765e31ffd4059bada, PoW=0000050c34a64b415b6b, ver=1, hashPrevBlock=00000000000000000000, hashMerkleRoot=97ddfbbae6, nTime=1317972665, nBits=1e0ffff0, nNonce=2084524493, vtx=1) + // CTransaction(hash=97ddfbbae6, ver=1, vin.size=1, vout.size=1, nLockTime=0) + // CTxIn(COutPoint(0000000000, -1), coinbase 04ffff001d0104404e592054696d65732030352f4f63742f32303131205374657665204a6f62732c204170706c65e280997320566973696f6e6172792c2044696573206174203536) + // CTxOut(nValue=50.00000000, scriptPubKey=040184710fa689ad5023690c80f3a4) + // vMerkleTree: 97ddfbbae6 // Genesis block - const char* pszTimestamp = "The Times 03/Jan/2009 Chancellor on brink of second bailout for banks"; + const char* pszTimestamp = "NY Times 05/Oct/2011 Steve Jobs, Appleā€™s Visionary, Dies at 56"; CTransaction txNew; txNew.vin.resize(1); txNew.vout.resize(1); txNew.vin[0].scriptSig = CScript() << 486604799 << CBigNum(4) << vector((const unsigned char*)pszTimestamp, (const unsigned char*)pszTimestamp + strlen(pszTimestamp)); txNew.vout[0].nValue = 50 * COIN; - txNew.vout[0].scriptPubKey = CScript() << ParseHex("04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f") << OP_CHECKSIG; + txNew.vout[0].scriptPubKey = CScript() << ParseHex("040184710fa689ad5023690c80f3a49c8f13f8d45b8c857fbcbc8bc4a8e4d3eb4b10f4d4604fa08dce601aaf0f470216fe1b51850b4acf21b179c45070ac7b03a9") << OP_CHECKSIG; CBlock block; block.vtx.push_back(txNew); block.hashPrevBlock = 0; block.hashMerkleRoot = block.BuildMerkleTree(); block.nVersion = 1; - block.nTime = 1231006505; - block.nBits = 0x1d00ffff; - block.nNonce = 2083236893; + block.nTime = 1317972665; + block.nBits = 0x1e0ffff0; + block.nNonce = 2084524493; if (fTestNet) { - block.nTime = 1296688602; - block.nNonce = 414098458; + block.nTime = 1317798646; + block.nNonce = 385270584; } //// debug print @@ -2774,7 +2774,7 @@ bool InitBlockIndex() { printf("%s\n", hash.ToString().c_str()); printf("%s\n", hashGenesisBlock.ToString().c_str()); printf("%s\n", block.hashMerkleRoot.ToString().c_str()); - assert(block.hashMerkleRoot == uint256("0x4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b")); + assert(block.hashMerkleRoot == uint256("0x97ddfbbae6be97fd6cdf3e7ca13232a3afff2353e29badfab7f73011edd4ced9")); block.print(); assert(hash == hashGenesisBlock); @@ -3047,7 +3047,7 @@ bool static AlreadyHave(const CInv& inv) // 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. -unsigned char pchMessageStart[4] = { 0xf9, 0xbe, 0xb4, 0xd9 }; +unsigned char pchMessageStart[4] = { 0xfb, 0xc0, 0xb6, 0xdb }; // Litecoin: increase each by adding 2 to bitcoin's value. void static ProcessGetData(CNode* pfrom) @@ -4297,7 +4297,7 @@ CBlockTemplate* CreateNewBlock(CReserveKey& reservekey) // Prioritize by fee once past the priority size or we run out of high-priority // transactions: if (!fSortedByFee && - ((nBlockSize + nTxSize >= nBlockPrioritySize) || (dPriority < COIN * 144 / 250))) + ((nBlockSize + nTxSize >= nBlockPrioritySize) || (dPriority < COIN * 576 / 250))) { fSortedByFee = true; comparer = TxPriorityCompare(fSortedByFee); diff --git a/src/main.h b/src/main.h index 42578a6848..8c222646b8 100644 --- a/src/main.h +++ b/src/main.h @@ -46,7 +46,7 @@ static const unsigned int UNDOFILE_CHUNK_SIZE = 0x100000; // 1 MiB /** Fake height value used in CCoins to signify they are only in the memory pool (since 0.8) */ static const unsigned int MEMPOOL_HEIGHT = 0x7FFFFFFF; /** No amount larger than this (in satoshi) is valid */ -static const int64 MAX_MONEY = 21000000 * COIN; +static const int64 MAX_MONEY = 84000000 * COIN; inline bool MoneyRange(int64 nValue) { return (nValue >= 0 && nValue <= MAX_MONEY); } /** Coinbase transaction outputs can only be spent after this number of new blocks (network rule) */ static const int COINBASE_MATURITY = 100; @@ -608,7 +608,7 @@ public: { // Large (in bytes) low-priority (new, small-coin) transactions // need a fee. - return dPriority > COIN * 144 / 250; + return dPriority > COIN * 576 / 250; } int64 GetMinFee(unsigned int nBlockSize=1, bool fAllowFree=true, enum GetMinFee_mode mode=GMF_BLOCK) const;