@@ -838,9 +838,9 @@ UniValue estimatesmartfee(const JSONRPCRequest& request)
838
838
839
839
UniValue estimaterawfee (const JSONRPCRequest& request)
840
840
{
841
- if (request.fHelp || request.params .size () < 1 || request.params .size () > 3 )
841
+ if (request.fHelp || request.params .size () < 1 || request.params .size () > 2 )
842
842
throw std::runtime_error (
843
- " estimaterawfee nblocks (threshold horizon )\n "
843
+ " estimaterawfee nblocks (threshold)\n "
844
844
" \n WARNING: This interface is unstable and may disappear or change!\n "
845
845
" \n WARNING: This is an advanced API call that is tightly coupled to the specific\n "
846
846
" implementation of fee estimation. The parameters it can be called with\n "
@@ -849,72 +849,95 @@ UniValue estimaterawfee(const JSONRPCRequest& request)
849
849
" confirmation within nblocks blocks if possible. Uses virtual transaction size as defined\n "
850
850
" in BIP 141 (witness data is discounted).\n "
851
851
" \n Arguments:\n "
852
- " 1. nblocks (numeric)\n "
852
+ " 1. nblocks (numeric) Confirmation target in blocks (1 - 1008) \n "
853
853
" 2. threshold (numeric, optional) The proportion of transactions in a given feerate range that must have been\n "
854
854
" confirmed within nblocks in order to consider those feerates as high enough and proceed to check\n "
855
855
" lower buckets. Default: 0.95\n "
856
- " 3. horizon (numeric, optional) How long a history of estimates to consider. 0=short, 1=medium, 2=long.\n "
857
- " Default: 1\n "
858
856
" \n Result:\n "
859
857
" {\n "
860
- " \" feerate\" : x.x, (numeric) estimate fee-per-kilobyte (in BTC)\n "
861
- " \" decay\" : x.x, (numeric) exponential decay (per block) for historical moving average of confirmation data\n "
862
- " \" scale\" : x, (numeric) The resolution of confirmation targets at this time horizon\n "
863
- " \" pass\" : { (json object) information about the lowest range of feerates to succeed in meeting the threshold\n "
864
- " \" startrange\" : x.x, (numeric) start of feerate range\n "
865
- " \" endrange\" : x.x, (numeric) end of feerate range\n "
866
- " \" withintarget\" : x.x, (numeric) number of txs over history horizon in the feerate range that were confirmed within target\n "
867
- " \" totalconfirmed\" : x.x, (numeric) number of txs over history horizon in the feerate range that were confirmed at any point\n "
868
- " \" inmempool\" : x.x, (numeric) current number of txs in mempool in the feerate range unconfirmed for at least target blocks\n "
869
- " \" leftmempool\" : x.x, (numeric) number of txs over history horizon in the feerate range that left mempool unconfirmed after target\n "
870
- " }\n "
871
- " \" fail\" : { ... } (json object) information about the highest range of feerates to fail to meet the threshold\n "
858
+ " \" short\" : { (json object, optional) estimate for short time horizon\n "
859
+ " \" feerate\" : x.x, (numeric, optional) estimate fee-per-kilobyte (in BTC)\n "
860
+ " \" decay\" : x.x, (numeric) exponential decay (per block) for historical moving average of confirmation data\n "
861
+ " \" scale\" : x, (numeric) The resolution of confirmation targets at this time horizon\n "
862
+ " \" pass\" : { (json object, optional) information about the lowest range of feerates to succeed in meeting the threshold\n "
863
+ " \" startrange\" : x.x, (numeric) start of feerate range\n "
864
+ " \" endrange\" : x.x, (numeric) end of feerate range\n "
865
+ " \" withintarget\" : x.x, (numeric) number of txs over history horizon in the feerate range that were confirmed within target\n "
866
+ " \" totalconfirmed\" : x.x, (numeric) number of txs over history horizon in the feerate range that were confirmed at any point\n "
867
+ " \" inmempool\" : x.x, (numeric) current number of txs in mempool in the feerate range unconfirmed for at least target blocks\n "
868
+ " \" leftmempool\" : x.x, (numeric) number of txs over history horizon in the feerate range that left mempool unconfirmed after target\n "
869
+ " },\n "
870
+ " \" fail\" : { ... }, (json object, optional) information about the highest range of feerates to fail to meet the threshold\n "
871
+ " \" errors\" : [ str... ] (json array of strings, optional) Errors encountered during processing\n "
872
+ " },\n "
873
+ " \" medium\" : { ... }, (json object, optional) estimate for medium time horizon\n "
874
+ " \" long\" : { ... } (json object) estimate for long time horizon\n "
872
875
" }\n "
873
876
" \n "
874
- " A negative feerate is returned if no answer can be given .\n "
877
+ " Results are returned for any horizon which tracks blocks up to the confirmation target .\n "
875
878
" \n Example:\n "
876
- + HelpExampleCli (" estimaterawfee" , " 6 0.9 1 " )
879
+ + HelpExampleCli (" estimaterawfee" , " 6 0.9" )
877
880
);
878
881
879
882
RPCTypeCheck (request.params , {UniValue::VNUM, UniValue::VNUM, UniValue::VNUM}, true );
880
883
RPCTypeCheckArgument (request.params [0 ], UniValue::VNUM);
881
884
int nBlocks = request.params [0 ].get_int ();
885
+ if (nBlocks < 1 || (unsigned int )nBlocks > ::feeEstimator.HighestTargetTracked (FeeEstimateHorizon::LONG_HALFLIFE)) {
886
+ throw JSONRPCError (RPC_INVALID_PARAMETER, " Invalid nblocks" );
887
+ }
882
888
double threshold = 0.95 ;
883
- if (!request.params [1 ].isNull ())
889
+ if (!request.params [1 ].isNull ()) {
884
890
threshold = request.params [1 ].get_real ();
885
- FeeEstimateHorizon horizon = FeeEstimateHorizon::MED_HALFLIFE;
886
- if (!request.params [2 ].isNull ()) {
887
- int horizonInt = request.params [2 ].get_int ();
888
- if (horizonInt < 0 || horizonInt > 2 ) {
889
- throw JSONRPCError (RPC_TYPE_ERROR, " Invalid horizon for fee estimates" );
890
- } else {
891
- horizon = (FeeEstimateHorizon)horizonInt;
892
- }
893
891
}
892
+ if (threshold < 0 || threshold > 1 ) {
893
+ throw JSONRPCError (RPC_INVALID_PARAMETER, " Invalid threshold" );
894
+ }
895
+
894
896
UniValue result (UniValue::VOBJ);
895
- CFeeRate feeRate;
896
- EstimationResult buckets;
897
- feeRate = ::feeEstimator.estimateRawFee (nBlocks, threshold, horizon, &buckets);
898
897
899
- result.push_back (Pair (" feerate" , feeRate == CFeeRate (0 ) ? -1.0 : ValueFromAmount (feeRate.GetFeePerK ())));
900
- result.push_back (Pair (" decay" , buckets.decay ));
901
- result.push_back (Pair (" scale" , (int )buckets.scale ));
902
- UniValue passbucket (UniValue::VOBJ);
903
- passbucket.push_back (Pair (" startrange" , round (buckets.pass .start )));
904
- passbucket.push_back (Pair (" endrange" , round (buckets.pass .end )));
905
- passbucket.push_back (Pair (" withintarget" , round (buckets.pass .withinTarget * 100.0 ) / 100.0 ));
906
- passbucket.push_back (Pair (" totalconfirmed" , round (buckets.pass .totalConfirmed * 100.0 ) / 100.0 ));
907
- passbucket.push_back (Pair (" inmempool" , round (buckets.pass .inMempool * 100.0 ) / 100.0 ));
908
- passbucket.push_back (Pair (" leftmempool" , round (buckets.pass .leftMempool * 100.0 ) / 100.0 ));
909
- result.push_back (Pair (" pass" , passbucket));
910
- UniValue failbucket (UniValue::VOBJ);
911
- failbucket.push_back (Pair (" startrange" , round (buckets.fail .start )));
912
- failbucket.push_back (Pair (" endrange" , round (buckets.fail .end )));
913
- failbucket.push_back (Pair (" withintarget" , round (buckets.fail .withinTarget * 100.0 ) / 100.0 ));
914
- failbucket.push_back (Pair (" totalconfirmed" , round (buckets.fail .totalConfirmed * 100.0 ) / 100.0 ));
915
- failbucket.push_back (Pair (" inmempool" , round (buckets.fail .inMempool * 100.0 ) / 100.0 ));
916
- failbucket.push_back (Pair (" leftmempool" , round (buckets.fail .leftMempool * 100.0 ) / 100.0 ));
917
- result.push_back (Pair (" fail" , failbucket));
898
+ for (FeeEstimateHorizon horizon : {FeeEstimateHorizon::SHORT_HALFLIFE, FeeEstimateHorizon::MED_HALFLIFE, FeeEstimateHorizon::LONG_HALFLIFE}) {
899
+ CFeeRate feeRate;
900
+ EstimationResult buckets;
901
+
902
+ // Only output results for horizons which track the target
903
+ if ((unsigned int )nBlocks > ::feeEstimator.HighestTargetTracked (horizon)) continue ;
904
+
905
+ feeRate = ::feeEstimator.estimateRawFee (nBlocks, threshold, horizon, &buckets);
906
+ UniValue horizon_result (UniValue::VOBJ);
907
+ UniValue errors (UniValue::VARR);
908
+ UniValue passbucket (UniValue::VOBJ);
909
+ passbucket.push_back (Pair (" startrange" , round (buckets.pass .start )));
910
+ passbucket.push_back (Pair (" endrange" , round (buckets.pass .end )));
911
+ passbucket.push_back (Pair (" withintarget" , round (buckets.pass .withinTarget * 100.0 ) / 100.0 ));
912
+ passbucket.push_back (Pair (" totalconfirmed" , round (buckets.pass .totalConfirmed * 100.0 ) / 100.0 ));
913
+ passbucket.push_back (Pair (" inmempool" , round (buckets.pass .inMempool * 100.0 ) / 100.0 ));
914
+ passbucket.push_back (Pair (" leftmempool" , round (buckets.pass .leftMempool * 100.0 ) / 100.0 ));
915
+ UniValue failbucket (UniValue::VOBJ);
916
+ failbucket.push_back (Pair (" startrange" , round (buckets.fail .start )));
917
+ failbucket.push_back (Pair (" endrange" , round (buckets.fail .end )));
918
+ failbucket.push_back (Pair (" withintarget" , round (buckets.fail .withinTarget * 100.0 ) / 100.0 ));
919
+ failbucket.push_back (Pair (" totalconfirmed" , round (buckets.fail .totalConfirmed * 100.0 ) / 100.0 ));
920
+ failbucket.push_back (Pair (" inmempool" , round (buckets.fail .inMempool * 100.0 ) / 100.0 ));
921
+ failbucket.push_back (Pair (" leftmempool" , round (buckets.fail .leftMempool * 100.0 ) / 100.0 ));
922
+
923
+ // CFeeRate(0) is used to indicate error as a return value from estimateRawFee
924
+ if (feeRate != CFeeRate (0 )) {
925
+ horizon_result.push_back (Pair (" feerate" , ValueFromAmount (feeRate.GetFeePerK ())));
926
+ horizon_result.push_back (Pair (" decay" , buckets.decay ));
927
+ horizon_result.push_back (Pair (" scale" , (int )buckets.scale ));
928
+ horizon_result.push_back (Pair (" pass" , passbucket));
929
+ // buckets.fail.start == -1 indicates that all buckets passed, there is no fail bucket to output
930
+ if (buckets.fail .start != -1 ) horizon_result.push_back (Pair (" fail" , failbucket));
931
+ } else {
932
+ // Output only information that is still meaningful in the event of error
933
+ horizon_result.push_back (Pair (" decay" , buckets.decay ));
934
+ horizon_result.push_back (Pair (" scale" , (int )buckets.scale ));
935
+ horizon_result.push_back (Pair (" fail" , failbucket));
936
+ errors.push_back (" Insufficient data or no feerate found which meets threshold" );
937
+ horizon_result.push_back (Pair (" errors" ,errors));
938
+ }
939
+ result.push_back (Pair (StringForFeeEstimateHorizon (horizon), horizon_result));
940
+ }
918
941
return result;
919
942
}
920
943
@@ -932,7 +955,7 @@ static const CRPCCommand commands[] =
932
955
{ " util" , " estimatefee" , &estimatefee, true , {" nblocks" } },
933
956
{ " util" , " estimatesmartfee" , &estimatesmartfee, true , {" nblocks" , " conservative" } },
934
957
935
- { " hidden" , " estimaterawfee" , &estimaterawfee, true , {" nblocks" , " threshold" , " horizon " } },
958
+ { " hidden" , " estimaterawfee" , &estimaterawfee, true , {" nblocks" , " threshold" } },
936
959
};
937
960
938
961
void RegisterMiningRPCCommands (CRPCTable &t)
0 commit comments