From 58b1afabec050ee54f8f51e13c83bbe88cda75f0 Mon Sep 17 00:00:00 2001 From: Hardik Jain Date: Tue, 20 Oct 2026 16:49:05 +0530 Subject: [PATCH 1/6] Adapt RGB wallet construction to the BFA library API --- lightning-invoice/Cargo.toml | 2 +- lightning/Cargo.toml | 3 ++- lightning/src/rgb_utils/mod.rs | 49 +++++++++++++++++++++++++--------- 3 files changed, 40 insertions(+), 14 deletions(-) diff --git a/lightning-invoice/Cargo.toml b/lightning-invoice/Cargo.toml index 17bd7e517..b7884547c 100644 --- a/lightning-invoice/Cargo.toml +++ b/lightning-invoice/Cargo.toml @@ -24,7 +24,7 @@ serde = { version = "1.0", optional = true, default-features = false, features = bitcoin = { version = "0.32.2", default-features = false, features = ["secp-recovery"] } # RGB and related -rgb-lib = { git = "https://github.com/UTEXO-Protocol/rgb-lib.git", tag = "v0.3.0-beta.50-bfa", default-features = false } +rgb-lib = { git = "https://github.com/UTEXO-Protocol/rgb-lib-bfa.git", rev = "3f571ac58909400046d69143ebb535f4da1f4d42", default-features = false } [dev-dependencies] serde_json = { version = "1"} diff --git a/lightning/Cargo.toml b/lightning/Cargo.toml index eeb54ddee..ed96ffeef 100644 --- a/lightning/Cargo.toml +++ b/lightning/Cargo.toml @@ -59,10 +59,11 @@ amplify = "4.8" bincode = "1.3" rgb-strict-encoding = "1.0.1" futures = "0.3" -rgb-lib = { git = "https://github.com/UTEXO-Protocol/rgb-lib.git", tag = "v0.3.0-beta.50-bfa", default-features = false } +rgb-lib = { git = "https://github.com/UTEXO-Protocol/rgb-lib-bfa.git", rev = "3f571ac58909400046d69143ebb535f4da1f4d42", default-features = false } serde = { version = "^1.0", features = [ "derive", ] } +serde_json = "1.0" tokio = { version = "1.14.1", features = [ "macros", "rt-multi-thread", diff --git a/lightning/src/rgb_utils/mod.rs b/lightning/src/rgb_utils/mod.rs index 7c3c6640d..7ae2df403 100644 --- a/lightning/src/rgb_utils/mod.rs +++ b/lightning/src/rgb_utils/mod.rs @@ -28,7 +28,8 @@ use rgb_lib::{ keys::WitnessVersion, wallet::{ rust_only::{AssetColoringInfo, ColoringInfo}, - DatabaseType, OnlineOptions, RgbWalletOpsOffline, SinglesigKeys, Wallet, WalletData, + DatabaseType, IndexerConfig, OnlineOptions, RgbWalletOpsOffline, SinglesigKeys, Wallet, + WalletData, }, AssetSchema, Assignment, BitcoinNetwork, ConsignmentExt, ContractId, Error as RgbLibError, Fascia, FileContent, RgbTransfer, WitnessOrd, @@ -55,6 +56,8 @@ pub const INDEXER_URL_FNAME: &str = "indexer_url"; /// KVStore configuration key for the Ethereum RPC used to validate BFA funding consignments. /// Missing or empty values disable BFA support. pub const ETH_RPC_URL_FNAME: &str = "eth_rpc_url"; +/// EVM RPC endpoints by chain ID, serialized as JSON for the current unlock. +pub const EVM_RPC_URLS_FNAME: &str = "evm_rpc_urls"; /// Name of the file containing the account-level xPub of the vanilla-side of the wallet pub const WALLET_ACCOUNT_XPUB_VANILLA_FNAME: &str = "wallet_account_xpub_vanilla"; /// Name of the file containing the account-level xPub of the colored-side of the wallet @@ -195,6 +198,34 @@ fn _get_eth_rpc_url(kv_store: &dyn KVStoreSync) -> Option { } } +fn _get_evm_rpc_urls(kv_store: &dyn KVStoreSync) -> HashMap { + match kv_store.read_config(EVM_RPC_URLS_FNAME) { + Ok(value) => serde_json::from_str(&value).expect("invalid EVM RPC map in KVStore"), + Err(e) if e.kind() == io::ErrorKind::NotFound => HashMap::new(), + Err(e) => panic!("cannot read EVM RPC configuration: {e}"), + } +} + +/// Construct explicit indexer and EVM options for the protocol-1.0 BFA library. +pub fn rgb_online_options( + indexer_url: String, evm_rpc_urls: HashMap, skip_consistency_check: bool, +) -> OnlineOptions { + let indexer_config = + if indexer_url.starts_with("https://") || indexer_url.starts_with("http://") { + IndexerConfig::Esplora { url: indexer_url } + } else { + IndexerConfig::Electrum { url: indexer_url } + }; + OnlineOptions { + indexer_config, + skip_consistency_check, + vanilla_sync_lookback: VANILLA_SYNC_LOOKBACK, + failed_witness_receive_grace_secs: 86400, + proxy_auth_keys: HashMap::new(), + evm_rpc_urls, + } +} + #[cfg(test)] mod bfa_config_tests { use super::*; @@ -238,7 +269,7 @@ pub fn supported_asset_schemas(bitcoin_network: BitcoinNetwork, bfa: bool) -> Ve fn _new_rgb_wallet( data_dir: String, bitcoin_network: BitcoinNetwork, account_xpub_vanilla: String, - account_xpub_colored: String, master_fingerprint: String, reuse_addresses: bool, bfa: bool, + account_xpub_colored: String, master_fingerprint: String, _reuse_addresses: bool, bfa: bool, ) -> Wallet { let keys = SinglesigKeys { account_xpub_vanilla, @@ -255,7 +286,6 @@ fn _new_rgb_wallet( database_type: DatabaseType::Sqlite, max_allocations_per_utxo: 1, supported_schemas: supported_asset_schemas(bitcoin_network, bfa), - reuse_addresses, }, keys, ) @@ -282,7 +312,7 @@ fn _get_wallet_data( } async fn _get_rgb_wallet(ldk_data_dir: &Path, kv_store: &dyn KVStoreSync) -> Wallet { - let bfa = _get_eth_rpc_url(kv_store).is_some(); + let bfa = !_get_evm_rpc_urls(kv_store).is_empty(); let ( data_dir, bitcoin_network, @@ -328,7 +358,7 @@ async fn _accept_transfer( reuse_addresses, ) = _get_wallet_data(ldk_data_dir, kv_store); let indexer_url = _get_indexer_url(kv_store); - let eth_rpc_url = _get_eth_rpc_url(kv_store); + let evm_rpc_urls = _get_evm_rpc_urls(kv_store); // the consignment is received from the channel counterparty over the p2p link and written to disk let consignment_path = ldk_data_dir.join(format!("consignment_{funding_txid}")); tokio::task::spawn_blocking(move || { @@ -339,14 +369,9 @@ async fn _accept_transfer( account_xpub_colored, master_fingerprint, reuse_addresses, - eth_rpc_url.is_some(), + !evm_rpc_urls.is_empty(), ); - let online = wallet.go_online(OnlineOptions { - indexer_url, - skip_consistency_check: true, - vanilla_sync_lookback: VANILLA_SYNC_LOOKBACK, - eth_rpc_url, - })?; + let online = wallet.go_online(rgb_online_options(indexer_url, evm_rpc_urls, true))?; let (consignment, assignments, media_digests) = wallet.accept_transfer_consignment( online, consignment_path, From 6f5a57db5cc5c0569973d79a99ba99d9ee39a65a Mon Sep 17 00:00:00 2001 From: Hardik Jain Date: Tue, 20 Oct 2026 16:59:44 +0530 Subject: [PATCH 2/6] Pin validated contract and snapshot prerequisites --- lightning-invoice/Cargo.toml | 2 +- lightning/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lightning-invoice/Cargo.toml b/lightning-invoice/Cargo.toml index b7884547c..af61cb6b3 100644 --- a/lightning-invoice/Cargo.toml +++ b/lightning-invoice/Cargo.toml @@ -24,7 +24,7 @@ serde = { version = "1.0", optional = true, default-features = false, features = bitcoin = { version = "0.32.2", default-features = false, features = ["secp-recovery"] } # RGB and related -rgb-lib = { git = "https://github.com/UTEXO-Protocol/rgb-lib-bfa.git", rev = "3f571ac58909400046d69143ebb535f4da1f4d42", default-features = false } +rgb-lib = { git = "https://github.com/UTEXO-Protocol/rgb-lib-bfa.git", rev = "7ce6045d7da6f07010aad1fe1b4f934437c8fc6d", default-features = false } [dev-dependencies] serde_json = { version = "1"} diff --git a/lightning/Cargo.toml b/lightning/Cargo.toml index ed96ffeef..58b34fb17 100644 --- a/lightning/Cargo.toml +++ b/lightning/Cargo.toml @@ -59,7 +59,7 @@ amplify = "4.8" bincode = "1.3" rgb-strict-encoding = "1.0.1" futures = "0.3" -rgb-lib = { git = "https://github.com/UTEXO-Protocol/rgb-lib-bfa.git", rev = "3f571ac58909400046d69143ebb535f4da1f4d42", default-features = false } +rgb-lib = { git = "https://github.com/UTEXO-Protocol/rgb-lib-bfa.git", rev = "7ce6045d7da6f07010aad1fe1b4f934437c8fc6d", default-features = false } serde = { version = "^1.0", features = [ "derive", ] } From 510189d5700a6d1406229ce7523e181c3838715e Mon Sep 17 00:00:00 2001 From: Hardik Jain Date: Tue, 20 Oct 2026 17:18:23 +0530 Subject: [PATCH 3/6] Pin content-bound BFA wallet snapshot source --- lightning-invoice/Cargo.toml | 2 +- lightning/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lightning-invoice/Cargo.toml b/lightning-invoice/Cargo.toml index af61cb6b3..d12e6c035 100644 --- a/lightning-invoice/Cargo.toml +++ b/lightning-invoice/Cargo.toml @@ -24,7 +24,7 @@ serde = { version = "1.0", optional = true, default-features = false, features = bitcoin = { version = "0.32.2", default-features = false, features = ["secp-recovery"] } # RGB and related -rgb-lib = { git = "https://github.com/UTEXO-Protocol/rgb-lib-bfa.git", rev = "7ce6045d7da6f07010aad1fe1b4f934437c8fc6d", default-features = false } +rgb-lib = { git = "https://github.com/UTEXO-Protocol/rgb-lib-bfa.git", rev = "962730a211f0f7569d7ad8ae777052f433d87655", default-features = false } [dev-dependencies] serde_json = { version = "1"} diff --git a/lightning/Cargo.toml b/lightning/Cargo.toml index 58b34fb17..f22b1c8e9 100644 --- a/lightning/Cargo.toml +++ b/lightning/Cargo.toml @@ -59,7 +59,7 @@ amplify = "4.8" bincode = "1.3" rgb-strict-encoding = "1.0.1" futures = "0.3" -rgb-lib = { git = "https://github.com/UTEXO-Protocol/rgb-lib-bfa.git", rev = "7ce6045d7da6f07010aad1fe1b4f934437c8fc6d", default-features = false } +rgb-lib = { git = "https://github.com/UTEXO-Protocol/rgb-lib-bfa.git", rev = "962730a211f0f7569d7ad8ae777052f433d87655", default-features = false } serde = { version = "^1.0", features = [ "derive", ] } From bbe68189872c26088e351d034b05c58769cb996a Mon Sep 17 00:00:00 2001 From: Hardik Jain Date: Fri, 23 Oct 2026 11:42:57 +0530 Subject: [PATCH 4/6] Pin strict EVM gateway request compatibility --- lightning-invoice/Cargo.toml | 2 +- lightning/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lightning-invoice/Cargo.toml b/lightning-invoice/Cargo.toml index d12e6c035..7b877dfb5 100644 --- a/lightning-invoice/Cargo.toml +++ b/lightning-invoice/Cargo.toml @@ -24,7 +24,7 @@ serde = { version = "1.0", optional = true, default-features = false, features = bitcoin = { version = "0.32.2", default-features = false, features = ["secp-recovery"] } # RGB and related -rgb-lib = { git = "https://github.com/UTEXO-Protocol/rgb-lib-bfa.git", rev = "962730a211f0f7569d7ad8ae777052f433d87655", default-features = false } +rgb-lib = { git = "https://github.com/UTEXO-Protocol/rgb-lib-bfa.git", rev = "89c37086a68ef792da75c62bce59b58b1d7952a0", default-features = false } [dev-dependencies] serde_json = { version = "1"} diff --git a/lightning/Cargo.toml b/lightning/Cargo.toml index f22b1c8e9..7e0c1b408 100644 --- a/lightning/Cargo.toml +++ b/lightning/Cargo.toml @@ -59,7 +59,7 @@ amplify = "4.8" bincode = "1.3" rgb-strict-encoding = "1.0.1" futures = "0.3" -rgb-lib = { git = "https://github.com/UTEXO-Protocol/rgb-lib-bfa.git", rev = "962730a211f0f7569d7ad8ae777052f433d87655", default-features = false } +rgb-lib = { git = "https://github.com/UTEXO-Protocol/rgb-lib-bfa.git", rev = "89c37086a68ef792da75c62bce59b58b1d7952a0", default-features = false } serde = { version = "^1.0", features = [ "derive", ] } From cf74e5b674115f12032cac6ee878028bcd6ab04c Mon Sep 17 00:00:00 2001 From: Hardik Jain Date: Tue, 27 Oct 2026 14:23:07 +0530 Subject: [PATCH 5/6] Pin integrated RGB sources and verify authenticated indexer builds --- .github/actions/private-sources/action.yml | 23 +++++++++++++++++ .github/workflows/build.yml | 29 ++++++++++++++++++++++ lightning-invoice/Cargo.toml | 2 +- lightning/Cargo.toml | 2 +- 4 files changed, 54 insertions(+), 2 deletions(-) create mode 100644 .github/actions/private-sources/action.yml diff --git a/.github/actions/private-sources/action.yml b/.github/actions/private-sources/action.yml new file mode 100644 index 000000000..ccec18aa7 --- /dev/null +++ b/.github/actions/private-sources/action.yml @@ -0,0 +1,23 @@ +name: Authenticate the pinned private RGB source +description: Configure Cargo's Git CLI fetches for rgb-lib-bfa. +inputs: + token: + description: Credential with read access to the pinned UTEXO-Protocol dependencies. + required: true +runs: + using: composite + steps: + - name: Configure scoped source authentication + shell: bash + env: + UTEXO_SOURCE_READ_TOKEN: ${{ inputs.token }} + run: | + set -euo pipefail + if [[ -z "$UTEXO_SOURCE_READ_TOKEN" ]]; then + echo "::error::Configure ORG_READ_TOKEN or RGB_LIB_RUST_LIGHTNING_PAT with read access to rgb-lib-bfa." + exit 1 + fi + git config --global \ + url."https://x-access-token:${UTEXO_SOURCE_READ_TOKEN}@github.com/UTEXO-Protocol/rgb-lib-bfa.git".insteadOf \ + "https://github.com/UTEXO-Protocol/rgb-lib-bfa.git" + echo "CARGO_NET_GIT_FETCH_WITH_CLI=true" >> "$GITHUB_ENV" diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 137b2d7d4..d10b8993e 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -9,12 +9,16 @@ on: - master workflow_dispatch: {} +permissions: + contents: read + concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true jobs: build: + timeout-minutes: 30 strategy: fail-fast: false matrix: @@ -29,6 +33,9 @@ jobs: steps: - name: Checkout source code uses: actions/checkout@v4 + - uses: ./.github/actions/private-sources + with: + token: ${{ secrets.ORG_READ_TOKEN || secrets.RGB_LIB_RUST_LIGHTNING_PAT }} - name: Install Rust ${{ matrix.toolchain }} toolchain run: | curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --profile=minimal --default-toolchain ${{ matrix.toolchain }} @@ -40,13 +47,34 @@ jobs: shell: bash # Default on Winblows is powershell run: cargo check --workspace --features lightning/electrum --verbose --color always + esplora: + name: Esplora workspace (Rust 1.94.0) + runs-on: ubuntu-latest + timeout-minutes: 30 + steps: + - name: Checkout source code + uses: actions/checkout@v4 + - uses: ./.github/actions/private-sources + with: + token: ${{ secrets.ORG_READ_TOKEN || secrets.RGB_LIB_RUST_LIGHTNING_PAT }} + - uses: actions-rust-lang/setup-rust-toolchain@v1 + with: + toolchain: 1.94.0 + rustflags: "" + - name: Check the supported Esplora source graph + run: cargo check --workspace --features lightning/esplora --verbose --color always + linting: + timeout-minutes: 30 runs-on: ubuntu-latest env: TOOLCHAIN: stable steps: - name: Checkout source code uses: actions/checkout@v4 + - uses: ./.github/actions/private-sources + with: + token: ${{ secrets.ORG_READ_TOKEN || secrets.RGB_LIB_RUST_LIGHTNING_PAT }} - name: Install Rust ${{ env.TOOLCHAIN }} toolchain run: | curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --profile=minimal --default-toolchain ${{ env.TOOLCHAIN }} @@ -58,6 +86,7 @@ jobs: ./ci/check-lint.sh rustfmt: + timeout-minutes: 10 runs-on: ubuntu-latest env: TOOLCHAIN: 1.63.0 diff --git a/lightning-invoice/Cargo.toml b/lightning-invoice/Cargo.toml index 7b877dfb5..fd557eee9 100644 --- a/lightning-invoice/Cargo.toml +++ b/lightning-invoice/Cargo.toml @@ -24,7 +24,7 @@ serde = { version = "1.0", optional = true, default-features = false, features = bitcoin = { version = "0.32.2", default-features = false, features = ["secp-recovery"] } # RGB and related -rgb-lib = { git = "https://github.com/UTEXO-Protocol/rgb-lib-bfa.git", rev = "89c37086a68ef792da75c62bce59b58b1d7952a0", default-features = false } +rgb-lib = { git = "https://github.com/UTEXO-Protocol/rgb-lib-bfa.git", rev = "45df336271ce9727306b6c9197ec44dcc74b7f07", default-features = false } [dev-dependencies] serde_json = { version = "1"} diff --git a/lightning/Cargo.toml b/lightning/Cargo.toml index 7e0c1b408..cccd01fc1 100644 --- a/lightning/Cargo.toml +++ b/lightning/Cargo.toml @@ -59,7 +59,7 @@ amplify = "4.8" bincode = "1.3" rgb-strict-encoding = "1.0.1" futures = "0.3" -rgb-lib = { git = "https://github.com/UTEXO-Protocol/rgb-lib-bfa.git", rev = "89c37086a68ef792da75c62bce59b58b1d7952a0", default-features = false } +rgb-lib = { git = "https://github.com/UTEXO-Protocol/rgb-lib-bfa.git", rev = "45df336271ce9727306b6c9197ec44dcc74b7f07", default-features = false } serde = { version = "^1.0", features = [ "derive", ] } From 191c8b8ab293f3bb1936fc01c1c10a6ffff91882 Mon Sep 17 00:00:00 2001 From: Hardik Jain Date: Tue, 27 Oct 2026 16:05:14 +0530 Subject: [PATCH 6/6] Pin qualified RGB graph and test public indexer configuration --- .github/workflows/build.yml | 5 +++ lightning-invoice/Cargo.toml | 2 +- lightning/Cargo.toml | 2 +- lightning/tests/rgb_config.rs | 75 +++++++++++++++++++++++++++++++++++ 4 files changed, 82 insertions(+), 2 deletions(-) create mode 100644 lightning/tests/rgb_config.rs diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index d10b8993e..31650cdc7 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -46,6 +46,9 @@ jobs: - name: Build the workspace shell: bash # Default on Winblows is powershell run: cargo check --workspace --features lightning/electrum --verbose --color always + - name: Test the public RGB configuration contract with Electrum + shell: bash + run: cargo test -p lightning --features electrum --test rgb_config --verbose --color always esplora: name: Esplora workspace (Rust 1.94.0) @@ -63,6 +66,8 @@ jobs: rustflags: "" - name: Check the supported Esplora source graph run: cargo check --workspace --features lightning/esplora --verbose --color always + - name: Test the public RGB configuration contract with Esplora + run: cargo test -p lightning --features esplora --test rgb_config --verbose --color always linting: timeout-minutes: 30 diff --git a/lightning-invoice/Cargo.toml b/lightning-invoice/Cargo.toml index fd557eee9..da55d4f2b 100644 --- a/lightning-invoice/Cargo.toml +++ b/lightning-invoice/Cargo.toml @@ -24,7 +24,7 @@ serde = { version = "1.0", optional = true, default-features = false, features = bitcoin = { version = "0.32.2", default-features = false, features = ["secp-recovery"] } # RGB and related -rgb-lib = { git = "https://github.com/UTEXO-Protocol/rgb-lib-bfa.git", rev = "45df336271ce9727306b6c9197ec44dcc74b7f07", default-features = false } +rgb-lib = { git = "https://github.com/UTEXO-Protocol/rgb-lib-bfa.git", rev = "abd41d3afff6d8fb11461e26e843301650e22df3", default-features = false } [dev-dependencies] serde_json = { version = "1"} diff --git a/lightning/Cargo.toml b/lightning/Cargo.toml index cccd01fc1..9bd018518 100644 --- a/lightning/Cargo.toml +++ b/lightning/Cargo.toml @@ -59,7 +59,7 @@ amplify = "4.8" bincode = "1.3" rgb-strict-encoding = "1.0.1" futures = "0.3" -rgb-lib = { git = "https://github.com/UTEXO-Protocol/rgb-lib-bfa.git", rev = "45df336271ce9727306b6c9197ec44dcc74b7f07", default-features = false } +rgb-lib = { git = "https://github.com/UTEXO-Protocol/rgb-lib-bfa.git", rev = "abd41d3afff6d8fb11461e26e843301650e22df3", default-features = false } serde = { version = "^1.0", features = [ "derive", ] } diff --git a/lightning/tests/rgb_config.rs b/lightning/tests/rgb_config.rs new file mode 100644 index 000000000..72deeda28 --- /dev/null +++ b/lightning/tests/rgb_config.rs @@ -0,0 +1,75 @@ +//! Public RGB configuration contracts, independent of the legacy Lightning unit-test harness. + +use lightning::rgb_utils::{rgb_online_options, supported_asset_schemas}; +use rgb_lib::wallet::IndexerConfig; +use rgb_lib::{AssetSchema, BitcoinNetwork}; +use std::collections::HashMap; + +#[test] +fn bfa_schema_requires_explicit_opt_in_on_every_network() { + for network in [ + BitcoinNetwork::Mainnet, + BitcoinNetwork::Testnet, + BitcoinNetwork::Testnet4, + BitcoinNetwork::Signet, + BitcoinNetwork::SignetCustom, + BitcoinNetwork::Regtest, + ] { + let baseline = supported_asset_schemas(network, false); + assert!(!baseline.contains(&AssetSchema::Bfa)); + assert!(baseline.contains(&AssetSchema::Nia)); + assert!(baseline.contains(&AssetSchema::Cfa)); + assert!(baseline.contains(&AssetSchema::Uda)); + assert_eq!(baseline.contains(&AssetSchema::Ifa), network != BitcoinNetwork::Mainnet); + let enabled = supported_asset_schemas(network, true); + assert_eq!(enabled.iter().filter(|schema| **schema == AssetSchema::Bfa).count(), 1); + let retained: Vec<_> = + enabled.into_iter().filter(|schema| *schema != AssetSchema::Bfa).collect(); + assert_eq!(retained, baseline, "BFA opt-in must preserve the other schema policy"); + } +} + +#[test] +fn indexer_selection_preserves_the_configured_url() { + for url in ["ssl://indexer.invalid:50002", "tcp://127.0.0.1:50001"] { + let options = rgb_online_options(url.into(), HashMap::new(), false); + assert!( + matches!(options.indexer_config, IndexerConfig::Electrum { url: actual } if actual == url) + ); + } + for url in ["https://indexer.invalid/api", "http://127.0.0.1:3002"] { + let options = rgb_online_options(url.into(), HashMap::new(), false); + assert!( + matches!(options.indexer_config, IndexerConfig::Esplora { url: actual } if actual == url) + ); + } +} + +#[test] +fn online_configuration_retains_explicit_evm_endpoints_and_safety_policy() { + let endpoints = HashMap::from([ + (1, "https://ethereum.invalid".into()), + (42161, "https://arbitrum.invalid/rpc".into()), + (31337, "http://127.0.0.1:8545".into()), + ]); + for skip_consistency_check in [false, true] { + let options = rgb_online_options( + "ssl://indexer.invalid:50002".into(), + endpoints.clone(), + skip_consistency_check, + ); + assert_eq!(options.evm_rpc_urls, endpoints); + assert_eq!(options.skip_consistency_check, skip_consistency_check); + assert_eq!(options.vanilla_sync_lookback, 20); + assert_eq!(options.failed_witness_receive_grace_secs, 86400); + assert!(options.proxy_auth_keys.is_empty(), "proxy authentication is explicit"); + } +} + +#[test] +fn missing_evm_configuration_does_not_invent_an_endpoint_or_proxy_secret() { + let options = rgb_online_options("http://127.0.0.1:3002".into(), HashMap::new(), false); + assert!(options.evm_rpc_urls.is_empty()); + assert!(options.proxy_auth_keys.is_empty()); + assert!(!options.skip_consistency_check); +}