[ create a new paste ] login | about

Link: http://codepad.org/5il1jH1K    [ raw code | fork ]

Plain Text, pasted on Jan 11:
diff --git a/qa/rpc-tests/getrawmempool_priority.py b/qa/rpc-tests/getrawmempool_priority.py
new file mode 100755
index 0000000..1adf61d
--- /dev/null
+++ b/qa/rpc-tests/getrawmempool_priority.py
@@ -0,0 +1,115 @@
+#!/usr/bin/env python2
+# Copyright (c) 2016 The Bitcoin Core developers
+# Distributed under the MIT/X11 software license, see the accompanying
+# file COPYING or http://www.opensource.org/licenses/mit-license.php.
+#
+
+from test_framework.blocktools import create_block, create_coinbase
+from test_framework.test_framework import BitcoinTestFramework
+from test_framework.util import *
+
+from binascii import a2b_hex, b2a_hex
+
+def find_unspent(node, txid, amount):
+    for utxo in node.listunspent(0):
+        if utxo['txid'] != txid: continue
+        if float(utxo['amount']) != amount: continue
+        return {'txid': utxo['txid'], 'vout': utxo['vout']}
+
+def solve_template_hex(tmpl, txlist):
+    block = create_block(tmpl=tmpl, txlist=txlist)
+    block.solve()
+    b = block.serialize()
+    x = b2a_hex(b).decode('ascii')
+    return x
+
+def get_modified_size(node, txdata):
+    decoded = node.decoderawtransaction(txdata)
+    size = len(txdata) // 2
+    for inp in decoded['vin']:
+        offset = 41 + min(len(inp['scriptSig']['hex']) // 2, 110)
+        if offset <= size:
+            size -= offset
+    return size
+
+def assert_approximate(a, b):
+    assert_equal(int(a), int(b))
+
+class PriorityTest(BitcoinTestFramework):
+
+    def __init__(self):
+        self.num_nodes = 2
+
+    def setup_nodes(self):
+        nodes = []
+        nodes.append(start_node(0, self.options.tmpdir, ['-blockmaxsize=0']))
+        nodes.append(start_node(1, self.options.tmpdir, ['-blockminsize=1000000', '-blockmaxsize=1000000']))
+        return nodes
+
+    def setup_network(self, split=False):
+        self.nodes = self.setup_nodes()
+        connect_nodes_bi(self.nodes,0,1)
+        self.is_network_split = False
+        self.sync_all()
+
+    def run_test(self):
+        node = self.nodes[0]
+        miner = self.nodes[1]
+        node.generate(50)
+        miner.generate(101)
+        self.sync_all()
+
+        fee = 0.01
+        amt = 11
+
+        txid_a = node.sendtoaddress(node.getnewaddress(), amt)
+        txdata_b = node.createrawtransaction([find_unspent(node, txid_a, amt)], {node.getnewaddress(): amt - fee})
+        txdata_b = node.signrawtransaction(txdata_b)['hex']
+        txmodsize_b = get_modified_size(node, txdata_b)
+        txid_b = node.sendrawtransaction(txdata_b)
+
+        txid_b_mempoolentry = node.getrawmempool(True)[txid_b]
+        assert_approximate(txid_b_mempoolentry['startingpriority'], txid_b_mempoolentry['currentpriority'])
+        assert_approximate(txid_b_mempoolentry['currentpriority'], 0)
+
+        # Mine only the sendtoaddress transaction
+        tmpl = node.getblocktemplate()
+        rawblock = solve_template_hex(tmpl, [create_coinbase(tmpl['height']), a2b_hex(node.getrawtransaction(txid_a))])
+        assert_equal(node.submitblock(rawblock), None)
+
+        txid_b_mempoolentry = node.getrawmempool(True)[txid_b]
+        assert_approximate(txid_b_mempoolentry['startingpriority'], 0)
+        assert_approximate(txid_b_mempoolentry['currentpriority'], amt * 1e8 / txmodsize_b)
+
+        node.generate(2)
+
+        txid_b_mempoolentry = node.getrawmempool(True)[txid_b]
+        assert_approximate(txid_b_mempoolentry['startingpriority'], 0)
+        assert_approximate(txid_b_mempoolentry['currentpriority'], amt * 1e8 * 3 / txmodsize_b)
+
+        self.sync_all()
+        miner.generate(4)
+        self.sync_all()
+
+        txdata_c = node.createrawtransaction([find_unspent(node, txid_b, amt - fee)], {node.getnewaddress(): amt - (fee * 2)})
+        txdata_c = node.signrawtransaction(txdata_c)['hex']
+        txmodsize_c = get_modified_size(node, txdata_c)
+        txid_c = node.sendrawtransaction(txdata_c)
+        txid_c_mempoolentry = node.getrawmempool(True)[txid_c]
+        assert_approximate(txid_c_mempoolentry['startingpriority'], txid_c_mempoolentry['currentpriority'])
+        assert_approximate(txid_c_mempoolentry['currentpriority'], (amt - fee) * 1e8 * 4 / txmodsize_c)
+
+        node.generate(1)
+
+        txid_c_mempoolentry = node.getrawmempool(True)[txid_c]
+        assert_approximate(txid_c_mempoolentry['startingpriority'], (amt - fee) * 1e8 * 4 / txmodsize_c)
+        assert_approximate(txid_c_mempoolentry['currentpriority'], (amt - fee) * 1e8 * 5 / txmodsize_c)
+
+        node.generate(2)
+
+        txid_c_mempoolentry = node.getrawmempool(True)[txid_c]
+        assert_approximate(txid_c_mempoolentry['startingpriority'], (amt - fee) * 1e8 * 4 / txmodsize_c)
+        assert_approximate(txid_c_mempoolentry['currentpriority'], (amt - fee) * 1e8 * 7 / txmodsize_c)
+
+if __name__ == '__main__':
+    PriorityTest().main()
diff --git a/qa/rpc-tests/test_framework/blocktools.py b/qa/rpc-tests/test_framework/blocktools.py
index 59aa8c1..b3aa8af 100644
--- a/qa/rpc-tests/test_framework/blocktools.py
+++ b/qa/rpc-tests/test_framework/blocktools.py
@@ -4,20 +4,41 @@
 # file COPYING or http://www.opensource.org/licenses/mit-license.php.
 #
 
+from binascii import a2b_hex, b2a_hex
+import cStringIO
 from mininode import *
 from script import CScript, CScriptOp, OP_TRUE, OP_CHECKSIG
+import struct
 
 # Create a block (with regtest difficulty)
-def create_block(hashprev, coinbase, nTime=None):
+def create_block(hashprev=None, coinbase=None, nTime=None, tmpl=None, txlist=None):
     block = CBlock()
-    if nTime is None:
+    if tmpl:
+        block.nVersion = tmpl.get('version', block.nVersion)
+    if not nTime is None:
+        block.nTime = nTime
+    elif tmpl and not tmpl.get('curtime') is None:
+        block.nTime = tmpl['curtime']
+    else:
         import time
         block.nTime = int(time.time()+600)
+    if not hashprev is None:
+        block.hashPrevBlock = hashprev
     else:
-        block.nTime = nTime
-    block.hashPrevBlock = hashprev
-    block.nBits = 0x207fffff # Will break after a difficulty adjustment...
-    block.vtx.append(coinbase)
+        block.hashPrevBlock = int ("0x" + tmpl['previousblockhash'] + "L", 0)
+    if tmpl and not tmpl.get('bits') is None:
+        block.nBits = struct.unpack('>I', a2b_hex(tmpl['bits']))[0]
+    else:
+        block.nBits = 0x207fffff # Will break after a difficulty adjustment...
+    if not coinbase is None:
+        block.vtx.append(coinbase)
+    if txlist:
+        for tx in txlist:
+            if not hasattr(tx, 'calc_sha256'):
+                txo = CTransaction()
+                txo.deserialize(cStringIO.StringIO(tx))
+                tx = txo
+            block.vtx.append(tx)
     block.hashMerkleRoot = block.calc_merkle_root()
     block.calc_sha256()
     return block
diff --git a/src/main.cpp b/src/main.cpp
index 37dfaaa..f02a53e 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -948,7 +948,8 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState &state, const C
         pool.ApplyDeltas(hash, nPriorityDummy, nModifiedFees);
 
         CAmount inChainInputValue;
-        double dPriority = view.GetPriority(tx, chainActive.Height(), inChainInputValue);
+        // Priority is based on height+1 since it is used for mining the *next* block
+        double dPriority = view.GetPriority(tx, chainActive.Height() + 1, inChainInputValue);
 
         // Keep track of transactions that spend a coinbase, which we re-scan
         // during reorgs to ensure COINBASE_MATURITY is still met.
diff --git a/src/rpcblockchain.cpp b/src/rpcblockchain.cpp
index 3cd2b76..8d9c66b 100644
--- a/src/rpcblockchain.cpp
+++ b/src/rpcblockchain.cpp
@@ -194,7 +194,7 @@ UniValue mempoolToJSON(bool fVerbose = false)
             info.push_back(Pair("time", e.GetTime()));
             info.push_back(Pair("height", (int)e.GetHeight()));
             info.push_back(Pair("startingpriority", e.GetStartingPriority()));
-            info.push_back(Pair("currentpriority", e.GetPriority(chainActive.Height())));
+            info.push_back(Pair("currentpriority", e.GetPriority(chainActive.Height() + 1)));
             info.push_back(Pair("descendantcount", e.GetCountWithDescendants()));
             info.push_back(Pair("descendantsize", e.GetSizeWithDescendants()));
             info.push_back(Pair("descendantfees", e.GetModFeesWithDescendants()));
diff --git a/src/txmempool.cpp b/src/txmempool.cpp
index ed44647..aed5fb4 100644
--- a/src/txmempool.cpp
+++ b/src/txmempool.cpp
@@ -39,7 +39,7 @@ CTxMemPoolEntry::CTxMemPoolEntry(const CTransaction& _tx, const CAmount& _nFee,
 
     feeDelta = 0;
 
-    cachedHeight = entryHeight;
+    cachedHeight = entryHeight + 1;
     cachedPriority = entryPriority;
 }
 
@@ -328,8 +328,9 @@ void CTxMemPoolEntry::UpdateState(int64_t modifySize, CAmount modifyFee, int64_t
 
 void CTxMemPoolEntry::UpdateCachedPriority(unsigned int currentHeight, CAmount valueInCurrentBlock)
 {
+    ++currentHeight;
     int heightDiff = currentHeight - cachedHeight;
-    double deltaPriority = ((double)heightDiff*inChainInputValue)/nModSize;
+    double deltaPriority = (((double)heightDiff*inChainInputValue) + valueInCurrentBlock)/nModSize;
     cachedPriority += deltaPriority;
     cachedHeight = currentHeight;
     inChainInputValue += valueInCurrentBlock;
@@ -648,11 +649,12 @@ void CTxMemPool::check(const CCoinsViewCache *pcoins, unsigned int nBlockHeight)
         unsigned int i = 0;
         checkTotal += it->GetTxSize();
         CAmount dummyValue;
-        double freshPriority = view.GetPriority(it->GetTx(), nBlockHeight, dummyValue);
-        double cachePriority = it->GetPriority(nBlockHeight);
+        double freshPriority = view.GetPriority(it->GetTx(), nBlockHeight + 1, dummyValue);
+        double cachePriority = it->GetPriority(nBlockHeight + 1);
         double priDiff = cachePriority > freshPriority ? cachePriority - freshPriority : freshPriority - cachePriority;
         // Verify that the difference between the on the fly calculation and a fresh calculation
-        // is small enough to be a result of double imprecision.
+        // is small enough to be a result of double imprecision. nBlockHeight + 1 is the
+        // earliest reliable value to use.
         assert(priDiff < .0001 * freshPriority + 1);
         innerUsage += it->DynamicMemoryUsage();
         const CTransaction& tx = it->GetTx();


Create a new paste based on this one


Comments: