Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F10615041
policyestimator_tests.cpp
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
9 KB
Subscribers
None
policyestimator_tests.cpp
View Options
// Copyright (c) 2011-2016 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include
"policy/policy.h"
#include
"policy/fees.h"
#include
"txmempool.h"
#include
"uint256.h"
#include
"util.h"
#include
"test/test_bitcoin.h"
#include
<boost/test/unit_test.hpp>
BOOST_FIXTURE_TEST_SUITE
(
policyestimator_tests
,
BasicTestingSetup
)
BOOST_AUTO_TEST_CASE
(
BlockPolicyEstimates
)
{
CTxMemPool
mpool
(
CFeeRate
(
1000
));
TestMemPoolEntryHelper
entry
;
CAmount
basefee
(
2000
);
CAmount
deltaFee
(
100
);
std
::
vector
<
CAmount
>
feeV
;
// Populate vectors of increasing fees
for
(
int
j
=
0
;
j
<
10
;
j
++
)
{
feeV
.
push_back
(
basefee
*
(
j
+
1
));
}
// Store the hashes of transactions that have been added to the mempool by
// their associate fee txHashes[j] is populated with transactions either of
// fee = basefee * (j+1)
std
::
vector
<
uint256
>
txHashes
[
10
];
// Create a transaction template
CScript
garbage
;
for
(
unsigned
int
i
=
0
;
i
<
128
;
i
++
)
garbage
.
push_back
(
'X'
);
CMutableTransaction
tx
;
tx
.
vin
.
resize
(
1
);
tx
.
vin
[
0
].
scriptSig
=
garbage
;
tx
.
vout
.
resize
(
1
);
tx
.
vout
[
0
].
nValue
=
0L
L
;
CFeeRate
baseRate
(
basefee
,
GetTransactionSize
(
tx
));
// Create a fake block
std
::
vector
<
CTransactionRef
>
block
;
int
blocknum
=
0
;
// Loop through 200 blocks
// At a decay .998 and 4 fee transactions per block
// This makes the tx count about 1.33 per bucket, above the 1 threshold
while
(
blocknum
<
200
)
{
// For each fee
for
(
int
j
=
0
;
j
<
10
;
j
++
)
{
// add 4 fee txs
for
(
int
k
=
0
;
k
<
4
;
k
++
)
{
// make transaction unique
tx
.
vin
[
0
].
prevout
.
n
=
10000
*
blocknum
+
100
*
j
+
k
;
uint256
hash
=
tx
.
GetId
();
mpool
.
addUnchecked
(
hash
,
entry
.
Fee
(
feeV
[
j
])
.
Time
(
GetTime
())
.
Priority
(
0
)
.
Height
(
blocknum
)
.
FromTx
(
tx
,
&
mpool
));
txHashes
[
j
].
push_back
(
hash
);
}
}
// Create blocks where higher fee txs are included more often
for
(
int
h
=
0
;
h
<=
blocknum
%
10
;
h
++
)
{
// 10/10 blocks add highest fee transactions
// 9/10 blocks add 2nd highest and so on until ...
// 1/10 blocks add lowest fee transactions
while
(
txHashes
[
9
-
h
].
size
())
{
CTransactionRef
ptx
=
mpool
.
get
(
txHashes
[
9
-
h
].
back
());
if
(
ptx
)
block
.
push_back
(
ptx
);
txHashes
[
9
-
h
].
pop_back
();
}
}
mpool
.
removeForBlock
(
block
,
++
blocknum
);
block
.
clear
();
if
(
blocknum
==
30
)
{
// At this point we should need to combine 5 buckets to get enough
// data points. So estimateFee(1,2,3) should fail and estimateFee(4)
// should return somewhere around 8*baserate. estimateFee(4) %'s
// are 100,100,100,100,90 = average 98%
BOOST_CHECK
(
mpool
.
estimateFee
(
1
)
==
CFeeRate
(
0
));
BOOST_CHECK
(
mpool
.
estimateFee
(
2
)
==
CFeeRate
(
0
));
BOOST_CHECK
(
mpool
.
estimateFee
(
3
)
==
CFeeRate
(
0
));
BOOST_CHECK
(
mpool
.
estimateFee
(
4
).
GetFeePerK
()
<
8
*
baseRate
.
GetFeePerK
()
+
deltaFee
);
BOOST_CHECK
(
mpool
.
estimateFee
(
4
).
GetFeePerK
()
>
8
*
baseRate
.
GetFeePerK
()
-
deltaFee
);
int
answerFound
;
BOOST_CHECK
(
mpool
.
estimateSmartFee
(
1
,
&
answerFound
)
==
mpool
.
estimateFee
(
4
)
&&
answerFound
==
4
);
BOOST_CHECK
(
mpool
.
estimateSmartFee
(
3
,
&
answerFound
)
==
mpool
.
estimateFee
(
4
)
&&
answerFound
==
4
);
BOOST_CHECK
(
mpool
.
estimateSmartFee
(
4
,
&
answerFound
)
==
mpool
.
estimateFee
(
4
)
&&
answerFound
==
4
);
BOOST_CHECK
(
mpool
.
estimateSmartFee
(
8
,
&
answerFound
)
==
mpool
.
estimateFee
(
8
)
&&
answerFound
==
8
);
}
}
std
::
vector
<
CAmount
>
origFeeEst
;
// Highest feerate is 10*baseRate and gets in all blocks, second highest
// feerate is 9*baseRate and gets in 9/10 blocks = 90%, third highest
// feerate is 8*base rate, and gets in 8/10 blocks = 80%, so estimateFee(1)
// would return 10*baseRate but is hardcoded to return failure. Second
// highest feerate has 100% chance of being included by 2 blocks, so
// estimateFee(2) should return 9*baseRate etc...
for
(
int
i
=
1
;
i
<
10
;
i
++
)
{
origFeeEst
.
push_back
(
mpool
.
estimateFee
(
i
).
GetFeePerK
());
// Fee estimates should be monotonically decreasing
if
(
i
>
2
)
{
BOOST_CHECK
(
origFeeEst
[
i
-
1
]
<=
origFeeEst
[
i
-
2
]);
}
int
mult
=
11
-
i
;
if
(
i
>
1
)
{
BOOST_CHECK
(
origFeeEst
[
i
-
1
]
<
mult
*
baseRate
.
GetFeePerK
()
+
deltaFee
);
BOOST_CHECK
(
origFeeEst
[
i
-
1
]
>
mult
*
baseRate
.
GetFeePerK
()
-
deltaFee
);
}
else
{
BOOST_CHECK
(
origFeeEst
[
i
-
1
]
==
CFeeRate
(
0
).
GetFeePerK
());
}
}
// Mine 50 more blocks with no transactions happening, estimates shouldn't
// change. We haven't decayed the moving average enough so we still have
// enough data points in every bucket
while
(
blocknum
<
250
)
mpool
.
removeForBlock
(
block
,
++
blocknum
);
BOOST_CHECK
(
mpool
.
estimateFee
(
1
)
==
CFeeRate
(
0
));
for
(
int
i
=
2
;
i
<
10
;
i
++
)
{
BOOST_CHECK
(
mpool
.
estimateFee
(
i
).
GetFeePerK
()
<
origFeeEst
[
i
-
1
]
+
deltaFee
);
BOOST_CHECK
(
mpool
.
estimateFee
(
i
).
GetFeePerK
()
>
origFeeEst
[
i
-
1
]
-
deltaFee
);
}
// Mine 15 more blocks with lots of transactions happening and not getting
// mined. Estimates should go up
while
(
blocknum
<
265
)
{
// For each fee multiple
for
(
int
j
=
0
;
j
<
10
;
j
++
)
{
// add 4 fee txs
for
(
int
k
=
0
;
k
<
4
;
k
++
)
{
tx
.
vin
[
0
].
prevout
.
n
=
10000
*
blocknum
+
100
*
j
+
k
;
uint256
txid
=
tx
.
GetId
();
mpool
.
addUnchecked
(
txid
,
entry
.
Fee
(
feeV
[
j
])
.
Time
(
GetTime
())
.
Priority
(
0
)
.
Height
(
blocknum
)
.
FromTx
(
tx
,
&
mpool
));
txHashes
[
j
].
push_back
(
txid
);
}
}
mpool
.
removeForBlock
(
block
,
++
blocknum
);
}
int
answerFound
;
for
(
int
i
=
1
;
i
<
10
;
i
++
)
{
BOOST_CHECK
(
mpool
.
estimateFee
(
i
)
==
CFeeRate
(
0
)
||
mpool
.
estimateFee
(
i
).
GetFeePerK
()
>
origFeeEst
[
i
-
1
]
-
deltaFee
);
BOOST_CHECK
(
mpool
.
estimateSmartFee
(
i
,
&
answerFound
).
GetFeePerK
()
>
origFeeEst
[
answerFound
-
1
]
-
deltaFee
);
}
// Mine all those transactions
// Estimates should still not be below original
for
(
int
j
=
0
;
j
<
10
;
j
++
)
{
while
(
txHashes
[
j
].
size
())
{
CTransactionRef
ptx
=
mpool
.
get
(
txHashes
[
j
].
back
());
if
(
ptx
)
block
.
push_back
(
ptx
);
txHashes
[
j
].
pop_back
();
}
}
mpool
.
removeForBlock
(
block
,
265
);
block
.
clear
();
BOOST_CHECK
(
mpool
.
estimateFee
(
1
)
==
CFeeRate
(
0
));
for
(
int
i
=
2
;
i
<
10
;
i
++
)
{
BOOST_CHECK
(
mpool
.
estimateFee
(
i
).
GetFeePerK
()
>
origFeeEst
[
i
-
1
]
-
deltaFee
);
}
// Mine 200 more blocks where everything is mined every block
// Estimates should be below original estimates
while
(
blocknum
<
465
)
{
// For each fee multiple
for
(
int
j
=
0
;
j
<
10
;
j
++
)
{
// add 4 fee txs
for
(
int
k
=
0
;
k
<
4
;
k
++
)
{
tx
.
vin
[
0
].
prevout
.
n
=
10000
*
blocknum
+
100
*
j
+
k
;
uint256
txid
=
tx
.
GetId
();
mpool
.
addUnchecked
(
txid
,
entry
.
Fee
(
feeV
[
j
])
.
Time
(
GetTime
())
.
Priority
(
0
)
.
Height
(
blocknum
)
.
FromTx
(
tx
,
&
mpool
));
CTransactionRef
ptx
=
mpool
.
get
(
txid
);
if
(
ptx
)
block
.
push_back
(
ptx
);
}
}
mpool
.
removeForBlock
(
block
,
++
blocknum
);
block
.
clear
();
}
BOOST_CHECK
(
mpool
.
estimateFee
(
1
)
==
CFeeRate
(
0
));
for
(
int
i
=
2
;
i
<
10
;
i
++
)
{
BOOST_CHECK
(
mpool
.
estimateFee
(
i
).
GetFeePerK
()
<
origFeeEst
[
i
-
1
]
-
deltaFee
);
}
// Test that if the mempool is limited, estimateSmartFee won't return a
// value below the mempool min fee and that estimateSmartPriority returns
// essentially an infinite value
mpool
.
addUnchecked
(
tx
.
GetId
(),
entry
.
Fee
(
feeV
[
5
]).
Time
(
GetTime
()).
Priority
(
0
).
Height
(
blocknum
).
FromTx
(
tx
,
&
mpool
));
// evict that transaction which should set a mempool min fee of
// minRelayTxFee + feeV[5]
mpool
.
TrimToSize
(
1
);
BOOST_CHECK
(
mpool
.
GetMinFee
(
1
).
GetFeePerK
()
>
feeV
[
5
]);
for
(
int
i
=
1
;
i
<
10
;
i
++
)
{
BOOST_CHECK
(
mpool
.
estimateSmartFee
(
i
).
GetFeePerK
()
>=
mpool
.
estimateFee
(
i
).
GetFeePerK
());
BOOST_CHECK
(
mpool
.
estimateSmartFee
(
i
).
GetFeePerK
()
>=
mpool
.
GetMinFee
(
1
).
GetFeePerK
());
BOOST_CHECK
(
mpool
.
estimateSmartPriority
(
i
)
==
INF_PRIORITY
);
}
}
BOOST_AUTO_TEST_SUITE_END
()
File Metadata
Details
Attached
Mime Type
text/x-c
Expires
Sat, Nov 23, 09:55 (1 d, 4 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
4536513
Default Alt Text
policyestimator_tests.cpp (9 KB)
Attached To
rSTAGING Bitcoin ABC staging
Event Timeline
Log In to Comment