From 6b92607a1470b515979bc1c3e08a1e3cdd7b8948 Mon Sep 17 00:00:00 2001 From: GTO90 Date: Fri, 13 Feb 2026 11:23:23 -0600 Subject: [PATCH 1/9] build: fix deferred evaluation for OpenSSL CFLAGS in depends Use $$ deferred evaluation for CFLAGS/CPPFLAGS assignments so OS-specific flags (cflags_linux, cppflags_linux) appended by funcs.mk after set_vars are included. Route -fPIC and -D_GNU_SOURCE through proper cflags/cppflags variables instead of bare config_opts to avoid OpenSSL's "Mixing make variables" rejection. --- depends/packages/openssl.mk | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/depends/packages/openssl.mk b/depends/packages/openssl.mk index 83f676062d..45b730600c 100644 --- a/depends/packages/openssl.mk +++ b/depends/packages/openssl.mk @@ -16,10 +16,13 @@ define $(package)_set_vars # rather than positional args, because multi-word flags like "-arch arm64" # get split by the shell and OpenSSL's Configure misparses the second word # as a target name, causing "target already defined" errors on ARM64 macOS. - $(package)_config_opts+=CFLAGS="$($(package)_cflags)" - $(package)_config_opts+=CPPFLAGS="$($(package)_cppflags)" - $(package)_config_opts_linux=-fPIC -D_GNU_SOURCE - $(package)_config_opts_freebsd=-fPIC + # Use $$ for deferred evaluation so OS-specific flags (cflags_linux, etc.) + # appended by funcs.mk after set_vars runs are included in the expansion. + $(package)_config_opts+=CFLAGS="$$($(package)_cflags)" + $(package)_config_opts+=CPPFLAGS="$$($(package)_cppflags)" + $(package)_cflags_linux=-fPIC + $(package)_cppflags_linux=-D_GNU_SOURCE + $(package)_cflags_freebsd=-fPIC $(package)_config_opts_x86_64_linux=linux-x86_64 $(package)_config_opts_i686_linux=linux-generic32 $(package)_config_opts_arm_linux=linux-generic32 From dae34eb43fa2e6a97b514ae14ab8b6931e93e163 Mon Sep 17 00:00:00 2001 From: GTO90 Date: Fri, 13 Feb 2026 11:53:32 -0600 Subject: [PATCH 2/9] build: remove empty ARFLAGS from OpenSSL config_env The depends system never defines $(package)_arflags, so ARFLAGS=$($(package)_arflags) in config_env exported an empty ARFLAGS="" to the environment. When CFLAGS/CPPFLAGS are passed as VAR=value assignments (not positional flags), OpenSSL 1.1.1w's Configure sets $anyuseradd=false and falls back to reading env vars. The empty ARFLAGS overrides the target default "r" from Configurations/00-base-templates.conf, producing a Makefile with ARFLAGS= (empty). This causes "ar: two different operation options specified" on Linux and "ar: illegal option -- /" on macOS during build_libs, as ar interprets the archive path as flags. Fix: remove ARFLAGS from config_env entirely, letting Configure use its target default ARFLAGS="r". Verified locally: - Linux x86_64: ar r apps/libapps.a ... (ARFLAGS=r in Makefile) - macOS ARM64: ar r apps/libapps.a ... (ARFLAGS=r in Makefile) - Full build_libs completes successfully on darwin64-arm64-cc --- depends/packages/openssl.mk | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/depends/packages/openssl.mk b/depends/packages/openssl.mk index 45b730600c..5780089a92 100644 --- a/depends/packages/openssl.mk +++ b/depends/packages/openssl.mk @@ -5,7 +5,14 @@ $(package)_file_name=$(package)-$($(package)_version).tar.gz $(package)_sha256_hash=cf3098950cb4d853ad95c0841f1f9c6d3dc102dccfcacd521d93925208b76ac8 define $(package)_set_vars - $(package)_config_env=AR="$($(package)_ar)" ARFLAGS=$($(package)_arflags) RANLIB="$($(package)_ranlib)" CC="$($(package)_cc)" + # Do NOT export ARFLAGS in config_env. The depends system never defines + # $(package)_arflags, so it expands to empty string. When CFLAGS/CPPFLAGS + # are passed as VAR=value (no positional flags), OpenSSL's Configure sets + # $anyuseradd=false and falls back to reading env vars. An empty ARFLAGS + # in the environment overrides the target default ("r"), producing a + # Makefile with ARFLAGS= (empty), which causes "ar: two different + # operation options specified" at build time. + $(package)_config_env=AR="$($(package)_ar)" RANLIB="$($(package)_ranlib)" CC="$($(package)_cc)" $(package)_config_env_android=ANDROID_NDK_ROOT=$(host_prefix)/native $(package)_config_opts=no-capieng no-dso no-dtls1 no-ec_nistp_64_gcc_128 no-gost $(package)_config_opts+=no-md2 no-rc5 no-rdrand no-rfc3779 no-sctp no-shared From b33cccd782021e20b34a395be40a7f7880d0b953 Mon Sep 17 00:00:00 2001 From: GTO90 Date: Fri, 13 Feb 2026 13:38:17 -0600 Subject: [PATCH 3/9] test: add diagnostic messages to CI-failing mint validation tests Replace BOOST_CHECK with BOOST_CHECK_MESSAGE in 5 mint validation tests that fail on CI but pass locally. Diagnostic output captures the exact reject reason, script sizes, collateral amounts, and script type identification to help debug the CI-specific failure. --- src/test/digidollar_validation_tests.cpp | 47 +++++++++++++++++++----- 1 file changed, 37 insertions(+), 10 deletions(-) diff --git a/src/test/digidollar_validation_tests.cpp b/src/test/digidollar_validation_tests.cpp index ca01e0e7df..02931ad35b 100644 --- a/src/test/digidollar_validation_tests.cpp +++ b/src/test/digidollar_validation_tests.cpp @@ -342,8 +342,14 @@ BOOST_FIXTURE_TEST_CASE(transaction_validation_mint_tx, DigiDollarValidationTest CTransaction tx(mtx); TxValidationState state; - BOOST_CHECK(DigiDollar::ValidateDigiDollarTransaction(tx, validationContext, state)); - BOOST_CHECK(state.IsValid()); + bool result = DigiDollar::ValidateDigiDollarTransaction(tx, validationContext, state); + BOOST_CHECK_MESSAGE(result, "[transaction_validation_mint_tx] Expected valid, got reject: " + state.GetRejectReason() + + " | collateralScript.size()=" + std::to_string(collateralScript.size()) + + " ddScript.size()=" + std::to_string(ddScript.size()) + + " requiredCollateral=" + std::to_string(requiredCollateral) + + " collateralType=" + std::to_string(static_cast(DigiDollar::IdentifyScriptType(collateralScript))) + + " ddType=" + std::to_string(static_cast(DigiDollar::IdentifyScriptType(ddScript)))); + BOOST_CHECK_MESSAGE(state.IsValid(), "[transaction_validation_mint_tx] state invalid: " + state.GetRejectReason()); } BOOST_FIXTURE_TEST_CASE(transaction_validation_invalid_mint_amount, DigiDollarValidationTestSetup) @@ -466,8 +472,14 @@ BOOST_FIXTURE_TEST_CASE(mint_validation_valid_basic_mint, DigiDollarValidationTe TxValidationState state; // This should pass when implementation is complete - BOOST_CHECK(DigiDollar::ValidateDigiDollarTransaction(tx, validationContext, state)); - BOOST_CHECK(state.IsValid()); + bool result = DigiDollar::ValidateDigiDollarTransaction(tx, validationContext, state); + BOOST_CHECK_MESSAGE(result, "[mint_validation_valid_basic_mint] Expected valid, got reject: " + state.GetRejectReason() + + " | collateralScript.size()=" + std::to_string(collateralScript.size()) + + " ddScript.size()=" + std::to_string(ddScript.size()) + + " requiredCollateral=" + std::to_string(requiredCollateral) + + " collateralType=" + std::to_string(static_cast(DigiDollar::IdentifyScriptType(collateralScript))) + + " ddType=" + std::to_string(static_cast(DigiDollar::IdentifyScriptType(ddScript)))); + BOOST_CHECK_MESSAGE(state.IsValid(), "[mint_validation_valid_basic_mint] state invalid: " + state.GetRejectReason()); } BOOST_FIXTURE_TEST_CASE(mint_validation_insufficient_collateral, DigiDollarValidationTestSetup) @@ -724,8 +736,13 @@ BOOST_FIXTURE_TEST_CASE(mint_validation_dca_multiplier_adjustment, DigiDollarVal TxValidationState state; // Should pass with adjusted collateral - BOOST_CHECK(DigiDollar::ValidateDigiDollarTransaction(tx, validationContext, state)); - BOOST_CHECK(state.IsValid()); + bool result = DigiDollar::ValidateDigiDollarTransaction(tx, validationContext, state); + BOOST_CHECK_MESSAGE(result, "[mint_validation_dca_multiplier] Expected valid, got reject: " + state.GetRejectReason() + + " | systemCollateral=" + std::to_string(validationContext.systemCollateral) + + " adjustedCollateral=" + std::to_string(adjustedCollateral) + + " collateralType=" + std::to_string(static_cast(DigiDollar::IdentifyScriptType(collateralScript))) + + " ddType=" + std::to_string(static_cast(DigiDollar::IdentifyScriptType(ddScript)))); + BOOST_CHECK_MESSAGE(state.IsValid(), "[mint_validation_dca_multiplier] state invalid: " + state.GetRejectReason()); // Test with original 500% collateral - should fail CAmount originalCollateral = (static_cast(ddAmount) * COIN * 500 * 100) / mockOraclePrice; @@ -877,8 +894,13 @@ BOOST_FIXTURE_TEST_CASE(mint_validation_edge_case_exact_minimum, DigiDollarValid CTransaction tx(mtx); TxValidationState state; - BOOST_CHECK(DigiDollar::ValidateDigiDollarTransaction(tx, validationContext, state)); - BOOST_CHECK(state.IsValid()); + bool result = DigiDollar::ValidateDigiDollarTransaction(tx, validationContext, state); + BOOST_CHECK_MESSAGE(result, "[mint_validation_edge_case_exact_minimum] Expected valid, got reject: " + state.GetRejectReason() + + " | ddAmount=" + std::to_string(ddAmount) + + " exactCollateral=" + std::to_string(exactCollateral) + + " collateralType=" + std::to_string(static_cast(DigiDollar::IdentifyScriptType(collateralScript))) + + " ddType=" + std::to_string(static_cast(DigiDollar::IdentifyScriptType(ddScript)))); + BOOST_CHECK_MESSAGE(state.IsValid(), "[mint_validation_edge_case_exact_minimum] state invalid: " + state.GetRejectReason()); } BOOST_FIXTURE_TEST_CASE(mint_validation_edge_case_exact_maximum, DigiDollarValidationTestSetup) @@ -913,8 +935,13 @@ BOOST_FIXTURE_TEST_CASE(mint_validation_edge_case_exact_maximum, DigiDollarValid CTransaction tx(mtx); TxValidationState state; - BOOST_CHECK(DigiDollar::ValidateDigiDollarTransaction(tx, validationContext, state)); - BOOST_CHECK(state.IsValid()); + bool result = DigiDollar::ValidateDigiDollarTransaction(tx, validationContext, state); + BOOST_CHECK_MESSAGE(result, "[mint_validation_edge_case_exact_maximum] Expected valid, got reject: " + state.GetRejectReason() + + " | ddAmount=" + std::to_string(ddAmount) + + " requiredCollateral=" + std::to_string(requiredCollateral) + + " collateralType=" + std::to_string(static_cast(DigiDollar::IdentifyScriptType(collateralScript))) + + " ddType=" + std::to_string(static_cast(DigiDollar::IdentifyScriptType(ddScript)))); + BOOST_CHECK_MESSAGE(state.IsValid(), "[mint_validation_edge_case_exact_maximum] state invalid: " + state.GetRejectReason()); } // ============================================================================= From 1d8ddea163f2566407403ddab6649398d753377b Mon Sep 17 00:00:00 2001 From: GTO90 Date: Fri, 13 Feb 2026 13:46:07 -0600 Subject: [PATCH 4/9] test: fix cross-suite state pollution causing CI-only mint test failures Replace ClearFreeze() with ClearHistory() in the validation test fixture. ClearFreeze() only clears freeze flags, but UpdateState() (called during ValidateDigiDollarTransaction) recalculates volatility from stale price history left by earlier test suites (e.g., digidollar_health_tests) and re-sets the freeze. This caused all "valid mint" tests to fail with "minting-frozen-volatility" on CI where the test suite ordering (linker-dependent) places health_tests before validation_tests. ClearHistory() resets price history, volatility state, and all freeze flags, ensuring each test starts from a clean state. --- src/test/digidollar_validation_tests.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/test/digidollar_validation_tests.cpp b/src/test/digidollar_validation_tests.cpp index 02931ad35b..df0a503d33 100644 --- a/src/test/digidollar_validation_tests.cpp +++ b/src/test/digidollar_validation_tests.cpp @@ -37,8 +37,10 @@ struct DigiDollarValidationTestSetup : public TestingSetup { testPubKey = testKey.GetPubKey(); testXOnlyKey = XOnlyPubKey(testPubKey); - // Clear volatility freeze state from previous tests - DigiDollar::Volatility::VolatilityMonitor::ClearFreeze(); + // Clear ALL volatility state from previous test suites. + // ClearFreeze() alone is insufficient — UpdateState() recalculates + // from stale price history and can re-set freeze flags. + DigiDollar::Volatility::VolatilityMonitor::ClearHistory(); // Validation context is initialized in member initializer list } From b77f7f2acff0c9b671b21e6dcfa2c12e2a938556 Mon Sep 17 00:00:00 2001 From: GTO90 Date: Fri, 13 Feb 2026 13:52:10 -0600 Subject: [PATCH 5/9] ci: trigger CI run for cross-suite state pollution fix From b80613df9e1cfee2e58cb27b21158c8c7ffaee96 Mon Sep 17 00:00:00 2001 From: GTO90 Date: Fri, 13 Feb 2026 13:55:22 -0600 Subject: [PATCH 6/9] ci: re-trigger CI with cross-suite state pollution fix Previous CI re-run used old code without the fix. Canceling that and triggering fresh run. From c475e62235689dd14994abb5e412e83c9d63591e Mon Sep 17 00:00:00 2001 From: GTO90 Date: Fri, 13 Feb 2026 13:57:43 -0600 Subject: [PATCH 7/9] chore: update copyright year format in validation tests Trigger fresh CI run with the cross-suite state pollution fix. --- src/test/digidollar_validation_tests.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/digidollar_validation_tests.cpp b/src/test/digidollar_validation_tests.cpp index df0a503d33..afda10f59f 100644 --- a/src/test/digidollar_validation_tests.cpp +++ b/src/test/digidollar_validation_tests.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2025 The DigiByte Core developers +// Copyright (c) 2025-present The DigiByte Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. From 7eae4d6ac23620dea11db9d90164e76b96cd0b6a Mon Sep 17 00:00:00 2001 From: GTO90 Date: Fri, 13 Feb 2026 14:51:18 -0600 Subject: [PATCH 8/9] fix: resolve bad auto-merge that dropped DD amount consistency check The merge with feature/digidollar-v1 silently dropped critical code: 1. DD amount double-counting prevention in ValidateMintTransaction() The OP_RETURN and DD token output both encode ddAmount. Without the consistency check, totalDD was counted twice (e.g. 10000 + 10000 = 20000), requiring 2x the collateral and failing all valid mint tests. 2. Missing #include 3. Improved log format for insufficient-collateral diagnostic Also adopts the base branch's test file which includes: - DD OP_RETURN outputs required for T1-04b NUMS verification - Proper NUMS key usage via GetCollateralNUMSKey() - ClearHistory() fix for cross-suite volatility state pollution --- src/digidollar/validation.cpp | 19 ++++- src/test/digidollar_validation_tests.cpp | 95 +++++++++++++----------- 2 files changed, 66 insertions(+), 48 deletions(-) diff --git a/src/digidollar/validation.cpp b/src/digidollar/validation.cpp index 8b4e8657dc..fd98b9aa11 100644 --- a/src/digidollar/validation.cpp +++ b/src/digidollar/validation.cpp @@ -5,6 +5,7 @@ #include #include #include +#include // Phase 1 metadata tracking support using DigiDollar::ScriptMetadata; @@ -887,7 +888,18 @@ bool ValidateMintTransaction(const CTransaction& tx, LogPrintf("DigiDollar: Invalid DD amount: %d\n", ddAmount); return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-dd-amount"); } - totalDD += ddAmount; + // If totalDD was already set from OP_RETURN, verify consistency + // rather than double-counting the DD amount. + if (totalDD > 0) { + if (ddAmount != totalDD) { + LogPrintf("DigiDollar: DD amount mismatch: token output=%lld, OP_RETURN=%lld\n", + (long long)ddAmount, (long long)totalDD); + return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-dd-amount-mismatch", + "DD token output amount does not match OP_RETURN amount"); + } + } else { + totalDD += ddAmount; + } } // If we can't extract (cross-node validation), we'll calculate after loop } @@ -1018,8 +1030,9 @@ bool ValidateMintTransaction(const CTransaction& tx, // Verify sufficient collateral if (totalCollateral < requiredCollateral) { - LogPrintf("DigiDollar: Insufficient collateral: provided %d, required %d\n", - totalCollateral, requiredCollateral); + LogPrintf("DigiDollar: Insufficient collateral: provided %lld, required %lld (totalDD=%lld, lockPeriod=%lld)\n", + (long long)totalCollateral, (long long)requiredCollateral, + (long long)totalDD, (long long)lockPeriod); return state.Invalid(TxValidationResult::TX_CONSENSUS, "insufficient-collateral"); } diff --git a/src/test/digidollar_validation_tests.cpp b/src/test/digidollar_validation_tests.cpp index a278a58251..b788410e73 100644 --- a/src/test/digidollar_validation_tests.cpp +++ b/src/test/digidollar_validation_tests.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2025-present The DigiByte Core developers +// Copyright (c) 2025 The DigiByte Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. @@ -52,6 +52,22 @@ struct DigiDollarValidationTestSetup : public TestingSetup { int mockSystemCollateral; int mockHeight; DigiDollar::ValidationContext validationContext; + + // Helper: Build a DD mint OP_RETURN output script + // Format: OP_RETURN <"DD"> + CScript MakeDDMintOpReturn(CAmount ddAmount, int64_t lockHeight, int lockTier) { + CScript script; + script << OP_RETURN; + std::vector dd_marker = {'D', 'D'}; + script << dd_marker; + script << CScriptNum(1); // Type = MINT + script << CScriptNum::serialize(ddAmount); + script << CScriptNum::serialize(lockHeight); + script << CScriptNum(lockTier); + std::vector keyData(testXOnlyKey.begin(), testXOnlyKey.end()); + script << keyData; + return script; + } }; // ============================================================================ @@ -315,43 +331,51 @@ BOOST_FIXTURE_TEST_CASE(script_validation_non_dd_script, DigiDollarValidationTes BOOST_FIXTURE_TEST_CASE(transaction_validation_mint_tx, DigiDollarValidationTestSetup) { - // Create a mock mint transaction + // Create a valid mint transaction with all required components: + // - Collateral input + // - DD OP_RETURN with owner pubkey (required for NUMS verification per T1-04b) + // - Collateral output (P2TR with NUMS internal key) + // - DD token output CMutableTransaction mtx; mtx.nVersion = 0x01000770; // DD_TX_MINT (type=1 in bits 24-31, marker=0x0770 in bits 0-15) - // Add collateral input (simplified for test) + // Add collateral input mtx.vin.resize(1); mtx.vin[0].prevout = COutPoint(uint256S("0x1234"), 0); - // Add collateral output + // Set up mint parameters DigiDollar::MintParams params; params.ddAmount = 10000; // $100.00 - params.lockHeight = mockHeight + 30 * 24 * 60 * 4; + params.lockHeight = mockHeight + 30 * 24 * 60 * 4; // 30-day lock params.ownerKey = testXOnlyKey; - params.internalKey = testXOnlyKey; + params.internalKey = DigiDollar::GetCollateralNUMSKey(); params.oracleKeys = DigiDollar::GetOracleKeys(15); CScript collateralScript = DigiDollar::CreateCollateralP2TR(params); CAmount requiredCollateral = (static_cast(params.ddAmount) * COIN * 500 * 100) / mockOraclePrice; - mtx.vout.resize(2); - mtx.vout[0] = CTxOut(requiredCollateral, collateralScript); + // DD OP_RETURN with owner pubkey (required for NUMS verification) + CScript opReturn = CScript() << OP_RETURN + << std::vector{'D', 'D'} + << CScriptNum(1) + << CScriptNum(params.ddAmount) + << CScriptNum(params.lockHeight) + << CScriptNum(1) // lockTier 1 = 30 days + << std::vector(testXOnlyKey.begin(), testXOnlyKey.end()); + + mtx.vout.resize(3); + mtx.vout[0] = CTxOut(0, opReturn); + mtx.vout[1] = CTxOut(requiredCollateral, collateralScript); // Add DD token output CScript ddScript = DigiDollar::CreateDigiDollarP2TR(testXOnlyKey, params.ddAmount); - mtx.vout[1] = CTxOut(0, ddScript); // DD tokens have no DGB value + mtx.vout[2] = CTxOut(0, ddScript); // DD tokens have no DGB value CTransaction tx(mtx); TxValidationState state; - bool result = DigiDollar::ValidateDigiDollarTransaction(tx, validationContext, state); - BOOST_CHECK_MESSAGE(result, "[transaction_validation_mint_tx] Expected valid, got reject: " + state.GetRejectReason() - + " | collateralScript.size()=" + std::to_string(collateralScript.size()) - + " ddScript.size()=" + std::to_string(ddScript.size()) - + " requiredCollateral=" + std::to_string(requiredCollateral) - + " collateralType=" + std::to_string(static_cast(DigiDollar::IdentifyScriptType(collateralScript))) - + " ddType=" + std::to_string(static_cast(DigiDollar::IdentifyScriptType(ddScript)))); - BOOST_CHECK_MESSAGE(state.IsValid(), "[transaction_validation_mint_tx] state invalid: " + state.GetRejectReason()); + BOOST_CHECK(DigiDollar::ValidateDigiDollarTransaction(tx, validationContext, state)); + BOOST_CHECK(state.IsValid()); } BOOST_FIXTURE_TEST_CASE(transaction_validation_invalid_mint_amount, DigiDollarValidationTestSetup) @@ -494,13 +518,9 @@ BOOST_FIXTURE_TEST_CASE(mint_validation_valid_basic_mint, DigiDollarValidationTe // This should pass when implementation is complete bool result = DigiDollar::ValidateDigiDollarTransaction(tx, validationContext, state); - BOOST_CHECK_MESSAGE(result, "[mint_validation_valid_basic_mint] Expected valid, got reject: " + state.GetRejectReason() - + " | collateralScript.size()=" + std::to_string(collateralScript.size()) - + " ddScript.size()=" + std::to_string(ddScript.size()) - + " requiredCollateral=" + std::to_string(requiredCollateral) - + " collateralType=" + std::to_string(static_cast(DigiDollar::IdentifyScriptType(collateralScript))) - + " ddType=" + std::to_string(static_cast(DigiDollar::IdentifyScriptType(ddScript)))); - BOOST_CHECK_MESSAGE(state.IsValid(), "[mint_validation_valid_basic_mint] state invalid: " + state.GetRejectReason()); + BOOST_TEST_MESSAGE("mint_validation_valid_basic_mint result: " + std::to_string(result) + " reason: " + state.GetRejectReason()); + BOOST_CHECK(result); + BOOST_CHECK(state.IsValid()); } BOOST_FIXTURE_TEST_CASE(mint_validation_insufficient_collateral, DigiDollarValidationTestSetup) @@ -779,13 +799,8 @@ BOOST_FIXTURE_TEST_CASE(mint_validation_dca_multiplier_adjustment, DigiDollarVal TxValidationState state; // Should pass with adjusted collateral - bool result = DigiDollar::ValidateDigiDollarTransaction(tx, validationContext, state); - BOOST_CHECK_MESSAGE(result, "[mint_validation_dca_multiplier] Expected valid, got reject: " + state.GetRejectReason() - + " | systemCollateral=" + std::to_string(validationContext.systemCollateral) - + " adjustedCollateral=" + std::to_string(adjustedCollateral) - + " collateralType=" + std::to_string(static_cast(DigiDollar::IdentifyScriptType(collateralScript))) - + " ddType=" + std::to_string(static_cast(DigiDollar::IdentifyScriptType(ddScript)))); - BOOST_CHECK_MESSAGE(state.IsValid(), "[mint_validation_dca_multiplier] state invalid: " + state.GetRejectReason()); + BOOST_CHECK(DigiDollar::ValidateDigiDollarTransaction(tx, validationContext, state)); + BOOST_CHECK(state.IsValid()); // Test with original 500% collateral - should fail CAmount originalCollateral = (static_cast(ddAmount) * COIN * 500 * 100) / mockOraclePrice; @@ -962,13 +977,8 @@ BOOST_FIXTURE_TEST_CASE(mint_validation_edge_case_exact_minimum, DigiDollarValid CTransaction tx(mtx); TxValidationState state; - bool result = DigiDollar::ValidateDigiDollarTransaction(tx, validationContext, state); - BOOST_CHECK_MESSAGE(result, "[mint_validation_edge_case_exact_minimum] Expected valid, got reject: " + state.GetRejectReason() - + " | ddAmount=" + std::to_string(ddAmount) - + " exactCollateral=" + std::to_string(exactCollateral) - + " collateralType=" + std::to_string(static_cast(DigiDollar::IdentifyScriptType(collateralScript))) - + " ddType=" + std::to_string(static_cast(DigiDollar::IdentifyScriptType(ddScript)))); - BOOST_CHECK_MESSAGE(state.IsValid(), "[mint_validation_edge_case_exact_minimum] state invalid: " + state.GetRejectReason()); + BOOST_CHECK(DigiDollar::ValidateDigiDollarTransaction(tx, validationContext, state)); + BOOST_CHECK(state.IsValid()); } BOOST_FIXTURE_TEST_CASE(mint_validation_edge_case_exact_maximum, DigiDollarValidationTestSetup) @@ -1013,13 +1023,8 @@ BOOST_FIXTURE_TEST_CASE(mint_validation_edge_case_exact_maximum, DigiDollarValid CTransaction tx(mtx); TxValidationState state; - bool result = DigiDollar::ValidateDigiDollarTransaction(tx, validationContext, state); - BOOST_CHECK_MESSAGE(result, "[mint_validation_edge_case_exact_maximum] Expected valid, got reject: " + state.GetRejectReason() - + " | ddAmount=" + std::to_string(ddAmount) - + " requiredCollateral=" + std::to_string(requiredCollateral) - + " collateralType=" + std::to_string(static_cast(DigiDollar::IdentifyScriptType(collateralScript))) - + " ddType=" + std::to_string(static_cast(DigiDollar::IdentifyScriptType(ddScript)))); - BOOST_CHECK_MESSAGE(state.IsValid(), "[mint_validation_edge_case_exact_maximum] state invalid: " + state.GetRejectReason()); + BOOST_CHECK(DigiDollar::ValidateDigiDollarTransaction(tx, validationContext, state)); + BOOST_CHECK(state.IsValid()); } // ============================================================================= From 7ee010aefd8b5dd468ba6754a80f52a1b68b9d3c Mon Sep 17 00:00:00 2001 From: GTO90 Date: Fri, 13 Feb 2026 15:41:31 -0600 Subject: [PATCH 9/9] test: fix undefined behavior in redteam mixed-inputs test MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The test at line 4133 created two separate temporary XOnlyPubKey objects — one for .begin() and another for .end() — producing iterators into different memory regions. This is undefined behavior that manifests as std::length_error on some platforms. Fix: create a named XOnlyPubKey variable and use the existing MakeP2TR() helper instead of manual CScript construction. --- src/test/digidollar_redteam_tests.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/test/digidollar_redteam_tests.cpp b/src/test/digidollar_redteam_tests.cpp index 6ab2440011..79d4b46c26 100644 --- a/src/test/digidollar_redteam_tests.cpp +++ b/src/test/digidollar_redteam_tests.cpp @@ -4130,9 +4130,8 @@ BOOST_AUTO_TEST_CASE(redteam_t2_02g_mixed_dd_and_regular_inputs) CMutableTransaction feeTx; feeTx.nVersion = 2; // Regular Bitcoin version feeTx.vin.push_back(CTxIn(COutPoint(uint256S("ccdd020200000000000000000000000000000000000000000000000000000001"), 0))); - feeTx.vout.push_back(CTxOut(1 * COIN, CScript() << OP_1 << std::vector(feeKey.GetPubKey().IsCompressed() ? - std::vector(XOnlyPubKey(feeKey.GetPubKey()).begin(), XOnlyPubKey(feeKey.GetPubKey()).end()) : - std::vector(32, 0)))); + XOnlyPubKey feeXOnly(feeKey.GetPubKey()); + feeTx.vout.push_back(CTxOut(1 * COIN, MakeP2TR(feeXOnly))); CTransactionRef feeTxRef = MakeTransactionRef(feeTx); uint256 feeTxHash = feeTxRef->GetHash();