Skip to content

Commit 56106a3

Browse files
committed
Expose RPC calls for estimatesmart functions
Also add testing for estimatesmartfee in smartfees.py
1 parent e93a236 commit 56106a3

File tree

5 files changed

+108
-22
lines changed

5 files changed

+108
-22
lines changed

qa/rpc-tests/smartfees.py

Lines changed: 30 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -120,15 +120,26 @@ def check_estimates(node, fees_seen, max_invalid, print_estimates = True):
120120
last_e = e
121121
valid_estimate = False
122122
invalid_estimates = 0
123-
for e in all_estimates:
123+
for i,e in enumerate(all_estimates): # estimate is for i+1
124124
if e >= 0:
125125
valid_estimate = True
126+
# estimatesmartfee should return the same result
127+
assert_equal(node.estimatesmartfee(i+1)["feerate"], e)
128+
126129
else:
127130
invalid_estimates += 1
128-
# Once we're at a high enough confirmation count that we can give an estimate
129-
# We should have estimates for all higher confirmation counts
130-
if valid_estimate and e < 0:
131-
raise AssertionError("Invalid estimate appears at higher confirm count than valid estimate")
131+
132+
# estimatesmartfee should still be valid
133+
approx_estimate = node.estimatesmartfee(i+1)["feerate"]
134+
answer_found = node.estimatesmartfee(i+1)["blocks"]
135+
assert(approx_estimate > 0)
136+
assert(answer_found > i+1)
137+
138+
# Once we're at a high enough confirmation count that we can give an estimate
139+
# We should have estimates for all higher confirmation counts
140+
if valid_estimate:
141+
raise AssertionError("Invalid estimate appears at higher confirm count than valid estimate")
142+
132143
# Check on the expected number of different confirmation counts
133144
# that we might not have valid estimates for
134145
if invalid_estimates > max_invalid:
@@ -184,13 +195,13 @@ def setup_network(self):
184195
# NOTE: the CreateNewBlock code starts counting block size at 1,000 bytes,
185196
# (17k is room enough for 110 or so transactions)
186197
self.nodes.append(start_node(1, self.options.tmpdir,
187-
["-blockprioritysize=1500", "-blockmaxsize=18000",
198+
["-blockprioritysize=1500", "-blockmaxsize=17000",
188199
"-maxorphantx=1000", "-relaypriority=0", "-debug=estimatefee"]))
189200
connect_nodes(self.nodes[1], 0)
190201

191202
# Node2 is a stingy miner, that
192-
# produces too small blocks (room for only 70 or so transactions)
193-
node2args = ["-blockprioritysize=0", "-blockmaxsize=12000", "-maxorphantx=1000", "-relaypriority=0"]
203+
# produces too small blocks (room for only 55 or so transactions)
204+
node2args = ["-blockprioritysize=0", "-blockmaxsize=8000", "-maxorphantx=1000", "-relaypriority=0"]
194205

195206
self.nodes.append(start_node(2, self.options.tmpdir, node2args))
196207
connect_nodes(self.nodes[0], 2)
@@ -229,22 +240,19 @@ def run_test(self):
229240
self.fees_per_kb = []
230241
self.memutxo = []
231242
self.confutxo = self.txouts # Start with the set of confirmed txouts after splitting
232-
print("Checking estimates for 1/2/3/6/15/25 blocks")
233-
print("Creating transactions and mining them with a huge block size")
234-
# Create transactions and mine 20 big blocks with node 0 such that the mempool is always emptied
235-
self.transact_and_mine(30, self.nodes[0])
236-
check_estimates(self.nodes[1], self.fees_per_kb, 1)
243+
print("Will output estimates for 1/2/3/6/15/25 blocks")
237244

238-
print("Creating transactions and mining them with a block size that can't keep up")
239-
# Create transactions and mine 30 small blocks with node 2, but create txs faster than we can mine
240-
self.transact_and_mine(20, self.nodes[2])
241-
check_estimates(self.nodes[1], self.fees_per_kb, 3)
245+
for i in xrange(2):
246+
print("Creating transactions and mining them with a block size that can't keep up")
247+
# Create transactions and mine 10 small blocks with node 2, but create txs faster than we can mine
248+
self.transact_and_mine(10, self.nodes[2])
249+
check_estimates(self.nodes[1], self.fees_per_kb, 14)
242250

243-
print("Creating transactions and mining them at a block size that is just big enough")
244-
# Generate transactions while mining 40 more blocks, this time with node1
245-
# which mines blocks with capacity just above the rate that transactions are being created
246-
self.transact_and_mine(40, self.nodes[1])
247-
check_estimates(self.nodes[1], self.fees_per_kb, 2)
251+
print("Creating transactions and mining them at a block size that is just big enough")
252+
# Generate transactions while mining 10 more blocks, this time with node1
253+
# which mines blocks with capacity just above the rate that transactions are being created
254+
self.transact_and_mine(10, self.nodes[1])
255+
check_estimates(self.nodes[1], self.fees_per_kb, 2)
248256

249257
# Finish by mining a normal-sized block:
250258
while len(self.nodes[1].getrawmempool()) > 0:

src/rpcclient.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,8 @@ static const CRPCConvertParam vRPCConvertParams[] =
9696
{ "getrawmempool", 0 },
9797
{ "estimatefee", 0 },
9898
{ "estimatepriority", 0 },
99+
{ "estimatesmartfee", 0 },
100+
{ "estimatesmartpriority", 0 },
99101
{ "prioritisetransaction", 1 },
100102
{ "prioritisetransaction", 2 },
101103
{ "setban", 2 },

src/rpcmining.cpp

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -726,3 +726,75 @@ UniValue estimatepriority(const UniValue& params, bool fHelp)
726726

727727
return mempool.estimatePriority(nBlocks);
728728
}
729+
730+
UniValue estimatesmartfee(const UniValue& params, bool fHelp)
731+
{
732+
if (fHelp || params.size() != 1)
733+
throw runtime_error(
734+
"estimatesmartfee nblocks\n"
735+
"\nWARNING: This interface is unstable and may disappear or change!\n"
736+
"\nEstimates the approximate fee per kilobyte needed for a transaction to begin\n"
737+
"confirmation within nblocks blocks if possible and return the number of blocks\n"
738+
"for which the estimate is valid.\n"
739+
"\nArguments:\n"
740+
"1. nblocks (numeric)\n"
741+
"\nResult:\n"
742+
"{\n"
743+
" \"feerate\" : x.x, (numeric) estimate fee-per-kilobyte (in BTC)\n"
744+
" \"blocks\" : n (numeric) block number where estimate was found\n"
745+
"}\n"
746+
"\n"
747+
"A negative value is returned if not enough transactions and blocks\n"
748+
"have been observed to make an estimate for any number of blocks.\n"
749+
"However it will not return a value below the mempool reject fee.\n"
750+
"\nExample:\n"
751+
+ HelpExampleCli("estimatesmartfee", "6")
752+
);
753+
754+
RPCTypeCheck(params, boost::assign::list_of(UniValue::VNUM));
755+
756+
int nBlocks = params[0].get_int();
757+
758+
UniValue result(UniValue::VOBJ);
759+
int answerFound;
760+
CFeeRate feeRate = mempool.estimateSmartFee(nBlocks, &answerFound);
761+
result.push_back(Pair("feerate", feeRate == CFeeRate(0) ? -1.0 : ValueFromAmount(feeRate.GetFeePerK())));
762+
result.push_back(Pair("blocks", answerFound));
763+
return result;
764+
}
765+
766+
UniValue estimatesmartpriority(const UniValue& params, bool fHelp)
767+
{
768+
if (fHelp || params.size() != 1)
769+
throw runtime_error(
770+
"estimatesmartpriority nblocks\n"
771+
"\nWARNING: This interface is unstable and may disappear or change!\n"
772+
"\nEstimates the approximate priority a zero-fee transaction needs to begin\n"
773+
"confirmation within nblocks blocks if possible and return the number of blocks\n"
774+
"for which the estimate is valid.\n"
775+
"\nArguments:\n"
776+
"1. nblocks (numeric)\n"
777+
"\nResult:\n"
778+
"{\n"
779+
" \"priority\" : x.x, (numeric) estimated priority\n"
780+
" \"blocks\" : n (numeric) block number where estimate was found\n"
781+
"}\n"
782+
"\n"
783+
"A negative value is returned if not enough transactions and blocks\n"
784+
"have been observed to make an estimate for any number of blocks.\n"
785+
"However if the mempool reject fee is set it will return 1e9 * MAX_MONEY.\n"
786+
"\nExample:\n"
787+
+ HelpExampleCli("estimatesmartpriority", "6")
788+
);
789+
790+
RPCTypeCheck(params, boost::assign::list_of(UniValue::VNUM));
791+
792+
int nBlocks = params[0].get_int();
793+
794+
UniValue result(UniValue::VOBJ);
795+
int answerFound;
796+
double priority = mempool.estimateSmartPriority(nBlocks, &answerFound);
797+
result.push_back(Pair("priority", priority));
798+
result.push_back(Pair("blocks", answerFound));
799+
return result;
800+
}

src/rpcserver.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -319,6 +319,8 @@ static const CRPCCommand vRPCCommands[] =
319319
{ "util", "verifymessage", &verifymessage, true },
320320
{ "util", "estimatefee", &estimatefee, true },
321321
{ "util", "estimatepriority", &estimatepriority, true },
322+
{ "util", "estimatesmartfee", &estimatesmartfee, true },
323+
{ "util", "estimatesmartpriority", &estimatesmartpriority, true },
322324

323325
/* Not shown in help */
324326
{ "hidden", "invalidateblock", &invalidateblock, true },

src/rpcserver.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,8 @@ extern UniValue getblocktemplate(const UniValue& params, bool fHelp);
193193
extern UniValue submitblock(const UniValue& params, bool fHelp);
194194
extern UniValue estimatefee(const UniValue& params, bool fHelp);
195195
extern UniValue estimatepriority(const UniValue& params, bool fHelp);
196+
extern UniValue estimatesmartfee(const UniValue& params, bool fHelp);
197+
extern UniValue estimatesmartpriority(const UniValue& params, bool fHelp);
196198

197199
extern UniValue getnewaddress(const UniValue& params, bool fHelp); // in rpcwallet.cpp
198200
extern UniValue getaccountaddress(const UniValue& params, bool fHelp);

0 commit comments

Comments
 (0)