psibase 0.23.0

Library and command-line tool for interacting with psibase networks
Documentation
//! # Description
//!
//! Dynamic difficulty adjustment service for adaptive rate limiting
//!
//! This service provides a self-adjusting rate limiting mechanism that dynamically modifies
//! difficulty thresholds based on observed activity patterns. Each rate limiter is represented
//! by an NFT, allowing ownership-based administration.
//!
//! # Mechanics
//!
//! The service operates on a time-windowed counter system:
//!
//! 1. **Activity Tracking**: A consumer account increments a counter each time an action occurs.
//!    The counter accumulates activity within a configurable time window.
//!
//! 2. **Difficulty Adjustment**:
//!    - **Below Target**: If the counter is below `target_min` when a window elapses, the
//!      difficulty decreases by a configured percentage (subject to a floor value).
//!    - **Above Target**: If the counter exceeds `target_max` at any point, the difficulty
//!      immediately increases by a configured percentage, the counter resets, and a new window
//!      begins. If one increment pushes the counter past `target_max` by one or more whole multiples
//!      of `target_max`, the difficulty is increased by the configured percentage once per multiple.
//!
//! 3. **Window-Based Decay**: After each window period (`window_seconds`), if activity was below
//!    the minimum target, difficulty decays proportionally for each complete window that elapsed.
//!
//! 4. **Bounded Adjustments**: Difficulty cannot fall below `floor_difficulty`, ensuring a minimum
//!    security threshold is maintained.
//!
//! # Roles
//!
//! - **Admin**: The NFT owner can configure all parameters (targets, window, percentages, floor).
//!   The NFT is initially minted to the account that creates the rate limiter, but can be
//!   transferred to change administration.
//! - **Consumer**: The account designated at creation time can increment the counter and query
//!   difficulty. The consumer is automatically set to the account that calls `create()` and cannot
//!   be changed after creation. Initially, the creator is both admin and consumer, but the admin
//!   role can be transferred via NFT ownership while the consumer remains fixed.
#[crate::service(name = "diff-adjust", dispatch = false, psibase_mod = "crate")]
#[allow(non_snake_case, unused_variables)]
pub mod Service {

    /// Creates a new Rate limit
    ///
    /// # Arguments
    /// * `initial_difficulty` - Sets initial difficulty
    /// * `window_seconds` - Seconds duration before decay occurs
    /// * `target_min` - Minimum rate limit target
    /// * `target_max` - Maximum rate limit target
    /// * `floor_difficulty` - Minimum difficulty
    /// * `increase_ppm` - PPM to increase when over target, e.g. 50000 ppm = 5%
    /// * `decrease_ppm` - PPM to decrease when under target, e.g. 50000 ppm = 5%
    #[action]
    fn create(
        initial_difficulty: u64,
        window_seconds: u32,
        target_min: u32,
        target_max: u32,
        floor_difficulty: u64,
        increase_ppm: u32,
        decrease_ppm: u32,
    ) -> u32 {
        unimplemented!()
    }

    /// Get RateLimit difficulty
    ///
    /// # Arguments
    /// * `nft_id` - RateLimit / NFT ID
    ///
    /// # Returns
    /// Difficulty of RateLimit
    #[action]
    fn get_diff(nft_id: u32) -> u64 {
        unimplemented!()
    }

    /// Increment RateLimit instance, potentially increasing the difficulty.
    ///
    /// The difficulty may increase multiple times if the counter exceeds `target_max`
    ///   by more than one multiple of `target_max`.
    ///
    /// Returns the difficulty before any difficulty adjustment due to the increment.
    ///
    /// * Requires sender to be consumer account.
    ///
    /// # Arguments
    /// * `nft_id` - RateLimit / NFT ID
    /// * `amount` - Amount to increment the counter by
    #[action]
    fn increment(nft_id: u32, amount: u32) -> u64 {
        unimplemented!()
    }

    /// Update targets
    ///
    /// * Requires holding administration NFT.
    ///
    /// # Arguments
    /// * `nft_id` - RateLimit / NFT ID
    /// * `target_min` - Minimum target difficulty
    /// * `target_max` - Maximum target difficulty
    #[action]
    fn set_targets(nft_id: u32, target_min: u32, target_max: u32) {
        unimplemented!()
    }

    /// Update window
    ///
    /// * Requires holding administration NFT.
    ///
    /// # Arguments
    /// * `nft_id` - RateLimit / NFT ID
    /// * `seconds` - Seconds
    #[action]
    fn set_window(nft_id: u32, seconds: u32) {
        unimplemented!()
    }

    /// Update floor difficulty
    ///
    /// * Requires holding administration NFT.
    ///
    /// # Arguments
    /// * `nft_id` - RateLimit / NFT ID
    /// * `difficulty` - Difficulty
    #[action]
    fn set_floor(nft_id: u32, difficulty: u64) {
        unimplemented!()
    }

    /// Update ppm change
    ///
    /// * Requires holding administration NFT.
    ///
    /// # Arguments
    /// * `nft_id` - RateLimit / NFT ID
    /// * `increase_ppm` - PPM to increase when over target, e.g. 50000 ppm = 5%
    /// * `decrease_ppm` - PPM to decrease when under target, e.g. 50000 ppm = 5%
    #[action]
    fn set_ppm(nft_id: u32, increase_ppm: u32, decrease_ppm: u32) {
        unimplemented!()
    }

    /// Delete RateLimit instance
    ///
    /// * Requires holding administration NFT.
    ///
    /// # Arguments
    /// * `nft_id` - RateLimit / NFT ID
    #[action]
    fn delete(nft_id: u32) {
        unimplemented!()
    }

    /// Get targets
    ///
    /// Gets the minimum and maximum targets for the specified DiffAdjust
    ///
    /// Returns (target_min, target_max)
    #[action]
    fn get_targets(nft_id: u32) -> (u32, u32) {
        unimplemented!()
    }
}

#[test]
fn verify_schema() {
    crate::assert_schema_matches_package::<Wrapper>();
}