aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGavin Andresen <gavinandresen@gmail.com>2010-11-21 15:48:48 -0500
committerGavin Andresen <gavinandresen@gmail.com>2010-11-21 15:48:48 -0500
commit2d8b65e8378492842613dcea3cad9be7decf3839 (patch)
treeb8f6c430ff42fc4989c6adce070324da45c20ff0
parent11c570cfb4a314d63f461ca107ed1db8638f1509 (diff)
parent51d9b435cd1fc6efe5fc418e8adb48ef33c9e836 (diff)
Merge remote branch 'refs/remotes/svn/trunk' into svn
-rw-r--r--main.cpp123
-rw-r--r--main.h21
-rw-r--r--net.cpp22
-rw-r--r--serialize.h2
4 files changed, 111 insertions, 57 deletions
diff --git a/main.cpp b/main.cpp
index 190cd4b296..1f5261d4e9 100644
--- a/main.cpp
+++ b/main.cpp
@@ -598,6 +598,8 @@ bool CTransaction::AcceptToMemoryPool(CTxDB& txdb, bool fCheckInputs, bool* pfMi
if (i != 0)
return false;
ptxOld = mapNextTx[outpoint].ptx;
+ if (ptxOld->IsFinal())
+ return false;
if (!IsNewerThan(*ptxOld))
return false;
for (int i = 0; i < vin.size(); i++)
@@ -3031,6 +3033,28 @@ extern unsigned int ScanHash_4WaySSE2(char* pmidstate, char* pblock, char* phash
+class COrphan
+{
+public:
+ CTransaction* ptx;
+ set<uint256> setDependsOn;
+ double dPriority;
+
+ COrphan(CTransaction* ptxIn)
+ {
+ ptx = ptxIn;
+ dPriority = 0;
+ }
+
+ void print() const
+ {
+ printf("COrphan(hash=%s, dPriority=%.1f)\n", ptx->GetHash().ToString().substr(0,10).c_str(), dPriority);
+ foreach(uint256 hash, setDependsOn)
+ printf(" setDependsOn %s\n", hash.ToString().substr(0,10).c_str());
+ }
+};
+
+
void BitcoinMiner()
{
@@ -3098,6 +3122,8 @@ void BitcoinMiner()
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)
{
@@ -3105,6 +3131,7 @@ void BitcoinMiner()
if (tx.IsCoinBase() || !tx.IsFinal())
continue;
+ COrphan* porphan = NULL;
double dPriority = 0;
foreach(const CTxIn& txin, tx.vin)
{
@@ -3112,7 +3139,18 @@ void BitcoinMiner()
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
@@ -3138,55 +3176,68 @@ void BitcoinMiner()
// Priority is sum(valuein * age) / txsize
dPriority /= ::GetSerializeSize(tx, SER_NETWORK);
- mapPriority.insert(make_pair(-dPriority, &(*mi).second));
+ 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\n", dPriority, tx.GetHash().ToString().substr(0,10).c_str(), tx.ToString().c_str());
+ {
+ 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;
- bool fFoundSomething = true;
- while (fFoundSomething)
+ while (!mapPriority.empty())
{
- fFoundSomething = false;
- for (multimap<double, CTransaction*>::iterator mi = mapPriority.begin(); mi != mapPriority.end();)
- {
- CTransaction& tx = *(*mi).second;
- unsigned int nTxSize = ::GetSerializeSize(tx, SER_NETWORK);
- if (nBlockSize + nTxSize >= MAX_BLOCK_SIZE_GEN)
- {
- mapPriority.erase(mi++);
- continue;
- }
- int nTxSigOps = tx.GetSigOpCount();
- if (nBlockSigOps + nTxSigOps >= MAX_BLOCK_SIGOPS)
- {
- mapPriority.erase(mi++);
- continue;
- }
+ // 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 based on block size
- int64 nMinFee = tx.GetMinFee(nBlockSize);
+ // Transaction fee required depends on block size
+ bool fAllowFree = (nBlockSize + nTxSize < 4000 || dPriority > COIN * 144 / 250);
+ int64 nMinFee = tx.GetMinFee(nBlockSize, fAllowFree);
- // Connecting can fail due to dependency on other memory pool transactions
- // that aren't in the block yet, so keep trying in later passes
- map<uint256, CTxIndex> mapTestPoolTmp(mapTestPool);
- if (!tx.ConnectInputs(txdb, mapTestPoolTmp, CDiskTxPos(1,1,1), pindexPrev, nFees, false, true, nMinFee))
+ // 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])
{
- mi++;
- continue;
+ if (!porphan->setDependsOn.empty())
+ {
+ porphan->setDependsOn.erase(hash);
+ if (porphan->setDependsOn.empty())
+ mapPriority.insert(make_pair(-porphan->dPriority, porphan->ptx));
+ }
}
- swap(mapTestPool, mapTestPoolTmp);
-
- // Added
- pblock->vtx.push_back(tx);
- nBlockSize += nTxSize;
- nBlockSigOps += nTxSigOps;
- fFoundSomething = true;
- mapPriority.erase(mi++);
}
}
}
diff --git a/main.h b/main.h
index d5734103c0..cc150e62b6 100644
--- a/main.h
+++ b/main.h
@@ -528,21 +528,24 @@ public:
return nValueOut;
}
- int64 GetMinFee(unsigned int nBlockSize=1) const
+ int64 GetMinFee(unsigned int nBlockSize=1, bool fAllowFree=true) const
{
// Base fee is 1 cent per kilobyte
unsigned int nBytes = ::GetSerializeSize(*this, SER_NETWORK);
unsigned int nNewBlockSize = nBlockSize + nBytes;
int64 nMinFee = (1 + (int64)nBytes / 1000) * CENT;
- // Transactions under 25K are free as long as block size is under 40K
- // (about 11,000bc if made of 50bc inputs)
- if (nBytes < 25000 && nNewBlockSize < 40000)
- nMinFee = 0;
-
- // Transactions under 3K are free as long as block size is under 50K
- if (nBytes < 3000 && nNewBlockSize < 50000)
- nMinFee = 0;
+ if (fAllowFree)
+ {
+ // Transactions under 25K are free as long as block size is under 40K
+ // (about 11,000bc if made of 50bc inputs)
+ if (nBytes < 25000 && nNewBlockSize < 40000)
+ nMinFee = 0;
+
+ // Transactions under 3K are free as long as block size is under 50K
+ if (nBytes < 3000 && nNewBlockSize < 50000)
+ nMinFee = 0;
+ }
// To limit dust spam, require a 0.01 fee if any output is less than 0.01
if (nMinFee < CENT)
diff --git a/net.cpp b/net.cpp
index 7cc21be398..3c80644a49 100644
--- a/net.cpp
+++ b/net.cpp
@@ -178,41 +178,41 @@ bool GetMyExternalIP(unsigned int& ipRet)
{
if (nHost == 1)
{
- addrConnect = CAddress("72.233.89.199:80"); // www.whatismyip.com
+ addrConnect = CAddress("91.198.22.70:80"); // checkip.dyndns.org
if (nLookup == 1)
{
- struct hostent* phostent = gethostbyname("www.whatismyip.com");
+ struct hostent* phostent = gethostbyname("checkip.dyndns.org");
if (phostent && phostent->h_addr_list && phostent->h_addr_list[0])
addrConnect = CAddress(*(u_long*)phostent->h_addr_list[0], htons(80));
}
- pszGet = "GET /automation/n09230945.asp HTTP/1.1\r\n"
- "Host: www.whatismyip.com\r\n"
- "User-Agent: Bitcoin/1.0 (see www.bitcoin.org)\r\n"
+ pszGet = "GET / HTTP/1.1\r\n"
+ "Host: checkip.dyndns.org\r\n"
+ "User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)\r\n"
"Connection: close\r\n"
"\r\n";
- pszKeyword = NULL; // Returns just IP address
+ pszKeyword = "Address:";
}
else if (nHost == 2)
{
- addrConnect = CAddress("91.198.22.70:80"); // checkip.dyndns.org
+ addrConnect = CAddress("74.208.43.192:80"); // www.showmyip.com
if (nLookup == 1)
{
- struct hostent* phostent = gethostbyname("checkip.dyndns.org");
+ struct hostent* phostent = gethostbyname("www.showmyip.com");
if (phostent && phostent->h_addr_list && phostent->h_addr_list[0])
addrConnect = CAddress(*(u_long*)phostent->h_addr_list[0], htons(80));
}
- pszGet = "GET / HTTP/1.1\r\n"
- "Host: checkip.dyndns.org\r\n"
+ pszGet = "GET /simple/ HTTP/1.1\r\n"
+ "Host: www.showmyip.com\r\n"
"User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)\r\n"
"Connection: close\r\n"
"\r\n";
- pszKeyword = "Address:";
+ pszKeyword = NULL; // Returns just IP address
}
if (GetMyExternalIP2(addrConnect, pszGet, pszKeyword, ipRet))
diff --git a/serialize.h b/serialize.h
index 43122078d5..e0b83aca43 100644
--- a/serialize.h
+++ b/serialize.h
@@ -22,7 +22,7 @@ class CDataStream;
class CAutoFile;
static const unsigned int MAX_SIZE = 0x02000000;
-static const int VERSION = 31501;
+static const int VERSION = 31504;
static const char* pszSubVer = "";