/ cli / src / helpers / bech32m.rs
bech32m.rs
  1  // Copyright (c) 2025-2026 ACDC Network
  2  // This file is part of the alphaos library.
  3  //
  4  // Alpha Chain | Delta Chain Protocol
  5  // International Monetary Graphite.
  6  //
  7  // Derived from Aleo (https://aleo.org) and ProvableHQ (https://provable.com).
  8  // They built world-class ZK infrastructure. We installed the EASY button.
  9  // Their cryptography: elegant. Our modifications: bureaucracy-compatible.
 10  // Original brilliance: theirs. Robert's Rules: ours. Bugs: definitely ours.
 11  //
 12  // Original Aleo/ProvableHQ code subject to Apache 2.0 https://www.apache.org/licenses/LICENSE-2.0
 13  // All modifications and new work: CC0 1.0 Universal Public Domain Dedication.
 14  // No rights reserved. No permission required. No warranty. No refunds.
 15  //
 16  // https://creativecommons.org/publicdomain/zero/1.0/
 17  // SPDX-License-Identifier: CC0-1.0
 18  
 19  pub const BECH32M_CHARSET: &str = "qpzry9x8gf2tvdw0s3jn54khce6mua7l1";
 20  
 21  /// Check if a string is a valid bech32m character set.
 22  ///
 23  /// A bech32m character set is considered valid if it consists of the following characters:
 24  /// ```ignore
 25  ///     qpzry9x8gf2tvdw0s3jn54khce6mua7l1
 26  /// ```
 27  /// The function returns `true` if the string is a valid bech32m character set, and `false` otherwise.
 28  pub fn is_in_bech32m_charset(s: &str) -> bool {
 29      s.as_bytes().iter().all(|b| BECH32M_CHARSET.as_bytes().contains(b))
 30  }
 31  
 32  /// Check if a given vanity string exists at the start or end of the data part of a bech32m string.
 33  ///
 34  /// The bech32m string must have the following format:
 35  /// ```ignore
 36  ///     <HRP>1<data>[<vanity string>]
 37  /// ```
 38  /// where:
 39  ///
 40  /// - `<HRP>` is the human-readable part of the bech32m string.
 41  /// - `1` is the separator between the HRP and the data part.
 42  /// - `<data>` is the data part of the bech32m string.
 43  /// - `<vanity string>` is the vanity string to search for. This string may or may not be present at
 44  ///   the start or end of the data part.
 45  ///
 46  /// The function returns `true` if the vanity string exists at the start or end of the data part, and
 47  /// `false` otherwise.
 48  pub fn has_vanity_string(s: &str, vanity: &str) -> bool {
 49      // Split the bech32m string into the HRP and data parts.
 50      let (hrp, data) = match s.split_once('1') {
 51          Some((hrp, data)) => (hrp, data),
 52          // The bech32m string is invalid.
 53          None => return false,
 54      };
 55      // Ensure neither the HRP nor the data part are empty.
 56      if hrp.is_empty() || data.is_empty() {
 57          return false;
 58      }
 59      // Check if the vanity string exists at the start or end of the data part.
 60      data.starts_with(vanity) || data.ends_with(vanity)
 61  }
 62  
 63  #[test]
 64  fn test_is_in_bech32m_charset() {
 65      // Basic valid/invalid tests
 66      assert!(is_in_bech32m_charset("qpzry9x8gf2tvdw0s3jn54khce6mua7l1qpzry9x8gf2tvdw0s3jn54khce6mua7l1"));
 67      assert!(!is_in_bech32m_charset("qpzry9x8gf2tvdw0s3jn54khce6mua7l1qpzry9x8gf2tvdw0s3jn54khce6mua7lo"));
 68  
 69      // Boundary: empty string should be valid (all() returns true for empty)
 70      assert!(is_in_bech32m_charset(""));
 71  
 72      // Single character tests - kills all->any mutation
 73      assert!(is_in_bech32m_charset("q"));
 74      assert!(!is_in_bech32m_charset("o"));
 75  
 76      // Invalid character at different positions - kills boundary mutations
 77      assert!(!is_in_bech32m_charset("oqqq")); // Invalid at start
 78      assert!(!is_in_bech32m_charset("qqqo")); // Invalid at end
 79      assert!(!is_in_bech32m_charset("qqoq")); // Invalid in middle
 80  
 81      // All valid characters individually
 82      for c in BECH32M_CHARSET.chars() {
 83          assert!(is_in_bech32m_charset(&c.to_string()));
 84      }
 85  
 86      // Characters not in charset
 87      assert!(!is_in_bech32m_charset("b")); // Lowercase not in set
 88      assert!(!is_in_bech32m_charset("i")); // Excluded character
 89      assert!(!is_in_bech32m_charset("O")); // Uppercase
 90  }
 91  
 92  #[test]
 93  fn test_has_vanity_string() {
 94      // Basic tests
 95      assert!(has_vanity_string("myhrp1myvanitystring", "myvanitystring"));
 96      assert!(!has_vanity_string("myhrp1myvanitystring", "anotherstring"));
 97      assert!(has_vanity_string("myhrp1myvanitystring1234", "myvanitystring"));
 98      assert!(has_vanity_string("myhrp11234myvanitystring", "myvanitystring"));
 99      assert!(!has_vanity_string("myhrp1anotherstring1234", "myvanitystring"));
100  
101      // Test starts_with specifically (kills || -> && mutation)
102      assert!(has_vanity_string("hrp1vanity", "vanity"));
103      assert!(has_vanity_string("hrp1vanityxxx", "vanity")); // starts_with only
104  
105      // Test ends_with specifically (kills || -> && mutation)
106      assert!(has_vanity_string("hrp1xxxvanity", "vanity")); // ends_with only
107  
108      // Test neither starts nor ends (ensures || logic is tested)
109      assert!(!has_vanity_string("hrp1xxvanityxx", "vanity"));
110  
111      // Boundary: no separator - kills split_once mutation
112      assert!(!has_vanity_string("notseparated", "vanity"));
113  
114      // Boundary: empty HRP - kills hrp.is_empty() mutation
115      assert!(!has_vanity_string("1data", "data"));
116  
117      // Boundary: empty data - kills data.is_empty() mutation
118      assert!(!has_vanity_string("hrp1", ""));
119  
120      // Boundary: empty vanity string (should match any data)
121      assert!(has_vanity_string("hrp1anydata", ""));
122  
123      // Multiple separators - only first '1' is used
124      assert!(has_vanity_string("hrp11data", "1data"));
125      assert!(has_vanity_string("hrp1data1", "data1"));
126  
127      // Vanity in middle only (not at start or end)
128      assert!(!has_vanity_string("hrp1aavanitybb", "vanity"));
129  }