Merge remote branch 'refs/remotes/svn/trunk' into svn
This commit is contained in:
commit
94073ecf7b
10 changed files with 467 additions and 252 deletions
41
coding.txt
Normal file
41
coding.txt
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
Please be consistent with the existing coding style.
|
||||||
|
|
||||||
|
Block style:
|
||||||
|
|
||||||
|
bool Function(char* psz, int n)
|
||||||
|
{
|
||||||
|
// Comment summarising what this section of code does
|
||||||
|
for (int i = 0; i < n; i++)
|
||||||
|
{
|
||||||
|
// When something fails, return early
|
||||||
|
if (!Something())
|
||||||
|
return false;
|
||||||
|
...
|
||||||
|
}
|
||||||
|
|
||||||
|
// Success return is usually at the end
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
- ANSI/Allman block style
|
||||||
|
- 4 space indenting, no tabs
|
||||||
|
- No extra spaces inside parenthesis; please don't do ( this )
|
||||||
|
- No space after function names, one space after if, for and while
|
||||||
|
|
||||||
|
Variable names begin with the type in lowercase, like nSomeVariable.
|
||||||
|
Please don't put the first word of the variable name in lowercase like
|
||||||
|
someVariable.
|
||||||
|
|
||||||
|
Common types:
|
||||||
|
n integer number: short, unsigned short, int, unsigned int,
|
||||||
|
int64, uint64, sometimes char if used as a number
|
||||||
|
d double, float
|
||||||
|
f flag
|
||||||
|
hash uint256
|
||||||
|
p pointer or array, one p for each level of indirection
|
||||||
|
psz pointer to null terminated string
|
||||||
|
str string object
|
||||||
|
v vector or similar list objects
|
||||||
|
map map or multimap
|
||||||
|
set set or multiset
|
||||||
|
bn CBigNum
|
4
db.cpp
4
db.cpp
|
@ -961,7 +961,7 @@ void CWalletDB::ReturnKey(int64 nIndex)
|
||||||
printf("keypool return %"PRI64d"\n", nIndex);
|
printf("keypool return %"PRI64d"\n", nIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
vector<unsigned char> CWalletDB::GetKeyFromKeyPool()
|
vector<unsigned char> GetKeyFromKeyPool()
|
||||||
{
|
{
|
||||||
CWalletDB walletdb;
|
CWalletDB walletdb;
|
||||||
int64 nIndex = 0;
|
int64 nIndex = 0;
|
||||||
|
@ -971,7 +971,7 @@ vector<unsigned char> CWalletDB::GetKeyFromKeyPool()
|
||||||
return keypool.vchPubKey;
|
return keypool.vchPubKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
int64 CWalletDB::GetOldestKeyPoolTime()
|
int64 GetOldestKeyPoolTime()
|
||||||
{
|
{
|
||||||
CWalletDB walletdb;
|
CWalletDB walletdb;
|
||||||
int64 nIndex = 0;
|
int64 nIndex = 0;
|
||||||
|
|
7
db.h
7
db.h
|
@ -26,6 +26,8 @@ extern DbEnv dbenv;
|
||||||
|
|
||||||
|
|
||||||
extern void DBFlush(bool fShutdown);
|
extern void DBFlush(bool fShutdown);
|
||||||
|
extern vector<unsigned char> GetKeyFromKeyPool();
|
||||||
|
extern int64 GetOldestKeyPoolTime();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -440,9 +442,8 @@ protected:
|
||||||
void KeepKey(int64 nIndex);
|
void KeepKey(int64 nIndex);
|
||||||
static void ReturnKey(int64 nIndex);
|
static void ReturnKey(int64 nIndex);
|
||||||
friend class CReserveKey;
|
friend class CReserveKey;
|
||||||
public:
|
friend vector<unsigned char> GetKeyFromKeyPool();
|
||||||
vector<unsigned char> GetKeyFromKeyPool();
|
friend int64 GetOldestKeyPoolTime();
|
||||||
int64 GetOldestKeyPoolTime();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
bool LoadWallet(bool& fFirstRunRet);
|
bool LoadWallet(bool& fFirstRunRet);
|
||||||
|
|
524
main.cpp
524
main.cpp
|
@ -159,7 +159,7 @@ bool AddToWallet(const CWalletTx& wtxIn)
|
||||||
if (txout.scriptPubKey == scriptDefaultKey)
|
if (txout.scriptPubKey == scriptDefaultKey)
|
||||||
{
|
{
|
||||||
CWalletDB walletdb;
|
CWalletDB walletdb;
|
||||||
vchDefaultKey = walletdb.GetKeyFromKeyPool();
|
vchDefaultKey = GetKeyFromKeyPool();
|
||||||
walletdb.WriteDefaultKey(vchDefaultKey);
|
walletdb.WriteDefaultKey(vchDefaultKey);
|
||||||
walletdb.WriteName(PubKeyToAddress(vchDefaultKey), "");
|
walletdb.WriteName(PubKeyToAddress(vchDefaultKey), "");
|
||||||
}
|
}
|
||||||
|
@ -1557,31 +1557,25 @@ bool ProcessBlock(CNode* pfrom, CBlock* pblock)
|
||||||
|
|
||||||
// Preliminary checks
|
// Preliminary checks
|
||||||
if (!pblock->CheckBlock())
|
if (!pblock->CheckBlock())
|
||||||
{
|
|
||||||
delete pblock;
|
|
||||||
return error("ProcessBlock() : CheckBlock FAILED");
|
return error("ProcessBlock() : CheckBlock FAILED");
|
||||||
}
|
|
||||||
|
|
||||||
// If don't already have its previous block, shunt it off to holding area until we get it
|
// If don't already have its previous block, shunt it off to holding area until we get it
|
||||||
if (!mapBlockIndex.count(pblock->hashPrevBlock))
|
if (!mapBlockIndex.count(pblock->hashPrevBlock))
|
||||||
{
|
{
|
||||||
printf("ProcessBlock: ORPHAN BLOCK, prev=%s\n", pblock->hashPrevBlock.ToString().substr(0,20).c_str());
|
printf("ProcessBlock: ORPHAN BLOCK, prev=%s\n", pblock->hashPrevBlock.ToString().substr(0,20).c_str());
|
||||||
mapOrphanBlocks.insert(make_pair(hash, pblock));
|
CBlock* pblock2 = new CBlock(*pblock);
|
||||||
mapOrphanBlocksByPrev.insert(make_pair(pblock->hashPrevBlock, pblock));
|
mapOrphanBlocks.insert(make_pair(hash, pblock2));
|
||||||
|
mapOrphanBlocksByPrev.insert(make_pair(pblock2->hashPrevBlock, pblock2));
|
||||||
|
|
||||||
// Ask this guy to fill in what we're missing
|
// Ask this guy to fill in what we're missing
|
||||||
if (pfrom)
|
if (pfrom)
|
||||||
pfrom->PushGetBlocks(pindexBest, GetOrphanRoot(pblock));
|
pfrom->PushGetBlocks(pindexBest, GetOrphanRoot(pblock2));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Store to disk
|
// Store to disk
|
||||||
if (!pblock->AcceptBlock())
|
if (!pblock->AcceptBlock())
|
||||||
{
|
|
||||||
delete pblock;
|
|
||||||
return error("ProcessBlock() : AcceptBlock FAILED");
|
return error("ProcessBlock() : AcceptBlock FAILED");
|
||||||
}
|
|
||||||
delete pblock;
|
|
||||||
|
|
||||||
// Recursively process any orphan blocks that depended on this one
|
// Recursively process any orphan blocks that depended on this one
|
||||||
vector<uint256> vWorkQueue;
|
vector<uint256> vWorkQueue;
|
||||||
|
@ -2504,7 +2498,7 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
|
||||||
CInv inv(MSG_BLOCK, pblock->GetHash());
|
CInv inv(MSG_BLOCK, pblock->GetHash());
|
||||||
pfrom->AddInventoryKnown(inv);
|
pfrom->AddInventoryKnown(inv);
|
||||||
|
|
||||||
if (ProcessBlock(pfrom, pblock.release()))
|
if (ProcessBlock(pfrom, pblock.get()))
|
||||||
mapAlreadyAskedFor.erase(inv);
|
mapAlreadyAskedFor.erase(inv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2549,7 +2543,7 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
|
||||||
|
|
||||||
// Keep giving the same key to the same ip until they use it
|
// Keep giving the same key to the same ip until they use it
|
||||||
if (!mapReuseKey.count(pfrom->addr.ip))
|
if (!mapReuseKey.count(pfrom->addr.ip))
|
||||||
mapReuseKey[pfrom->addr.ip] = CWalletDB().GetKeyFromKeyPool();
|
mapReuseKey[pfrom->addr.ip] = GetKeyFromKeyPool();
|
||||||
|
|
||||||
// Send back approval of order and pubkey to use
|
// Send back approval of order and pubkey to use
|
||||||
CScript scriptPubKey;
|
CScript scriptPubKey;
|
||||||
|
@ -3000,19 +2994,19 @@ inline void SHA256Transform(void* pstate, void* pinput, const void* pinit)
|
||||||
// ScanHash scans nonces looking for a hash with at least some zero bits.
|
// ScanHash scans nonces looking for a hash with at least some zero bits.
|
||||||
// It operates on big endian data. Caller does the byte reversing.
|
// It operates on big endian data. Caller does the byte reversing.
|
||||||
// All input buffers are 16-byte aligned. nNonce is usually preserved
|
// All input buffers are 16-byte aligned. nNonce is usually preserved
|
||||||
// between calls, but periodically or if nNonce is above 0xff000000,
|
// between calls, but periodically or if nNonce is 0xffff0000 or above,
|
||||||
// the block is rebuilt and nNonce starts over at zero.
|
// the block is rebuilt and nNonce starts over at zero.
|
||||||
//
|
//
|
||||||
unsigned int ScanHash_CryptoPP(char* pmidstate, char* pblock, char* phash1, char* phash, unsigned int& nHashesDone)
|
unsigned int ScanHash_CryptoPP(char* pmidstate, char* pdata, char* phash1, char* phash, unsigned int& nHashesDone)
|
||||||
{
|
{
|
||||||
unsigned int& nNonce = *(unsigned int*)(pblock + 12);
|
unsigned int& nNonce = *(unsigned int*)(pdata + 12);
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
// Crypto++ SHA-256
|
// Crypto++ SHA-256
|
||||||
// Hash pblock using pmidstate as the starting state into
|
// Hash pdata using pmidstate as the starting state into
|
||||||
// preformatted buffer phash1, then hash phash1 into phash
|
// preformatted buffer phash1, then hash phash1 into phash
|
||||||
nNonce++;
|
nNonce++;
|
||||||
SHA256Transform(phash1, pblock, pmidstate);
|
SHA256Transform(phash1, pdata, pmidstate);
|
||||||
SHA256Transform(phash, phash1, pSHA256InitState);
|
SHA256Transform(phash, phash1, pSHA256InitState);
|
||||||
|
|
||||||
// Return the nonce if the hash has at least some zero bits,
|
// Return the nonce if the hash has at least some zero bits,
|
||||||
|
@ -3055,6 +3049,262 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
CBlock* CreateNewBlock(CReserveKey& reservekey)
|
||||||
|
{
|
||||||
|
CBlockIndex* pindexPrev = pindexBest;
|
||||||
|
|
||||||
|
// Create new block
|
||||||
|
auto_ptr<CBlock> pblock(new CBlock());
|
||||||
|
if (!pblock.get())
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
// Create coinbase tx
|
||||||
|
CTransaction txNew;
|
||||||
|
txNew.vin.resize(1);
|
||||||
|
txNew.vin[0].prevout.SetNull();
|
||||||
|
txNew.vout.resize(1);
|
||||||
|
txNew.vout[0].scriptPubKey << reservekey.GetReservedKey() << OP_CHECKSIG;
|
||||||
|
|
||||||
|
// Add our coinbase tx as first transaction
|
||||||
|
pblock->vtx.push_back(txNew);
|
||||||
|
|
||||||
|
// Collect memory pool transactions into the block
|
||||||
|
int64 nFees = 0;
|
||||||
|
CRITICAL_BLOCK(cs_main)
|
||||||
|
CRITICAL_BLOCK(cs_mapTransactions)
|
||||||
|
{
|
||||||
|
CTxDB txdb("r");
|
||||||
|
|
||||||
|
// Priority order to process transactions
|
||||||
|
list<COrphan> vOrphan; // list memory doesn't move
|
||||||
|
map<uint256, vector<COrphan*> > mapDependers;
|
||||||
|
multimap<double, CTransaction*> mapPriority;
|
||||||
|
for (map<uint256, CTransaction>::iterator mi = mapTransactions.begin(); mi != mapTransactions.end(); ++mi)
|
||||||
|
{
|
||||||
|
CTransaction& tx = (*mi).second;
|
||||||
|
if (tx.IsCoinBase() || !tx.IsFinal())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
COrphan* porphan = NULL;
|
||||||
|
double dPriority = 0;
|
||||||
|
foreach(const CTxIn& txin, tx.vin)
|
||||||
|
{
|
||||||
|
// Read prev transaction
|
||||||
|
CTransaction txPrev;
|
||||||
|
CTxIndex txindex;
|
||||||
|
if (!txPrev.ReadFromDisk(txdb, txin.prevout, txindex))
|
||||||
|
{
|
||||||
|
// Has to wait for dependencies
|
||||||
|
if (!porphan)
|
||||||
|
{
|
||||||
|
// Use list for automatic deletion
|
||||||
|
vOrphan.push_back(COrphan(&tx));
|
||||||
|
porphan = &vOrphan.back();
|
||||||
|
}
|
||||||
|
mapDependers[txin.prevout.hash].push_back(porphan);
|
||||||
|
porphan->setDependsOn.insert(txin.prevout.hash);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
int64 nValueIn = txPrev.vout[txin.prevout.n].nValue;
|
||||||
|
|
||||||
|
// Read block header
|
||||||
|
int nConf = 0;
|
||||||
|
CBlock block;
|
||||||
|
if (block.ReadFromDisk(txindex.pos.nFile, txindex.pos.nBlockPos, false))
|
||||||
|
{
|
||||||
|
map<uint256, CBlockIndex*>::iterator it = mapBlockIndex.find(block.GetHash());
|
||||||
|
if (it != mapBlockIndex.end())
|
||||||
|
{
|
||||||
|
CBlockIndex* pindex = (*it).second;
|
||||||
|
if (pindex->IsInMainChain())
|
||||||
|
nConf = 1 + nBestHeight - pindex->nHeight;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dPriority += (double)nValueIn * nConf;
|
||||||
|
|
||||||
|
if (fDebug && mapArgs.count("-printpriority"))
|
||||||
|
printf("priority nValueIn=%-12I64d nConf=%-5d dPriority=%-20.1f\n", nValueIn, nConf, dPriority);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Priority is sum(valuein * age) / txsize
|
||||||
|
dPriority /= ::GetSerializeSize(tx, SER_NETWORK);
|
||||||
|
|
||||||
|
if (porphan)
|
||||||
|
porphan->dPriority = dPriority;
|
||||||
|
else
|
||||||
|
mapPriority.insert(make_pair(-dPriority, &(*mi).second));
|
||||||
|
|
||||||
|
if (fDebug && mapArgs.count("-printpriority"))
|
||||||
|
{
|
||||||
|
printf("priority %-20.1f %s\n%s", dPriority, tx.GetHash().ToString().substr(0,10).c_str(), tx.ToString().c_str());
|
||||||
|
if (porphan)
|
||||||
|
porphan->print();
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Collect transactions into block
|
||||||
|
map<uint256, CTxIndex> mapTestPool;
|
||||||
|
uint64 nBlockSize = 1000;
|
||||||
|
int nBlockSigOps = 100;
|
||||||
|
while (!mapPriority.empty())
|
||||||
|
{
|
||||||
|
// Take highest priority transaction off priority queue
|
||||||
|
double dPriority = -(*mapPriority.begin()).first;
|
||||||
|
CTransaction& tx = *(*mapPriority.begin()).second;
|
||||||
|
mapPriority.erase(mapPriority.begin());
|
||||||
|
|
||||||
|
// Size limits
|
||||||
|
unsigned int nTxSize = ::GetSerializeSize(tx, SER_NETWORK);
|
||||||
|
if (nBlockSize + nTxSize >= MAX_BLOCK_SIZE_GEN)
|
||||||
|
continue;
|
||||||
|
int nTxSigOps = tx.GetSigOpCount();
|
||||||
|
if (nBlockSigOps + nTxSigOps >= MAX_BLOCK_SIGOPS)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Transaction fee required depends on block size
|
||||||
|
bool fAllowFree = (nBlockSize + nTxSize < 4000 || dPriority > COIN * 144 / 250);
|
||||||
|
int64 nMinFee = tx.GetMinFee(nBlockSize, fAllowFree);
|
||||||
|
|
||||||
|
// Connecting shouldn't fail due to dependency on other memory pool transactions
|
||||||
|
// because we're already processing them in order of dependency
|
||||||
|
map<uint256, CTxIndex> mapTestPoolTmp(mapTestPool);
|
||||||
|
if (!tx.ConnectInputs(txdb, mapTestPoolTmp, CDiskTxPos(1,1,1), pindexPrev, nFees, false, true, nMinFee))
|
||||||
|
continue;
|
||||||
|
swap(mapTestPool, mapTestPoolTmp);
|
||||||
|
|
||||||
|
// Added
|
||||||
|
pblock->vtx.push_back(tx);
|
||||||
|
nBlockSize += nTxSize;
|
||||||
|
nBlockSigOps += nTxSigOps;
|
||||||
|
|
||||||
|
// Add transactions that depend on this one to the priority queue
|
||||||
|
uint256 hash = tx.GetHash();
|
||||||
|
if (mapDependers.count(hash))
|
||||||
|
{
|
||||||
|
foreach(COrphan* porphan, mapDependers[hash])
|
||||||
|
{
|
||||||
|
if (!porphan->setDependsOn.empty())
|
||||||
|
{
|
||||||
|
porphan->setDependsOn.erase(hash);
|
||||||
|
if (porphan->setDependsOn.empty())
|
||||||
|
mapPriority.insert(make_pair(-porphan->dPriority, porphan->ptx));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pblock->vtx[0].vout[0].nValue = GetBlockValue(pindexPrev->nHeight+1, nFees);
|
||||||
|
|
||||||
|
// Fill in header
|
||||||
|
pblock->hashPrevBlock = pindexPrev->GetBlockHash();
|
||||||
|
pblock->hashMerkleRoot = pblock->BuildMerkleTree();
|
||||||
|
pblock->nTime = max(pindexPrev->GetMedianTimePast()+1, GetAdjustedTime());
|
||||||
|
pblock->nBits = GetNextWorkRequired(pindexPrev);
|
||||||
|
pblock->nNonce = 0;
|
||||||
|
|
||||||
|
return pblock.release();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void IncrementExtraNonce(CBlock* pblock, CBlockIndex* pindexPrev, unsigned int& nExtraNonce, int64& nPrevTime)
|
||||||
|
{
|
||||||
|
// Update nExtraNonce
|
||||||
|
int64 nNow = max(pindexPrev->GetMedianTimePast()+1, GetAdjustedTime());
|
||||||
|
if (++nExtraNonce >= 0x7f && nNow > nPrevTime+1)
|
||||||
|
{
|
||||||
|
nExtraNonce = 1;
|
||||||
|
nPrevTime = nNow;
|
||||||
|
}
|
||||||
|
pblock->vtx[0].vin[0].scriptSig = CScript() << pblock->nBits << CBigNum(nExtraNonce);
|
||||||
|
pblock->hashMerkleRoot = pblock->BuildMerkleTree();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void FormatHashBuffers(CBlock* pblock, char* pmidstate, char* pdata, char* phash1)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// Prebuild hash buffers
|
||||||
|
//
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
struct unnamed2
|
||||||
|
{
|
||||||
|
int nVersion;
|
||||||
|
uint256 hashPrevBlock;
|
||||||
|
uint256 hashMerkleRoot;
|
||||||
|
unsigned int nTime;
|
||||||
|
unsigned int nBits;
|
||||||
|
unsigned int nNonce;
|
||||||
|
}
|
||||||
|
block;
|
||||||
|
unsigned char pchPadding0[64];
|
||||||
|
uint256 hash1;
|
||||||
|
unsigned char pchPadding1[64];
|
||||||
|
}
|
||||||
|
tmp;
|
||||||
|
memset(&tmp, 0, sizeof(tmp));
|
||||||
|
|
||||||
|
tmp.block.nVersion = pblock->nVersion;
|
||||||
|
tmp.block.hashPrevBlock = pblock->hashPrevBlock;
|
||||||
|
tmp.block.hashMerkleRoot = pblock->hashMerkleRoot;
|
||||||
|
tmp.block.nTime = pblock->nTime;
|
||||||
|
tmp.block.nBits = pblock->nBits;
|
||||||
|
tmp.block.nNonce = pblock->nNonce;
|
||||||
|
|
||||||
|
FormatHashBlocks(&tmp.block, sizeof(tmp.block));
|
||||||
|
FormatHashBlocks(&tmp.hash1, sizeof(tmp.hash1));
|
||||||
|
|
||||||
|
// Byte swap all the input buffer
|
||||||
|
for (int i = 0; i < sizeof(tmp)/4; i++)
|
||||||
|
((unsigned int*)&tmp)[i] = ByteReverse(((unsigned int*)&tmp)[i]);
|
||||||
|
|
||||||
|
// Precalc the first half of the first hash, which stays constant
|
||||||
|
SHA256Transform(pmidstate, &tmp.block, pSHA256InitState);
|
||||||
|
|
||||||
|
memcpy(pdata, &tmp.block, 128);
|
||||||
|
memcpy(phash1, &tmp.hash1, 64);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool CheckWork(CBlock* pblock, CReserveKey& reservekey)
|
||||||
|
{
|
||||||
|
uint256 hash = pblock->GetHash();
|
||||||
|
uint256 hashTarget = CBigNum().SetCompact(pblock->nBits).getuint256();
|
||||||
|
|
||||||
|
if (hash > hashTarget)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
//// debug print
|
||||||
|
printf("BitcoinMiner:\n");
|
||||||
|
printf("proof-of-work found \n hash: %s \ntarget: %s\n", hash.GetHex().c_str(), hashTarget.GetHex().c_str());
|
||||||
|
pblock->print();
|
||||||
|
printf("%s ", DateTimeStrFormat("%x %H:%M", GetTime()).c_str());
|
||||||
|
printf("generated %s\n", FormatMoney(pblock->vtx[0].vout[0].nValue).c_str());
|
||||||
|
|
||||||
|
// Found a solution
|
||||||
|
CRITICAL_BLOCK(cs_main)
|
||||||
|
{
|
||||||
|
if (pblock->hashPrevBlock != hashBestChain)
|
||||||
|
return error("BitcoinMiner : generated block is stale");
|
||||||
|
|
||||||
|
// Remove key from key pool
|
||||||
|
reservekey.KeepKey();
|
||||||
|
|
||||||
|
// Track how many getdata requests this block gets
|
||||||
|
CRITICAL_BLOCK(cs_mapRequestCount)
|
||||||
|
mapRequestCount[pblock->GetHash()] = 0;
|
||||||
|
|
||||||
|
// Process this block the same as if we had received it from another node
|
||||||
|
if (!ProcessBlock(NULL, pblock))
|
||||||
|
return error("BitcoinMiner : ProcessBlock, block not accepted");
|
||||||
|
}
|
||||||
|
|
||||||
|
Sleep(2000);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void BitcoinMiner()
|
void BitcoinMiner()
|
||||||
{
|
{
|
||||||
|
@ -3064,9 +3314,11 @@ void BitcoinMiner()
|
||||||
if (mapArgs.count("-4way"))
|
if (mapArgs.count("-4way"))
|
||||||
f4WaySSE2 = (mapArgs["-4way"] != "0");
|
f4WaySSE2 = (mapArgs["-4way"] != "0");
|
||||||
|
|
||||||
|
// Each thread has its own key and counter
|
||||||
CReserveKey reservekey;
|
CReserveKey reservekey;
|
||||||
unsigned int nExtraNonce = 0;
|
unsigned int nExtraNonce = 0;
|
||||||
int64 nPrevTime = 0;
|
int64 nPrevTime = 0;
|
||||||
|
|
||||||
while (fGenerateBitcoins)
|
while (fGenerateBitcoins)
|
||||||
{
|
{
|
||||||
if (AffinityBugWorkaround(ThreadBitcoinMiner))
|
if (AffinityBugWorkaround(ThreadBitcoinMiner))
|
||||||
|
@ -3082,210 +3334,32 @@ void BitcoinMiner()
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int nTransactionsUpdatedLast = nTransactionsUpdated;
|
|
||||||
CBlockIndex* pindexPrev = pindexBest;
|
|
||||||
unsigned int nBits = GetNextWorkRequired(pindexPrev);
|
|
||||||
|
|
||||||
|
|
||||||
//
|
|
||||||
// Create coinbase tx
|
|
||||||
//
|
|
||||||
CTransaction txNew;
|
|
||||||
txNew.vin.resize(1);
|
|
||||||
txNew.vin[0].prevout.SetNull();
|
|
||||||
int64 nNow = max(pindexPrev->GetMedianTimePast()+1, GetAdjustedTime());
|
|
||||||
if (++nExtraNonce >= 0x7f && nNow > nPrevTime+1)
|
|
||||||
{
|
|
||||||
nExtraNonce = 1;
|
|
||||||
nPrevTime = nNow;
|
|
||||||
}
|
|
||||||
txNew.vin[0].scriptSig << nBits << CBigNum(nExtraNonce);
|
|
||||||
txNew.vout.resize(1);
|
|
||||||
txNew.vout[0].scriptPubKey << reservekey.GetReservedKey() << OP_CHECKSIG;
|
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Create new block
|
// Create new block
|
||||||
//
|
//
|
||||||
auto_ptr<CBlock> pblock(new CBlock());
|
unsigned int nTransactionsUpdatedLast = nTransactionsUpdated;
|
||||||
|
CBlockIndex* pindexPrev = pindexBest;
|
||||||
|
|
||||||
|
auto_ptr<CBlock> pblock(CreateNewBlock(reservekey));
|
||||||
if (!pblock.get())
|
if (!pblock.get())
|
||||||
return;
|
return;
|
||||||
|
IncrementExtraNonce(pblock.get(), pindexPrev, nExtraNonce, nPrevTime);
|
||||||
|
|
||||||
// Add our coinbase tx as first transaction
|
|
||||||
pblock->vtx.push_back(txNew);
|
|
||||||
|
|
||||||
// Collect memory pool transactions into the block
|
|
||||||
int64 nFees = 0;
|
|
||||||
CRITICAL_BLOCK(cs_main)
|
|
||||||
CRITICAL_BLOCK(cs_mapTransactions)
|
|
||||||
{
|
|
||||||
CTxDB txdb("r");
|
|
||||||
|
|
||||||
// Priority order to process transactions
|
|
||||||
list<COrphan> vOrphan; // list memory doesn't move
|
|
||||||
map<uint256, vector<COrphan*> > mapDependers;
|
|
||||||
multimap<double, CTransaction*> mapPriority;
|
|
||||||
for (map<uint256, CTransaction>::iterator mi = mapTransactions.begin(); mi != mapTransactions.end(); ++mi)
|
|
||||||
{
|
|
||||||
CTransaction& tx = (*mi).second;
|
|
||||||
if (tx.IsCoinBase() || !tx.IsFinal())
|
|
||||||
continue;
|
|
||||||
|
|
||||||
COrphan* porphan = NULL;
|
|
||||||
double dPriority = 0;
|
|
||||||
foreach(const CTxIn& txin, tx.vin)
|
|
||||||
{
|
|
||||||
// Read prev transaction
|
|
||||||
CTransaction txPrev;
|
|
||||||
CTxIndex txindex;
|
|
||||||
if (!txPrev.ReadFromDisk(txdb, txin.prevout, txindex))
|
|
||||||
{
|
|
||||||
// Has to wait for dependencies
|
|
||||||
if (!porphan)
|
|
||||||
{
|
|
||||||
// Use list for automatic deletion
|
|
||||||
vOrphan.push_back(COrphan(&tx));
|
|
||||||
porphan = &vOrphan.back();
|
|
||||||
}
|
|
||||||
mapDependers[txin.prevout.hash].push_back(porphan);
|
|
||||||
porphan->setDependsOn.insert(txin.prevout.hash);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
int64 nValueIn = txPrev.vout[txin.prevout.n].nValue;
|
|
||||||
|
|
||||||
// Read block header
|
|
||||||
int nConf = 0;
|
|
||||||
CBlock block;
|
|
||||||
if (block.ReadFromDisk(txindex.pos.nFile, txindex.pos.nBlockPos, false))
|
|
||||||
{
|
|
||||||
map<uint256, CBlockIndex*>::iterator it = mapBlockIndex.find(block.GetHash());
|
|
||||||
if (it != mapBlockIndex.end())
|
|
||||||
{
|
|
||||||
CBlockIndex* pindex = (*it).second;
|
|
||||||
if (pindex->IsInMainChain())
|
|
||||||
nConf = 1 + nBestHeight - pindex->nHeight;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
dPriority += (double)nValueIn * nConf;
|
|
||||||
|
|
||||||
if (fDebug && mapArgs.count("-printpriority"))
|
|
||||||
printf("priority nValueIn=%-12I64d nConf=%-5d dPriority=%-20.1f\n", nValueIn, nConf, dPriority);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Priority is sum(valuein * age) / txsize
|
|
||||||
dPriority /= ::GetSerializeSize(tx, SER_NETWORK);
|
|
||||||
|
|
||||||
if (porphan)
|
|
||||||
porphan->dPriority = dPriority;
|
|
||||||
else
|
|
||||||
mapPriority.insert(make_pair(-dPriority, &(*mi).second));
|
|
||||||
|
|
||||||
if (fDebug && mapArgs.count("-printpriority"))
|
|
||||||
{
|
|
||||||
printf("priority %-20.1f %s\n%s", dPriority, tx.GetHash().ToString().substr(0,10).c_str(), tx.ToString().c_str());
|
|
||||||
if (porphan)
|
|
||||||
porphan->print();
|
|
||||||
printf("\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Collect transactions into block
|
|
||||||
map<uint256, CTxIndex> mapTestPool;
|
|
||||||
uint64 nBlockSize = 1000;
|
|
||||||
int nBlockSigOps = 100;
|
|
||||||
while (!mapPriority.empty())
|
|
||||||
{
|
|
||||||
// Take highest priority transaction off priority queue
|
|
||||||
double dPriority = -(*mapPriority.begin()).first;
|
|
||||||
CTransaction& tx = *(*mapPriority.begin()).second;
|
|
||||||
mapPriority.erase(mapPriority.begin());
|
|
||||||
|
|
||||||
// Size limits
|
|
||||||
unsigned int nTxSize = ::GetSerializeSize(tx, SER_NETWORK);
|
|
||||||
if (nBlockSize + nTxSize >= MAX_BLOCK_SIZE_GEN)
|
|
||||||
continue;
|
|
||||||
int nTxSigOps = tx.GetSigOpCount();
|
|
||||||
if (nBlockSigOps + nTxSigOps >= MAX_BLOCK_SIGOPS)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// Transaction fee required depends on block size
|
|
||||||
bool fAllowFree = (nBlockSize + nTxSize < 4000 || dPriority > COIN * 144 / 250);
|
|
||||||
int64 nMinFee = tx.GetMinFee(nBlockSize, fAllowFree);
|
|
||||||
|
|
||||||
// Connecting shouldn't fail due to dependency on other memory pool transactions
|
|
||||||
// because we're already processing them in order of dependency
|
|
||||||
map<uint256, CTxIndex> mapTestPoolTmp(mapTestPool);
|
|
||||||
if (!tx.ConnectInputs(txdb, mapTestPoolTmp, CDiskTxPos(1,1,1), pindexPrev, nFees, false, true, nMinFee))
|
|
||||||
continue;
|
|
||||||
swap(mapTestPool, mapTestPoolTmp);
|
|
||||||
|
|
||||||
// Added
|
|
||||||
pblock->vtx.push_back(tx);
|
|
||||||
nBlockSize += nTxSize;
|
|
||||||
nBlockSigOps += nTxSigOps;
|
|
||||||
|
|
||||||
// Add transactions that depend on this one to the priority queue
|
|
||||||
uint256 hash = tx.GetHash();
|
|
||||||
if (mapDependers.count(hash))
|
|
||||||
{
|
|
||||||
foreach(COrphan* porphan, mapDependers[hash])
|
|
||||||
{
|
|
||||||
if (!porphan->setDependsOn.empty())
|
|
||||||
{
|
|
||||||
porphan->setDependsOn.erase(hash);
|
|
||||||
if (porphan->setDependsOn.empty())
|
|
||||||
mapPriority.insert(make_pair(-porphan->dPriority, porphan->ptx));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pblock->nBits = nBits;
|
|
||||||
pblock->vtx[0].vout[0].nValue = GetBlockValue(pindexPrev->nHeight+1, nFees);
|
|
||||||
printf("Running BitcoinMiner with %d transactions in block\n", pblock->vtx.size());
|
printf("Running BitcoinMiner with %d transactions in block\n", pblock->vtx.size());
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Prebuild hash buffer
|
// Prebuild hash buffers
|
||||||
//
|
//
|
||||||
struct tmpworkspace
|
char pmidstatebuf[32+16]; char* pmidstate = alignup<16>(pmidstatebuf);
|
||||||
{
|
char pdatabuf[128+16]; char* pdata = alignup<16>(pdatabuf);
|
||||||
struct unnamed2
|
char phash1buf[64+16]; char* phash1 = alignup<16>(phash1buf);
|
||||||
{
|
|
||||||
int nVersion;
|
|
||||||
uint256 hashPrevBlock;
|
|
||||||
uint256 hashMerkleRoot;
|
|
||||||
unsigned int nTime;
|
|
||||||
unsigned int nBits;
|
|
||||||
unsigned int nNonce;
|
|
||||||
}
|
|
||||||
block;
|
|
||||||
unsigned char pchPadding0[64];
|
|
||||||
uint256 hash1;
|
|
||||||
unsigned char pchPadding1[64];
|
|
||||||
};
|
|
||||||
char tmpbuf[sizeof(tmpworkspace)+16];
|
|
||||||
tmpworkspace& tmp = *(tmpworkspace*)alignup<16>(tmpbuf);
|
|
||||||
|
|
||||||
tmp.block.nVersion = pblock->nVersion;
|
FormatHashBuffers(pblock.get(), pmidstate, pdata, phash1);
|
||||||
tmp.block.hashPrevBlock = pblock->hashPrevBlock = pindexPrev->GetBlockHash();
|
|
||||||
tmp.block.hashMerkleRoot = pblock->hashMerkleRoot = pblock->BuildMerkleTree();
|
|
||||||
tmp.block.nTime = pblock->nTime = max(pindexPrev->GetMedianTimePast()+1, GetAdjustedTime());
|
|
||||||
tmp.block.nBits = pblock->nBits = nBits;
|
|
||||||
tmp.block.nNonce = pblock->nNonce = 0;
|
|
||||||
|
|
||||||
unsigned int nBlocks0 = FormatHashBlocks(&tmp.block, sizeof(tmp.block));
|
unsigned int& nBlockTime = *(unsigned int*)(pdata + 64 + 4);
|
||||||
unsigned int nBlocks1 = FormatHashBlocks(&tmp.hash1, sizeof(tmp.hash1));
|
unsigned int& nBlockNonce = *(unsigned int*)(pdata + 64 + 12);
|
||||||
|
|
||||||
// Byte swap all the input buffer
|
|
||||||
for (int i = 0; i < sizeof(tmp)/4; i++)
|
|
||||||
((unsigned int*)&tmp)[i] = ByteReverse(((unsigned int*)&tmp)[i]);
|
|
||||||
|
|
||||||
// Precalc the first half of the first hash, which stays constant
|
|
||||||
uint256 midstatebuf[2];
|
|
||||||
uint256& midstate = *alignup<16>(midstatebuf);
|
|
||||||
SHA256Transform(&midstate, &tmp.block, pSHA256InitState);
|
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -3303,11 +3377,11 @@ void BitcoinMiner()
|
||||||
#ifdef FOURWAYSSE2
|
#ifdef FOURWAYSSE2
|
||||||
if (f4WaySSE2)
|
if (f4WaySSE2)
|
||||||
// tcatm's 4-way 128-bit SSE2 SHA-256
|
// tcatm's 4-way 128-bit SSE2 SHA-256
|
||||||
nNonceFound = ScanHash_4WaySSE2((char*)&midstate, (char*)&tmp.block + 64, (char*)&tmp.hash1, (char*)&hash, nHashesDone);
|
nNonceFound = ScanHash_4WaySSE2(pmidstate, pdata + 64, phash1, (char*)&hash, nHashesDone);
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
// Crypto++ SHA-256
|
// Crypto++ SHA-256
|
||||||
nNonceFound = ScanHash_CryptoPP((char*)&midstate, (char*)&tmp.block + 64, (char*)&tmp.hash1, (char*)&hash, nHashesDone);
|
nNonceFound = ScanHash_CryptoPP(pmidstate, pdata + 64, phash1, (char*)&hash, nHashesDone);
|
||||||
|
|
||||||
// Check if something found
|
// Check if something found
|
||||||
if (nNonceFound != -1)
|
if (nNonceFound != -1)
|
||||||
|
@ -3321,33 +3395,9 @@ void BitcoinMiner()
|
||||||
pblock->nNonce = ByteReverse(nNonceFound);
|
pblock->nNonce = ByteReverse(nNonceFound);
|
||||||
assert(hash == pblock->GetHash());
|
assert(hash == pblock->GetHash());
|
||||||
|
|
||||||
//// debug print
|
|
||||||
printf("BitcoinMiner:\n");
|
|
||||||
printf("proof-of-work found \n hash: %s \ntarget: %s\n", hash.GetHex().c_str(), hashTarget.GetHex().c_str());
|
|
||||||
pblock->print();
|
|
||||||
printf("%s ", DateTimeStrFormat("%x %H:%M", GetTime()).c_str());
|
|
||||||
printf("generated %s\n", FormatMoney(pblock->vtx[0].vout[0].nValue).c_str());
|
|
||||||
|
|
||||||
SetThreadPriority(THREAD_PRIORITY_NORMAL);
|
SetThreadPriority(THREAD_PRIORITY_NORMAL);
|
||||||
CRITICAL_BLOCK(cs_main)
|
CheckWork(pblock.get(), reservekey);
|
||||||
{
|
|
||||||
if (pindexPrev == pindexBest)
|
|
||||||
{
|
|
||||||
// Remove key from key pool
|
|
||||||
reservekey.KeepKey();
|
|
||||||
|
|
||||||
// Track how many getdata requests this block gets
|
|
||||||
CRITICAL_BLOCK(cs_mapRequestCount)
|
|
||||||
mapRequestCount[pblock->GetHash()] = 0;
|
|
||||||
|
|
||||||
// Process this block the same as if we had received it from another node
|
|
||||||
if (!ProcessBlock(NULL, pblock.release()))
|
|
||||||
printf("ERROR in BitcoinMiner, ProcessBlock, block not accepted\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
SetThreadPriority(THREAD_PRIORITY_LOWEST);
|
SetThreadPriority(THREAD_PRIORITY_LOWEST);
|
||||||
|
|
||||||
Sleep(500);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3393,7 +3443,7 @@ void BitcoinMiner()
|
||||||
return;
|
return;
|
||||||
if (vNodes.empty())
|
if (vNodes.empty())
|
||||||
break;
|
break;
|
||||||
if (tmp.block.nNonce >= 0xff000000)
|
if (nBlockNonce >= 0xffff0000)
|
||||||
break;
|
break;
|
||||||
if (nTransactionsUpdated != nTransactionsUpdatedLast && GetTime() - nStart > 60)
|
if (nTransactionsUpdated != nTransactionsUpdatedLast && GetTime() - nStart > 60)
|
||||||
break;
|
break;
|
||||||
|
@ -3402,7 +3452,7 @@ void BitcoinMiner()
|
||||||
|
|
||||||
// Update nTime every few seconds
|
// Update nTime every few seconds
|
||||||
pblock->nTime = max(pindexPrev->GetMedianTimePast()+1, GetAdjustedTime());
|
pblock->nTime = max(pindexPrev->GetMedianTimePast()+1, GetAdjustedTime());
|
||||||
tmp.block.nTime = ByteReverse(pblock->nTime);
|
nBlockTime = ByteReverse(pblock->nTime);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
11
main.h
11
main.h
|
@ -83,6 +83,10 @@ string SendMoney(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, bool fAs
|
||||||
string SendMoneyToBitcoinAddress(string strAddress, int64 nValue, CWalletTx& wtxNew, bool fAskFee=false);
|
string SendMoneyToBitcoinAddress(string strAddress, int64 nValue, CWalletTx& wtxNew, bool fAskFee=false);
|
||||||
void GenerateBitcoins(bool fGenerate);
|
void GenerateBitcoins(bool fGenerate);
|
||||||
void ThreadBitcoinMiner(void* parg);
|
void ThreadBitcoinMiner(void* parg);
|
||||||
|
CBlock* CreateNewBlock(CReserveKey& reservekey);
|
||||||
|
void IncrementExtraNonce(CBlock* pblock, CBlockIndex* pindexPrev, unsigned int& nExtraNonce, int64& nPrevTime);
|
||||||
|
void FormatHashBuffers(CBlock* pblock, char* pmidstate, char* pdata, char* phash1);
|
||||||
|
bool CheckWork(CBlock* pblock, CReserveKey& reservekey);
|
||||||
void BitcoinMiner();
|
void BitcoinMiner();
|
||||||
bool CheckProofOfWork(uint256 hash, unsigned int nBits);
|
bool CheckProofOfWork(uint256 hash, unsigned int nBits);
|
||||||
bool IsInitialBlockDownload();
|
bool IsInitialBlockDownload();
|
||||||
|
@ -753,21 +757,28 @@ public:
|
||||||
|
|
||||||
void Init()
|
void Init()
|
||||||
{
|
{
|
||||||
|
vtxPrev.clear();
|
||||||
|
mapValue.clear();
|
||||||
|
vOrderForm.clear();
|
||||||
nTimeReceived = 0;
|
nTimeReceived = 0;
|
||||||
fFromMe = false;
|
fFromMe = false;
|
||||||
fSpent = false;
|
fSpent = false;
|
||||||
fTimeReceivedIsTxTime = false;
|
fTimeReceivedIsTxTime = false;
|
||||||
fUnused = false;
|
fUnused = false;
|
||||||
|
strFromAccount.clear();
|
||||||
fDebitCached = false;
|
fDebitCached = false;
|
||||||
fCreditCached = false;
|
fCreditCached = false;
|
||||||
nDebitCached = 0;
|
nDebitCached = 0;
|
||||||
nCreditCached = 0;
|
nCreditCached = 0;
|
||||||
nTimeDisplayed = 0;
|
nTimeDisplayed = 0;
|
||||||
nLinesDisplayed = 0;
|
nLinesDisplayed = 0;
|
||||||
|
fConfirmedDisplayed = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
IMPLEMENT_SERIALIZE
|
IMPLEMENT_SERIALIZE
|
||||||
(
|
(
|
||||||
|
if (fRead)
|
||||||
|
const_cast<CWalletTx*>(this)->Init();
|
||||||
nSerSize += SerReadWrite(s, *(CMerkleTx*)this, nType, nVersion, ser_action);
|
nSerSize += SerReadWrite(s, *(CMerkleTx*)this, nType, nVersion, ser_action);
|
||||||
READWRITE(vtxPrev);
|
READWRITE(vtxPrev);
|
||||||
READWRITE(mapValue);
|
READWRITE(mapValue);
|
||||||
|
|
119
rpc.cpp
119
rpc.cpp
|
@ -3,6 +3,7 @@
|
||||||
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
|
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
|
||||||
|
|
||||||
#include "headers.h"
|
#include "headers.h"
|
||||||
|
#include "cryptopp/sha.h"
|
||||||
#undef printf
|
#undef printf
|
||||||
#include <boost/asio.hpp>
|
#include <boost/asio.hpp>
|
||||||
#include <boost/iostreams/concepts.hpp>
|
#include <boost/iostreams/concepts.hpp>
|
||||||
|
@ -50,6 +51,7 @@ void PrintConsole(const char* format, ...)
|
||||||
ret = limit - 1;
|
ret = limit - 1;
|
||||||
buffer[limit-1] = 0;
|
buffer[limit-1] = 0;
|
||||||
}
|
}
|
||||||
|
printf("%s", buffer);
|
||||||
#if defined(__WXMSW__) && defined(GUI)
|
#if defined(__WXMSW__) && defined(GUI)
|
||||||
MyMessageBox(buffer, "Bitcoin", wxOK | wxICON_EXCLAMATION);
|
MyMessageBox(buffer, "Bitcoin", wxOK | wxICON_EXCLAMATION);
|
||||||
#else
|
#else
|
||||||
|
@ -263,7 +265,7 @@ Value getinfo(const Array& params, bool fHelp)
|
||||||
obj.push_back(Pair("difficulty", (double)GetDifficulty()));
|
obj.push_back(Pair("difficulty", (double)GetDifficulty()));
|
||||||
obj.push_back(Pair("hashespersec", gethashespersec(params, false)));
|
obj.push_back(Pair("hashespersec", gethashespersec(params, false)));
|
||||||
obj.push_back(Pair("testnet", fTestNet));
|
obj.push_back(Pair("testnet", fTestNet));
|
||||||
obj.push_back(Pair("keypoololdest", (boost::int64_t)CWalletDB().GetOldestKeyPoolTime()));
|
obj.push_back(Pair("keypoololdest", (boost::int64_t)GetOldestKeyPoolTime()));
|
||||||
obj.push_back(Pair("paytxfee", (double)nTransactionFee / (double)COIN));
|
obj.push_back(Pair("paytxfee", (double)nTransactionFee / (double)COIN));
|
||||||
obj.push_back(Pair("errors", GetWarnings("statusbar")));
|
obj.push_back(Pair("errors", GetWarnings("statusbar")));
|
||||||
return obj;
|
return obj;
|
||||||
|
@ -285,7 +287,7 @@ Value getnewaddress(const Array& params, bool fHelp)
|
||||||
strAccount = params[0].get_str();
|
strAccount = params[0].get_str();
|
||||||
|
|
||||||
// Generate a new key that is added to wallet
|
// Generate a new key that is added to wallet
|
||||||
string strAddress = PubKeyToAddress(CWalletDB().GetKeyFromKeyPool());
|
string strAddress = PubKeyToAddress(GetKeyFromKeyPool());
|
||||||
|
|
||||||
SetAddressBookName(strAddress, strAccount);
|
SetAddressBookName(strAddress, strAccount);
|
||||||
return strAddress;
|
return strAddress;
|
||||||
|
@ -329,7 +331,7 @@ Value getaccountaddress(const Array& params, bool fHelp)
|
||||||
// Generate a new key
|
// Generate a new key
|
||||||
if (account.vchPubKey.empty())
|
if (account.vchPubKey.empty())
|
||||||
{
|
{
|
||||||
account.vchPubKey = CWalletDB().GetKeyFromKeyPool();
|
account.vchPubKey = GetKeyFromKeyPool();
|
||||||
string strAddress = PubKeyToAddress(account.vchPubKey);
|
string strAddress = PubKeyToAddress(account.vchPubKey);
|
||||||
SetAddressBookName(strAddress, strAccount);
|
SetAddressBookName(strAddress, strAccount);
|
||||||
walletdb.WriteAccount(strAccount, account);
|
walletdb.WriteAccount(strAccount, account);
|
||||||
|
@ -925,6 +927,112 @@ Value validateaddress(const Array& params, bool fHelp)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Value getwork(const Array& params, bool fHelp)
|
||||||
|
{
|
||||||
|
if (fHelp || params.size() > 1)
|
||||||
|
throw runtime_error(
|
||||||
|
"getwork [data]\n"
|
||||||
|
"If [data] is not specified, returns formatted hash data to work on:\n"
|
||||||
|
" \"midstate\" : precomputed hash state after hashing the first half of the data\n"
|
||||||
|
" \"data\" : block data\n"
|
||||||
|
" \"hash1\" : formatted hash buffer for second hash\n"
|
||||||
|
" \"target\" : little endian hash target\n"
|
||||||
|
"If [data] is specified, tries to solve the block and returns true if it was successful.");
|
||||||
|
|
||||||
|
if (vNodes.empty())
|
||||||
|
throw JSONRPCError(-9, "Bitcoin is not connected!");
|
||||||
|
|
||||||
|
if (IsInitialBlockDownload())
|
||||||
|
throw JSONRPCError(-10, "Bitcoin is downloading blocks...");
|
||||||
|
|
||||||
|
static map<uint256, pair<CBlock*, unsigned int> > mapNewBlock;
|
||||||
|
static vector<CBlock*> vNewBlock;
|
||||||
|
static CReserveKey reservekey;
|
||||||
|
|
||||||
|
if (params.size() == 0)
|
||||||
|
{
|
||||||
|
// Update block
|
||||||
|
static unsigned int nTransactionsUpdatedLast;
|
||||||
|
static CBlockIndex* pindexPrev;
|
||||||
|
static int64 nStart;
|
||||||
|
static CBlock* pblock;
|
||||||
|
if (pindexPrev != pindexBest ||
|
||||||
|
(nTransactionsUpdated != nTransactionsUpdatedLast && GetTime() - nStart > 60))
|
||||||
|
{
|
||||||
|
if (pindexPrev != pindexBest)
|
||||||
|
{
|
||||||
|
// Deallocate old blocks since they're obsolete now
|
||||||
|
mapNewBlock.clear();
|
||||||
|
foreach(CBlock* pblock, vNewBlock)
|
||||||
|
delete pblock;
|
||||||
|
vNewBlock.clear();
|
||||||
|
}
|
||||||
|
nTransactionsUpdatedLast = nTransactionsUpdated;
|
||||||
|
pindexPrev = pindexBest;
|
||||||
|
nStart = GetTime();
|
||||||
|
|
||||||
|
// Create new block
|
||||||
|
pblock = CreateNewBlock(reservekey);
|
||||||
|
if (!pblock)
|
||||||
|
throw JSONRPCError(-7, "Out of memory");
|
||||||
|
vNewBlock.push_back(pblock);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update nTime
|
||||||
|
pblock->nTime = max(pindexPrev->GetMedianTimePast()+1, GetAdjustedTime());
|
||||||
|
pblock->nNonce = 0;
|
||||||
|
|
||||||
|
// Update nExtraNonce
|
||||||
|
static unsigned int nExtraNonce = 0;
|
||||||
|
static int64 nPrevTime = 0;
|
||||||
|
IncrementExtraNonce(pblock, pindexPrev, nExtraNonce, nPrevTime);
|
||||||
|
|
||||||
|
// Save
|
||||||
|
mapNewBlock[pblock->hashMerkleRoot] = make_pair(pblock, nExtraNonce);
|
||||||
|
|
||||||
|
// Prebuild hash buffers
|
||||||
|
char pmidstate[32];
|
||||||
|
char pdata[128];
|
||||||
|
char phash1[64];
|
||||||
|
FormatHashBuffers(pblock, pmidstate, pdata, phash1);
|
||||||
|
|
||||||
|
uint256 hashTarget = CBigNum().SetCompact(pblock->nBits).getuint256();
|
||||||
|
|
||||||
|
Object result;
|
||||||
|
result.push_back(Pair("midstate", HexStr(BEGIN(pmidstate), END(pmidstate))));
|
||||||
|
result.push_back(Pair("data", HexStr(BEGIN(pdata), END(pdata))));
|
||||||
|
result.push_back(Pair("hash1", HexStr(BEGIN(phash1), END(phash1))));
|
||||||
|
result.push_back(Pair("target", HexStr(BEGIN(hashTarget), END(hashTarget))));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Parse parameters
|
||||||
|
vector<unsigned char> vchData = ParseHex(params[0].get_str());
|
||||||
|
if (vchData.size() != 128)
|
||||||
|
throw JSONRPCError(-8, "Invalid parameter");
|
||||||
|
CBlock* pdata = (CBlock*)&vchData[0];
|
||||||
|
|
||||||
|
// Byte reverse
|
||||||
|
for (int i = 0; i < 128/4; i++)
|
||||||
|
((unsigned int*)pdata)[i] = CryptoPP::ByteReverse(((unsigned int*)pdata)[i]);
|
||||||
|
|
||||||
|
// Get saved block
|
||||||
|
if (!mapNewBlock.count(pdata->hashMerkleRoot))
|
||||||
|
return false;
|
||||||
|
CBlock* pblock = mapNewBlock[pdata->hashMerkleRoot].first;
|
||||||
|
unsigned int nExtraNonce = mapNewBlock[pdata->hashMerkleRoot].second;
|
||||||
|
|
||||||
|
pblock->nTime = pdata->nTime;
|
||||||
|
pblock->nNonce = pdata->nNonce;
|
||||||
|
pblock->vtx[0].vin[0].scriptSig = CScript() << pblock->nBits << CBigNum(nExtraNonce);
|
||||||
|
pblock->hashMerkleRoot = pblock->BuildMerkleTree();
|
||||||
|
|
||||||
|
return CheckWork(pblock, reservekey);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -972,6 +1080,7 @@ pair<string, rpcfn_type> pCallTable[] =
|
||||||
make_pair("getbalance", &getbalance),
|
make_pair("getbalance", &getbalance),
|
||||||
make_pair("move", &movecmd),
|
make_pair("move", &movecmd),
|
||||||
make_pair("sendfrom", &sendfrom),
|
make_pair("sendfrom", &sendfrom),
|
||||||
|
make_pair("getwork", &getwork),
|
||||||
};
|
};
|
||||||
map<string, rpcfn_type> mapCallTable(pCallTable, pCallTable + sizeof(pCallTable)/sizeof(pCallTable[0]));
|
map<string, rpcfn_type> mapCallTable(pCallTable, pCallTable + sizeof(pCallTable)/sizeof(pCallTable[0]));
|
||||||
|
|
||||||
|
@ -996,6 +1105,7 @@ string pAllowInSafeMode[] =
|
||||||
"getaddressesbylabel", // deprecated
|
"getaddressesbylabel", // deprecated
|
||||||
"backupwallet",
|
"backupwallet",
|
||||||
"validateaddress",
|
"validateaddress",
|
||||||
|
"getwork",
|
||||||
};
|
};
|
||||||
set<string> setAllowInSafeMode(pAllowInSafeMode, pAllowInSafeMode + sizeof(pAllowInSafeMode)/sizeof(pAllowInSafeMode[0]));
|
set<string> setAllowInSafeMode(pAllowInSafeMode, pAllowInSafeMode + sizeof(pAllowInSafeMode)/sizeof(pAllowInSafeMode[0]));
|
||||||
|
|
||||||
|
@ -1418,7 +1528,8 @@ void ThreadRPCServer2(void* parg)
|
||||||
if (valMethod.type() != str_type)
|
if (valMethod.type() != str_type)
|
||||||
throw JSONRPCError(-32600, "Method must be a string");
|
throw JSONRPCError(-32600, "Method must be a string");
|
||||||
string strMethod = valMethod.get_str();
|
string strMethod = valMethod.get_str();
|
||||||
printf("ThreadRPCServer method=%s\n", strMethod.c_str());
|
if (strMethod != "getwork")
|
||||||
|
printf("ThreadRPCServer method=%s\n", strMethod.c_str());
|
||||||
|
|
||||||
// Parse params
|
// Parse params
|
||||||
Value valParams = find_value(request, "params");
|
Value valParams = find_value(request, "params");
|
||||||
|
|
|
@ -22,7 +22,7 @@ class CDataStream;
|
||||||
class CAutoFile;
|
class CAutoFile;
|
||||||
static const unsigned int MAX_SIZE = 0x02000000;
|
static const unsigned int MAX_SIZE = 0x02000000;
|
||||||
|
|
||||||
static const int VERSION = 31600;
|
static const int VERSION = 31601;
|
||||||
static const char* pszSubVer = "";
|
static const char* pszSubVer = "";
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -110,15 +110,15 @@ static const unsigned int pSHA256InitState[8] =
|
||||||
{0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19};
|
{0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19};
|
||||||
|
|
||||||
|
|
||||||
unsigned int ScanHash_4WaySSE2(char* pmidstate, char* pblock, char* phash1, char* phash, unsigned int& nHashesDone)
|
unsigned int ScanHash_4WaySSE2(char* pmidstate, char* pdata, char* phash1, char* phash, unsigned int& nHashesDone)
|
||||||
{
|
{
|
||||||
unsigned int& nNonce = *(unsigned int*)(pblock + 12);
|
unsigned int& nNonce = *(unsigned int*)(pdata + 12);
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
nNonce += NPAR;
|
nNonce += NPAR;
|
||||||
unsigned int thashbuf[9][NPAR];
|
unsigned int thashbuf[9][NPAR];
|
||||||
unsigned int (&thash)[9][NPAR] = *alignup<16>(&thashbuf);
|
unsigned int (&thash)[9][NPAR] = *alignup<16>(&thashbuf);
|
||||||
DoubleBlockSHA256(pblock, phash1, pmidstate, thash, pSHA256InitState);
|
DoubleBlockSHA256(pdata, phash1, pmidstate, thash, pSHA256InitState);
|
||||||
|
|
||||||
for (int j = 0; j < NPAR; j++)
|
for (int j = 0; j < NPAR; j++)
|
||||||
{
|
{
|
||||||
|
|
4
ui.cpp
4
ui.cpp
|
@ -1171,7 +1171,7 @@ void CMainFrame::OnButtonNew(wxCommandEvent& event)
|
||||||
string strName = dialog.GetValue();
|
string strName = dialog.GetValue();
|
||||||
|
|
||||||
// Generate new key
|
// Generate new key
|
||||||
string strAddress = PubKeyToAddress(CWalletDB().GetKeyFromKeyPool());
|
string strAddress = PubKeyToAddress(GetKeyFromKeyPool());
|
||||||
|
|
||||||
// Save
|
// Save
|
||||||
SetAddressBookName(strAddress, strName);
|
SetAddressBookName(strAddress, strName);
|
||||||
|
@ -2575,7 +2575,7 @@ void CAddressBookDialog::OnButtonNew(wxCommandEvent& event)
|
||||||
strName = dialog.GetValue();
|
strName = dialog.GetValue();
|
||||||
|
|
||||||
// Generate new key
|
// Generate new key
|
||||||
strAddress = PubKeyToAddress(CWalletDB().GetKeyFromKeyPool());
|
strAddress = PubKeyToAddress(GetKeyFromKeyPool());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add to list and select it
|
// Add to list and select it
|
||||||
|
|
1
util.cpp
1
util.cpp
|
@ -175,6 +175,7 @@ inline int OutputDebugStringF(const char* pszFormat, ...)
|
||||||
va_start(arg_ptr, pszFormat);
|
va_start(arg_ptr, pszFormat);
|
||||||
ret = vfprintf(fileout, pszFormat, arg_ptr);
|
ret = vfprintf(fileout, pszFormat, arg_ptr);
|
||||||
va_end(arg_ptr);
|
va_end(arg_ptr);
|
||||||
|
fflush(fileout);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue