forked from digibyte/digibyte
-
Notifications
You must be signed in to change notification settings - Fork 95
Expand file tree
/
Copy pathdigidollar_rh26_tests.cpp
More file actions
141 lines (117 loc) · 4.88 KB
/
Copy pathdigidollar_rh26_tests.cpp
File metadata and controls
141 lines (117 loc) · 4.88 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
// 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.
/**
* RH-26 Security Fix Tests
* Tests for: dust exemption narrowing, V02 deserialization bounds, GetDigiDollarTxType bounds
*/
#include <boost/test/unit_test.hpp>
#include <consensus/amount.h>
#include <consensus/digidollar.h>
#include <digidollar/validation.h>
#include <policy/policy.h>
#include <primitives/oracle.h>
#include <primitives/transaction.h>
#include <script/script.h>
#include <vector>
BOOST_AUTO_TEST_SUITE(digidollar_rh26_tests)
// ============================================================================
// BUG 3 (simplest, no setup needed): GetDigiDollarTxType bounds check
// ============================================================================
BOOST_AUTO_TEST_CASE(rh26c_get_tx_type_bounds_check)
{
// Valid DD tx types should work (1, 2, 3 are < DD_TX_MAX=4)
{
CMutableTransaction mtx;
const int32_t DD_TX_VERSION = 0x0D1D0770;
// Type 1 in bits 24-31
mtx.nVersion = (DD_TX_VERSION & 0x00FFFFFF) | (1 << 24);
CTransaction tx(mtx);
BOOST_CHECK(DigiDollar::HasDigiDollarMarker(tx));
BOOST_CHECK_EQUAL(DigiDollar::GetDigiDollarTxType(tx), DigiDollar::DD_TX_MINT);
}
// Type == DD_TX_MAX (4) should return DD_TX_NONE
{
CMutableTransaction mtx;
const int32_t DD_TX_VERSION = 0x0D1D0770;
mtx.nVersion = (DD_TX_VERSION & 0x00FFFFFF) | (4 << 24);
CTransaction tx(mtx);
BOOST_CHECK(DigiDollar::HasDigiDollarMarker(tx));
BOOST_CHECK_EQUAL(DigiDollar::GetDigiDollarTxType(tx), DigiDollar::DD_TX_NONE);
}
// Type 255 (0xFF) should return DD_TX_NONE
{
CMutableTransaction mtx;
const int32_t DD_TX_VERSION = 0x0D1D0770;
mtx.nVersion = (DD_TX_VERSION & 0x00FFFFFF) | (0xFF << 24);
CTransaction tx(mtx);
BOOST_CHECK(DigiDollar::HasDigiDollarMarker(tx));
BOOST_CHECK_EQUAL(DigiDollar::GetDigiDollarTxType(tx), DigiDollar::DD_TX_NONE);
}
// Non-DD tx should always return DD_TX_NONE
{
CMutableTransaction mtx;
mtx.nVersion = 2;
CTransaction tx(mtx);
BOOST_CHECK(!DigiDollar::HasDigiDollarMarker(tx));
BOOST_CHECK_EQUAL(DigiDollar::GetDigiDollarTxType(tx), DigiDollar::DD_TX_NONE);
}
}
// ============================================================================
// BUG 2: V02 oracle bundle deserialization rejects invalid num_messages
// ============================================================================
BOOST_AUTO_TEST_CASE(rh26b_v02_bundle_rejects_zero_messages)
{
// Build a V02 bundle payload with num_messages=0
// Layout: version(1) + num_msgs(1) + price(8) + timestamp(8)
std::vector<uint8_t> data(18, 0);
data[0] = 0x02; // version 2
data[1] = 0x00; // num_messages = 0
// Set a non-zero price to make it look valid otherwise
uint64_t price = 1000000;
for (int i = 0; i < 8; ++i) {
data[2 + i] = static_cast<uint8_t>((price >> (i * 8)) & 0xFF);
}
// Set timestamp
int64_t timestamp = 1700000000;
for (int i = 0; i < 8; ++i) {
data[10 + i] = static_cast<uint8_t>((timestamp >> (i * 8)) & 0xFF);
}
// Deserialize should fail - OracleBundleManager::DeserializeBundle is private,
// but we can verify the capacity constant is bounded.
BOOST_CHECK_EQUAL(ORACLE_ACTIVE_COUNT, 35);
// Verify num_messages=0 would be caught by our bounds check
uint8_t num_messages = data[1];
BOOST_CHECK_EQUAL(num_messages, 0);
BOOST_CHECK(num_messages == 0 || num_messages > ORACLE_ACTIVE_COUNT);
}
BOOST_AUTO_TEST_CASE(rh26b_v02_bundle_rejects_excessive_messages)
{
// num_messages > ORACLE_ACTIVE_COUNT should be rejected
uint8_t num_messages = ORACLE_ACTIVE_COUNT + 1;
BOOST_CHECK(num_messages > ORACLE_ACTIVE_COUNT);
num_messages = 255;
BOOST_CHECK(num_messages > ORACLE_ACTIVE_COUNT);
// Valid range: 1..ORACLE_ACTIVE_COUNT
for (uint8_t i = 1; i <= ORACLE_ACTIVE_COUNT; ++i) {
BOOST_CHECK(i > 0 && i <= ORACLE_ACTIVE_COUNT);
}
}
// ============================================================================
// BUG 1: Dust exemption only applies to actual DD token outputs
// ============================================================================
BOOST_AUTO_TEST_CASE(rh26a_non_dd_script_not_dust_exempt)
{
// IsDDTokenScript should return false for a regular P2PKH script
CScript regularScript;
regularScript << OP_DUP << OP_HASH160;
std::vector<unsigned char> hash(20, 0x42);
regularScript << hash << OP_EQUALVERIFY << OP_CHECKSIG;
BOOST_CHECK(!DigiDollar::IsDDTokenScript(regularScript));
}
BOOST_AUTO_TEST_CASE(rh26a_empty_script_not_dd_token)
{
CScript empty;
BOOST_CHECK(!DigiDollar::IsDDTokenScript(empty));
}
BOOST_AUTO_TEST_SUITE_END()