Skip to content

Commit 16bc930

Browse files
test(drive): add comprehensive tests for state_transition_action module (#3229)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 737d3b3 commit 16bc930

61 files changed

Lines changed: 11330 additions & 8 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎packages/rs-drive-proof-verifier/src/proof.rs‎

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2458,9 +2458,12 @@ impl FromProof<platform::GetMostRecentShieldedAnchorRequest> for MostRecentShiel
24582458
let proof = response.proof().or(Err(Error::NoProofInResult))?;
24592459
let mtd = response.metadata().or(Err(Error::EmptyResponseMetadata))?;
24602460

2461-
let (root_hash, maybe_anchor) =
2462-
Drive::verify_most_recent_shielded_anchor(&proof.grovedb_proof, false, platform_version)
2463-
.map_drive_error(proof, mtd)?;
2461+
let (root_hash, maybe_anchor) = Drive::verify_most_recent_shielded_anchor(
2462+
&proof.grovedb_proof,
2463+
false,
2464+
platform_version,
2465+
)
2466+
.map_drive_error(proof, mtd)?;
24642467

24652468
verify_tenderdash_proof(proof, mtd, &root_hash, provider)?;
24662469

@@ -2576,11 +2579,12 @@ impl FromProof<platform::GetShieldedNullifiersRequest> for ShieldedNullifierStat
25762579
statuses
25772580
.into_iter()
25782581
.map(|(nullifier, is_spent)| {
2579-
let nullifier: [u8; 32] = nullifier.try_into().map_err(|_| {
2580-
Error::ResultEncodingError {
2581-
error: "nullifier from Drive proof is not 32 bytes".to_string(),
2582-
}
2583-
})?;
2582+
let nullifier: [u8; 32] =
2583+
nullifier
2584+
.try_into()
2585+
.map_err(|_| Error::ResultEncodingError {
2586+
error: "nullifier from Drive proof is not 32 bytes".to_string(),
2587+
})?;
25842588
Ok(ShieldedNullifierStatus {
25852589
nullifier,
25862590
is_spent,

‎packages/rs-drive/src/state_transition_action/action_convert_to_operations/address_funds/address_credit_withdrawal_transition.rs‎

Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,3 +82,161 @@ impl DriveHighLevelOperationConverter for AddressCreditWithdrawalTransitionActio
8282
}
8383
}
8484
}
85+
86+
#[cfg(test)]
87+
mod tests {
88+
use super::*;
89+
use crate::state_transition_action::address_funds::address_credit_withdrawal::v0::AddressCreditWithdrawalTransitionActionV0;
90+
use dpp::address_funds::PlatformAddress;
91+
use dpp::block::epoch::Epoch;
92+
use dpp::document::{Document, DocumentV0};
93+
use dpp::prelude::Identifier;
94+
use dpp::version::PlatformVersion;
95+
use std::collections::BTreeMap;
96+
97+
fn make_document() -> Document {
98+
Document::V0(DocumentV0 {
99+
id: Identifier::from([0x11; 32]),
100+
owner_id: Identifier::from([0x22; 32]),
101+
properties: Default::default(),
102+
revision: Some(1),
103+
created_at: None,
104+
updated_at: None,
105+
transferred_at: None,
106+
created_at_block_height: None,
107+
updated_at_block_height: None,
108+
transferred_at_block_height: None,
109+
created_at_core_block_height: None,
110+
updated_at_core_block_height: None,
111+
transferred_at_core_block_height: None,
112+
creator_id: None,
113+
})
114+
}
115+
116+
fn make_action_with_output() -> AddressCreditWithdrawalTransitionAction {
117+
let addr_a = PlatformAddress::P2pkh([0xAA; 20]);
118+
let addr_b = PlatformAddress::P2sh([0xCC; 20]);
119+
120+
let mut inputs = BTreeMap::new();
121+
inputs.insert(addr_a, (5_u32, 10000_u64));
122+
123+
AddressCreditWithdrawalTransitionAction::V0(AddressCreditWithdrawalTransitionActionV0 {
124+
inputs_with_remaining_balance: inputs,
125+
output: Some((addr_b, 2000)),
126+
fee_strategy: vec![],
127+
user_fee_increase: 0,
128+
prepared_withdrawal_document: make_document(),
129+
amount: 8000,
130+
})
131+
}
132+
133+
fn make_action_no_output() -> AddressCreditWithdrawalTransitionAction {
134+
let addr_a = PlatformAddress::P2pkh([0xAA; 20]);
135+
136+
let mut inputs = BTreeMap::new();
137+
inputs.insert(addr_a, (5_u32, 2000_u64));
138+
139+
AddressCreditWithdrawalTransitionAction::V0(AddressCreditWithdrawalTransitionActionV0 {
140+
inputs_with_remaining_balance: inputs,
141+
output: None,
142+
fee_strategy: vec![],
143+
user_fee_increase: 0,
144+
prepared_withdrawal_document: make_document(),
145+
amount: 8000,
146+
})
147+
}
148+
149+
#[test]
150+
fn test_with_output_produces_correct_operation_count() {
151+
let action = make_action_with_output();
152+
let epoch = Epoch::new(0).unwrap();
153+
let platform_version = PlatformVersion::latest();
154+
155+
let ops = action
156+
.into_high_level_drive_operations(&epoch, platform_version)
157+
.expect("expected operations");
158+
159+
// SetBalanceToAddress (1 input) + AddBalanceToAddress (output)
160+
// + AddWithdrawalDocument + RemoveFromSystemCredits
161+
assert_eq!(ops.len(), 4);
162+
}
163+
164+
#[test]
165+
fn test_without_output_produces_correct_operation_count() {
166+
let action = make_action_no_output();
167+
let epoch = Epoch::new(0).unwrap();
168+
let platform_version = PlatformVersion::latest();
169+
170+
let ops = action
171+
.into_high_level_drive_operations(&epoch, platform_version)
172+
.expect("expected operations");
173+
174+
// SetBalanceToAddress (1 input) + AddWithdrawalDocument + RemoveFromSystemCredits
175+
assert_eq!(ops.len(), 3);
176+
}
177+
178+
#[test]
179+
fn test_input_balances_are_set() {
180+
let action = make_action_with_output();
181+
let epoch = Epoch::new(0).unwrap();
182+
let platform_version = PlatformVersion::latest();
183+
184+
let ops = action
185+
.into_high_level_drive_operations(&epoch, platform_version)
186+
.expect("expected operations");
187+
188+
match &ops[0] {
189+
AddressFundsOperation(AddressFundsOperationType::SetBalanceToAddress {
190+
address,
191+
nonce,
192+
balance,
193+
}) => {
194+
assert_eq!(*address, PlatformAddress::P2pkh([0xAA; 20]));
195+
assert_eq!(*nonce, 5);
196+
assert_eq!(*balance, 10000);
197+
}
198+
other => panic!("expected SetBalanceToAddress, got {:?}", other),
199+
}
200+
}
201+
202+
#[test]
203+
fn test_system_credits_removal_matches_amount() {
204+
let action = make_action_with_output();
205+
let epoch = Epoch::new(0).unwrap();
206+
let platform_version = PlatformVersion::latest();
207+
208+
let ops = action
209+
.into_high_level_drive_operations(&epoch, platform_version)
210+
.expect("expected operations");
211+
212+
let last = ops.last().unwrap();
213+
match last {
214+
SystemOperation(SystemOperationType::RemoveFromSystemCredits { amount }) => {
215+
assert_eq!(*amount, 8000);
216+
}
217+
other => panic!("expected RemoveFromSystemCredits, got {:?}", other),
218+
}
219+
}
220+
221+
#[test]
222+
fn test_has_withdrawal_document_operation() {
223+
let action = make_action_with_output();
224+
let epoch = Epoch::new(0).unwrap();
225+
let platform_version = PlatformVersion::latest();
226+
227+
let ops = action
228+
.into_high_level_drive_operations(&epoch, platform_version)
229+
.expect("expected operations");
230+
231+
let has_withdrawal_doc = ops.iter().any(|op| {
232+
matches!(
233+
op,
234+
DocumentOperation(DocumentOperationType::AddWithdrawalDocument { .. })
235+
)
236+
});
237+
assert!(
238+
has_withdrawal_doc,
239+
"expected AddWithdrawalDocument operation"
240+
);
241+
}
242+
}

‎packages/rs-drive/src/state_transition_action/action_convert_to_operations/address_funds/address_funding_from_asset_lock_transition.rs‎

Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,3 +89,139 @@ impl DriveHighLevelOperationConverter for AddressFundingFromAssetLockTransitionA
8989
}
9090
}
9191
}
92+
93+
#[cfg(test)]
94+
mod tests {
95+
use super::*;
96+
use crate::state_transition_action::address_funds::address_funding_from_asset_lock::v0::AddressFundingFromAssetLockTransitionActionV0;
97+
use dpp::address_funds::PlatformAddress;
98+
use dpp::asset_lock::reduced_asset_lock_value::AssetLockValue;
99+
use dpp::block::epoch::Epoch;
100+
use dpp::platform_value::Bytes36;
101+
use dpp::state_transition::signable_bytes_hasher::SignableBytesHasher;
102+
use dpp::version::PlatformVersion;
103+
use std::collections::BTreeMap;
104+
105+
fn make_asset_lock_value(remaining: u64) -> AssetLockValue {
106+
AssetLockValue::new(
107+
remaining + 1000,
108+
vec![0xDE, 0xAD],
109+
remaining,
110+
vec![],
111+
PlatformVersion::latest(),
112+
)
113+
.expect("should create AssetLockValue")
114+
}
115+
116+
fn make_action() -> AddressFundingFromAssetLockTransitionAction {
117+
let addr_input = PlatformAddress::P2pkh([0xAA; 20]);
118+
let addr_explicit = PlatformAddress::P2pkh([0xBB; 20]);
119+
let addr_remainder = PlatformAddress::P2sh([0xCC; 20]);
120+
121+
let mut inputs = BTreeMap::new();
122+
inputs.insert(addr_input, (1_u32, 2000_u64));
123+
124+
let mut outputs = BTreeMap::new();
125+
outputs.insert(addr_explicit, Some(3000_u64));
126+
outputs.insert(addr_remainder, None);
127+
128+
AddressFundingFromAssetLockTransitionAction::V0(
129+
AddressFundingFromAssetLockTransitionActionV0 {
130+
signable_bytes_hasher: SignableBytesHasher::Bytes(vec![0xFF; 8]),
131+
asset_lock_value_to_be_consumed: make_asset_lock_value(5000),
132+
asset_lock_outpoint: Bytes36([0xDD; 36]),
133+
inputs_with_remaining_balance: inputs,
134+
outputs,
135+
input_contributions_total: 2000,
136+
fee_strategy: vec![],
137+
user_fee_increase: 0,
138+
},
139+
)
140+
}
141+
142+
#[test]
143+
fn test_produces_system_input_and_output_operations() {
144+
let action = make_action();
145+
let epoch = Epoch::new(0).unwrap();
146+
let platform_version = PlatformVersion::latest();
147+
148+
let ops = action
149+
.into_high_level_drive_operations(&epoch, platform_version)
150+
.expect("expected operations");
151+
152+
// AddToSystemCredits + AddUsedAssetLock + SetBalanceToAddress (1 input)
153+
// + AddBalanceToAddress (explicit) + AddBalanceToAddress (remainder)
154+
assert_eq!(ops.len(), 5);
155+
}
156+
157+
#[test]
158+
fn test_first_op_is_add_to_system_credits() {
159+
let action = make_action();
160+
let epoch = Epoch::new(0).unwrap();
161+
let platform_version = PlatformVersion::latest();
162+
163+
let ops = action
164+
.into_high_level_drive_operations(&epoch, platform_version)
165+
.expect("expected operations");
166+
167+
match &ops[0] {
168+
DriveOperation::SystemOperation(SystemOperationType::AddToSystemCredits { amount }) => {
169+
assert_eq!(*amount, 5000); // remaining asset lock value
170+
}
171+
other => panic!("expected AddToSystemCredits, got {:?}", other),
172+
}
173+
}
174+
175+
#[test]
176+
fn test_second_op_is_add_used_asset_lock() {
177+
let action = make_action();
178+
let epoch = Epoch::new(0).unwrap();
179+
let platform_version = PlatformVersion::latest();
180+
181+
let ops = action
182+
.into_high_level_drive_operations(&epoch, platform_version)
183+
.expect("expected operations");
184+
185+
match &ops[1] {
186+
DriveOperation::SystemOperation(SystemOperationType::AddUsedAssetLock {
187+
asset_lock_outpoint,
188+
asset_lock_value,
189+
}) => {
190+
assert_eq!(*asset_lock_outpoint, Bytes36([0xDD; 36]));
191+
// remaining should be 0 after consumption
192+
use dpp::asset_lock::reduced_asset_lock_value::AssetLockValueGettersV0;
193+
assert_eq!(asset_lock_value.remaining_credit_value(), 0);
194+
}
195+
other => panic!("expected AddUsedAssetLock, got {:?}", other),
196+
}
197+
}
198+
199+
#[test]
200+
fn test_no_inputs_produces_only_system_and_output_ops() {
201+
let addr_output = PlatformAddress::P2pkh([0xBB; 20]);
202+
let mut outputs = BTreeMap::new();
203+
outputs.insert(addr_output, Some(5000_u64));
204+
205+
let action = AddressFundingFromAssetLockTransitionAction::V0(
206+
AddressFundingFromAssetLockTransitionActionV0 {
207+
signable_bytes_hasher: SignableBytesHasher::Bytes(vec![]),
208+
asset_lock_value_to_be_consumed: make_asset_lock_value(5000),
209+
asset_lock_outpoint: Bytes36([0xDD; 36]),
210+
inputs_with_remaining_balance: BTreeMap::new(),
211+
outputs,
212+
input_contributions_total: 0,
213+
fee_strategy: vec![],
214+
user_fee_increase: 0,
215+
},
216+
);
217+
let epoch = Epoch::new(0).unwrap();
218+
let platform_version = PlatformVersion::latest();
219+
220+
let ops = action
221+
.into_high_level_drive_operations(&epoch, platform_version)
222+
.expect("expected operations");
223+
224+
// AddToSystemCredits + AddUsedAssetLock + AddBalanceToAddress
225+
assert_eq!(ops.len(), 3);
226+
}
227+
}

0 commit comments

Comments
 (0)