Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: (experimental) optional fee estimator with different algorithms #4477

Open
wants to merge 4 commits into
base: develop
Choose a base branch
from

Conversation

yangby-cryptape
Copy link
Collaborator

@yangby-cryptape yangby-cryptape commented Jun 4, 2024

What problem does this PR solve?

Warning

This feature is experimental.
I have done lots of manual tests before submit this PR, but more production environment tests are still required.

Add an optional fee estimator with different algorithms and a RPC method for it.

Description

  • I do lots manual tests for several day, I don't sure which algorithm is better, so I just submit both of them.

    Let's make choice after collect more data in production environment (both mainnet and testnet).

  • Only 4 levels of priorities for the fee estimator.

    Different algorithms have different APIs, I just use some constants as default parameters to avoid specialized parameters, to make the public API more generic.

Current, there are 2 built-in algorithms:

  • Confirmation Fraction

    Migrated from this CKB PR.

    👉🏼 Sometimes, it returns unreasonable result, I haven't figured it out yet, since I couldn't reproduce it manually.

  • Weight-Units Flow

    A variant of the Weight-Units Flow Fee Estimator for Bitcoin.

    The main difference is I use the block interval to replace the time interval, to avoid unit conversion with random distributions, since our APIs require blocks as the target unit for estimation.

    The details of this algorithm are written in the head section of that source code file.

Merged fallback fee estimates algorithm from #4465.

Usage

Append the following content to ckb.toml:

[fee_estimator]
# Specifies the fee estimates algorithm. Current algorithms: ConfirmationFraction, WeightUnitsFlow.
algorithm = "WeightUnitsFlow"

And enable JSON-RPC API module Experiment.

After the CKB node started, try the following command:

echo '{ "id": 1, "jsonrpc": "2.0", "method": "estimate_fee_rate", "params": [] }' \
    | curl -s -H "Content-Type: application/json" -d @- "http://localhost:8114" \
    | jq

An example of result is:

{
  "jsonrpc": "2.0",
  "result":"0x3e8",
  "id": 1
}

What is changed and how it works?

What's Changed:

Related changes

  • PR to update owner/repo:
  • Need to cherry-pick to the release branch

Check List

Tests

  • Unit test
  • Integration test

Release note

Title Only: Include only the PR title in the release note.

@yangby-cryptape yangby-cryptape requested a review from a team as a code owner June 4, 2024 06:55
@yangby-cryptape yangby-cryptape requested review from quake, chenyukang, zhangsoledad and eval-exec and removed request for a team June 4, 2024 06:55
Comment on lines +441 to +453
impl Algorithm {
pub fn update_ibd_state(&mut self, in_ibd: bool) {
if self.is_ready {
if in_ibd {
self.clear();
self.is_ready = false;
}
} else if !in_ibd {
self.clear();
self.is_ready = true;
}
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

update_ibd_state is executed every time ckb-chain finishes processing a block, is this the expected behavior?

Or should update_ibd_state only be executed when the ibd_state of ckb changes from true to false?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I was correct, the IBD state could change to true from false, when a CKB node lost Internet connections for a long time.

Copy link
Collaborator

@eval-exec eval-exec Sep 22, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe that when CKB leaves IBD mode, self.ibd_finished is set to true only once. If CKB loses internet connection after 24 hours, self.ibd_finished will always remain true.

Cc. @driftluo @zhangsoledad

    /// Return whether chain is in initial block download
    pub fn is_initial_block_download(&self) -> bool {
        // Once this function has returned false, it must remain false.
        if self.ibd_finished.load(Ordering::Acquire) {
            false
        } else if unix_time_as_millis().saturating_sub(self.snapshot().tip_header().timestamp())
            > MAX_TIP_AGE
        {
            true
        } else {
            self.ibd_finished.store(true, Ordering::Release);
            false
        }
    }

use ckb_types::core::{BlockNumber, FeeRate};

/// Average block interval.
pub(crate) const AVG_BLOCK_INTERVAL: u64 = (MAX_BLOCK_INTERVAL + MIN_BLOCK_INTERVAL) / 2;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The AVG_BLOCK_INTERVAL is calculated as (48 + 8) / 2, which equals 28 seconds. However, according to https://explorer.nervos.org/charts/block-time-distribution, most block intervals are less than 10 seconds.

pub(crate) const MIN_TARGET: BlockNumber = TX_PROPOSAL_WINDOW.closest() + 1;

/// Lowest fee rate.
pub(crate) const LOWEST_FEE_RATE: FeeRate = FeeRate::from_u64(1000);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we reuse DEFAULT_MIN_FEE_RATE from ckb-app-config?

#[error("dummy fee estimator is used")]
Dummy,
/// Not ready for do estimate.
#[error("not ready")]
Copy link
Collaborator

@eval-exec eval-exec Sep 22, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about giving a more verbose errro: #[error("not ready, node is in IBD mode")]

@eval-exec eval-exec added t:enhancement Type: Feature, refactoring. b:rpc Break RPC interface m:tx-pool labels Sep 22, 2024
/// confirm_blocks => bucket index => confirmed txs count
confirm_blocks_to_confirmed_txs: Vec<Vec<f64>>,
/// confirm_blocks => bucket index => failed txs count
confirm_blocks_to_failed_txs: Vec<Vec<f64>>,
Copy link
Collaborator

@eval-exec eval-exec Sep 22, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems that confirm_blocks_to_failed_txs's length is always 1?
I didn't find which method append/insert Vec<f64> to confirm_blocks_to_failed_txs after initialization.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
b:rpc Break RPC interface m:tx-pool t:enhancement Type: Feature, refactoring.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants