1use crate::core::ledger_objects::{current_ledger_object, ledger_object};
2use crate::core::types::account_id::AccountID;
3use crate::core::types::amount::Amount;
4use crate::core::types::blob::{CONDITION_BLOB_SIZE, ConditionBlob, StandardBlob};
5use crate::core::types::contract_data::{ContractData, XRPL_CONTRACT_DATA_SIZE};
6use crate::core::types::uint::{Hash128, Hash256};
7
8use crate::host::error_codes::{match_result_code, match_result_code_optional};
14use crate::host::{Error, get_current_ledger_obj_field, get_ledger_obj_field, update_data};
15use crate::host::{Result, Result::Err, Result::Ok};
16use crate::sfield;
17
18pub trait LedgerObjectCommonFields {
23 fn get_slot_num(&self) -> i32;
36
37 fn get_flags(&self) -> Result<u32> {
47 ledger_object::get_field(self.get_slot_num(), sfield::Flags)
48 }
49
50 fn get_ledger_entry_type(&self) -> Result<u16> {
58 ledger_object::get_field(self.get_slot_num(), sfield::LedgerEntryType)
59 }
60}
61
62pub trait CurrentLedgerObjectCommonFields {
68 fn get_flags(&self) -> Result<u32> {
78 current_ledger_object::get_field(sfield::Flags)
79 }
80
81 fn get_ledger_entry_type(&self) -> Result<u16> {
89 current_ledger_object::get_field(sfield::LedgerEntryType)
90 }
91}
92
93pub trait CurrentEscrowFields: CurrentLedgerObjectCommonFields {
98 fn get_account(&self) -> Result<AccountID> {
101 current_ledger_object::get_field(sfield::Account)
102 }
103
104 fn get_amount(&self) -> Result<Amount> {
106 current_ledger_object::get_field(sfield::Amount)
107 }
108
109 fn get_cancel_after(&self) -> Result<Option<u32>> {
113 current_ledger_object::get_field_optional(sfield::CancelAfter)
114 }
115
116 fn get_condition(&self) -> Result<Option<ConditionBlob>> {
119 let mut buffer = ConditionBlob::new();
120
121 let result_code = unsafe {
122 get_current_ledger_obj_field(
123 sfield::Condition.into(),
124 buffer.data.as_mut_ptr(),
125 buffer.capacity(),
126 )
127 };
128
129 match_result_code_optional(result_code, || {
130 buffer.len = result_code as usize;
131 (result_code > 0).then_some(buffer)
132 })
133 }
134
135 fn get_destination(&self) -> Result<AccountID> {
137 current_ledger_object::get_field(sfield::Destination)
138 }
139
140 fn get_destination_node(&self) -> Result<Option<u64>> {
143 current_ledger_object::get_field_optional(sfield::DestinationNode)
144 }
145
146 fn get_destination_tag(&self) -> Result<Option<u32>> {
149 current_ledger_object::get_field_optional(sfield::DestinationTag)
150 }
151
152 fn get_finish_after(&self) -> Result<Option<u32>> {
156 current_ledger_object::get_field_optional(sfield::FinishAfter)
157 }
158
159 fn get_owner_node(&self) -> Result<u64> {
168 current_ledger_object::get_field(sfield::OwnerNode)
169 }
170
171 fn get_previous_txn_id(&self) -> Result<Hash256> {
173 current_ledger_object::get_field(sfield::PreviousTxnID)
174 }
175
176 fn get_previous_txn_lgr_seq(&self) -> Result<u32> {
179 current_ledger_object::get_field(sfield::PreviousTxnLgrSeq)
180 }
181
182 fn get_source_tag(&self) -> Result<Option<u32>> {
185 current_ledger_object::get_field_optional(sfield::SourceTag)
186 }
187
188 fn get_finish_function(&self) -> Result<Option<StandardBlob>> {
190 current_ledger_object::get_field_optional(sfield::FinishFunction)
191 }
192
193 fn get_data(&self) -> Result<ContractData> {
204 let mut data: [u8; XRPL_CONTRACT_DATA_SIZE] = [0; XRPL_CONTRACT_DATA_SIZE];
205
206 let result_code = unsafe {
207 get_current_ledger_obj_field(sfield::Data.into(), data.as_mut_ptr(), data.len())
208 };
209
210 match result_code {
211 code if code >= 0 => Ok(ContractData {
212 data,
213 len: code as usize,
214 }),
215 code => Err(Error::from_code(code)),
216 }
217 }
218
219 fn update_current_escrow_data(data: ContractData) -> Result<()> {
231 let result_code = unsafe { update_data(data.data.as_ptr(), data.len) };
235 match_result_code(result_code, || ())
236 }
237}
238
239pub trait EscrowFields: LedgerObjectCommonFields {
245 fn get_account(&self) -> Result<AccountID> {
248 ledger_object::get_field(self.get_slot_num(), sfield::Account)
249 }
250
251 fn get_amount(&self) -> Result<Amount> {
253 const BUFFER_SIZE: usize = 48usize;
255 let mut buffer = [0u8; BUFFER_SIZE];
256
257 let result_code = unsafe {
258 get_ledger_obj_field(
259 self.get_slot_num(),
260 sfield::Amount.into(),
261 buffer.as_mut_ptr(),
262 buffer.len(),
263 )
264 };
265
266 match_result_code(result_code, || Amount::from(buffer))
267 }
268
269 fn get_cancel_after(&self) -> Result<Option<u32>> {
273 ledger_object::get_field_optional(self.get_slot_num(), sfield::CancelAfter)
274 }
275
276 fn get_condition(&self) -> Result<Option<ConditionBlob>> {
279 let mut buffer = [0u8; CONDITION_BLOB_SIZE];
280
281 let result_code = unsafe {
282 get_ledger_obj_field(
283 self.get_slot_num(),
284 sfield::Condition.into(),
285 buffer.as_mut_ptr(),
286 buffer.len(),
287 )
288 };
289
290 match_result_code_optional(result_code, || {
291 if result_code > 0 {
292 let blob = ConditionBlob {
293 data: buffer,
294 len: result_code as usize,
295 };
296 Some(blob)
297 } else {
298 None
299 }
300 })
301 }
302
303 fn get_destination(&self) -> Result<AccountID> {
305 ledger_object::get_field(self.get_slot_num(), sfield::Destination)
306 }
307
308 fn get_destination_node(&self) -> Result<Option<u64>> {
311 ledger_object::get_field_optional(self.get_slot_num(), sfield::DestinationNode)
312 }
313
314 fn get_destination_tag(&self) -> Result<Option<u32>> {
317 ledger_object::get_field_optional(self.get_slot_num(), sfield::DestinationTag)
318 }
319
320 fn get_finish_after(&self) -> Result<Option<u32>> {
324 ledger_object::get_field_optional(self.get_slot_num(), sfield::FinishAfter)
325 }
326
327 fn get_owner_node(&self) -> Result<u64> {
336 ledger_object::get_field(self.get_slot_num(), sfield::OwnerNode)
337 }
338
339 fn get_previous_txn_id(&self) -> Result<Hash256> {
341 ledger_object::get_field(self.get_slot_num(), sfield::PreviousTxnID)
342 }
343
344 fn get_previous_txn_lgr_seq(&self) -> Result<u32> {
347 ledger_object::get_field(self.get_slot_num(), sfield::PreviousTxnLgrSeq)
348 }
349
350 fn get_source_tag(&self) -> Result<Option<u32>> {
353 ledger_object::get_field_optional(self.get_slot_num(), sfield::SourceTag)
354 }
355
356 fn get_finish_function(&self) -> Result<Option<StandardBlob>> {
358 ledger_object::get_field_optional(self.get_slot_num(), sfield::FinishFunction)
359 }
360
361 fn get_data(&self) -> Result<ContractData> {
377 let mut data: [u8; XRPL_CONTRACT_DATA_SIZE] = [0; XRPL_CONTRACT_DATA_SIZE];
378
379 let result_code = unsafe {
380 get_ledger_obj_field(
381 self.get_slot_num(),
382 sfield::Data.into(),
383 data.as_mut_ptr(),
384 data.len(),
385 )
386 };
387
388 match result_code {
389 code if code >= 0 => Ok(ContractData {
390 data,
391 len: code as usize,
392 }),
393 code => Err(Error::from_code(code)),
394 }
395 }
396}
397
398pub trait AccountFields: LedgerObjectCommonFields {
404 fn get_account(&self) -> Result<AccountID> {
406 ledger_object::get_field(self.get_slot_num(), sfield::Account)
407 }
408
409 fn account_txn_id(&self) -> Result<Option<Hash256>> {
411 ledger_object::get_field_optional(self.get_slot_num(), sfield::AccountTxnID)
412 }
413
414 fn amm_id(&self) -> Result<Option<Hash256>> {
418 ledger_object::get_field_optional(self.get_slot_num(), sfield::AMMID)
419 }
420
421 fn balance(&self) -> Result<Option<Amount>> {
423 ledger_object::get_field_optional(self.get_slot_num(), sfield::Balance)
424 }
425
426 fn burned_nf_tokens(&self) -> Result<Option<u32>> {
429 ledger_object::get_field_optional(self.get_slot_num(), sfield::BurnedNFTokens)
430 }
431
432 fn domain(&self) -> Result<Option<StandardBlob>> {
435 ledger_object::get_field_optional(self.get_slot_num(), sfield::Domain)
436 }
437
438 fn email_hash(&self) -> Result<Option<Hash128>> {
440 ledger_object::get_field_optional(self.get_slot_num(), sfield::EmailHash)
441 }
442
443 fn first_nf_token_sequence(&self) -> Result<Option<u32>> {
446 ledger_object::get_field_optional(self.get_slot_num(), sfield::FirstNFTokenSequence)
447 }
448
449 fn ledger_entry_type(&self) -> Result<u16> {
451 ledger_object::get_field(self.get_slot_num(), sfield::LedgerEntryType)
452 }
453
454 fn message_key(&self) -> Result<Option<StandardBlob>> {
458 ledger_object::get_field_optional(self.get_slot_num(), sfield::MessageKey)
459 }
460
461 fn minted_nf_tokens(&self) -> Result<Option<u32>> {
464 ledger_object::get_field_optional(self.get_slot_num(), sfield::MintedNFTokens)
465 }
466
467 fn nf_token_minter(&self) -> Result<Option<AccountID>> {
470 ledger_object::get_field_optional(self.get_slot_num(), sfield::NFTokenMinter)
471 }
472
473 fn owner_count(&self) -> Result<u32> {
475 ledger_object::get_field(self.get_slot_num(), sfield::OwnerCount)
476 }
477
478 fn previous_txn_id(&self) -> Result<Hash256> {
480 ledger_object::get_field(self.get_slot_num(), sfield::PreviousTxnID)
481 }
482
483 fn previous_txn_lgr_seq(&self) -> Result<u32> {
485 ledger_object::get_field(self.get_slot_num(), sfield::PreviousTxnLgrSeq)
486 }
487
488 fn regular_key(&self) -> Result<Option<AccountID>> {
491 ledger_object::get_field_optional(self.get_slot_num(), sfield::RegularKey)
492 }
493
494 fn sequence(&self) -> Result<u32> {
496 ledger_object::get_field(self.get_slot_num(), sfield::Sequence)
497 }
498
499 fn ticket_count(&self) -> Result<Option<u32>> {
503 ledger_object::get_field_optional(self.get_slot_num(), sfield::TicketCount)
504 }
505
506 fn tick_size(&self) -> Result<Option<u8>> {
509 ledger_object::get_field_optional(self.get_slot_num(), sfield::TickSize)
510 }
511
512 fn transfer_rate(&self) -> Result<Option<u32>> {
514 ledger_object::get_field_optional(self.get_slot_num(), sfield::TransferRate)
515 }
516
517 fn wallet_locator(&self) -> Result<Option<Hash256>> {
519 ledger_object::get_field_optional(self.get_slot_num(), sfield::WalletLocator)
520 }
521}
522
523#[cfg(test)]
524mod tests {
525 use super::*;
526 use crate::core::ledger_objects::LedgerObjectFieldGetter;
527 use crate::core::ledger_objects::account_root::AccountRoot;
528 use crate::host::error_codes::{FIELD_NOT_FOUND, INTERNAL_ERROR, INVALID_FIELD};
529 use crate::host::host_bindings_trait::MockHostBindings;
530 use crate::sfield::SField;
531 use mockall::predicate::{always, eq};
532
533 fn expect_current_field<
546 T: LedgerObjectFieldGetter + Send + std::fmt::Debug + PartialEq + 'static,
547 const CODE: i32,
548 >(
549 mock: &mut MockHostBindings,
550 _field: SField<T, CODE>,
551 size: usize,
552 times: usize,
553 ) {
554 mock.expect_get_current_ledger_obj_field()
555 .with(eq(CODE), always(), eq(size))
556 .times(times)
557 .returning(move |_, _, _| size as i32);
558 }
559
560 fn expect_ledger_field<
570 T: LedgerObjectFieldGetter + Send + std::fmt::Debug + PartialEq + 'static,
571 const CODE: i32,
572 >(
573 mock: &mut MockHostBindings,
574 slot: i32,
575 _field: SField<T, CODE>,
576 size: usize,
577 times: usize,
578 ) {
579 mock.expect_get_ledger_obj_field()
580 .with(eq(slot), eq(CODE), always(), eq(size))
581 .times(times)
582 .returning(move |_, _, _, _| size as i32);
583 }
584
585 mod ledger_object_common_fields {
586 use super::*;
587 use crate::host::setup_mock;
588
589 #[test]
590 fn test_mandatory_fields_return_ok() {
591 let mut mock = MockHostBindings::new();
592
593 expect_ledger_field(&mut mock, 1, sfield::Flags, 4, 1);
595 expect_ledger_field(&mut mock, 1, sfield::LedgerEntryType, 2, 1);
597
598 let _guard = setup_mock(mock);
599
600 let account = AccountRoot { slot_num: 1 };
601
602 assert!(account.get_flags().is_ok());
604 assert!(account.get_ledger_entry_type().is_ok());
605 }
606
607 #[test]
608 fn test_mandatory_fields_return_error_on_internal_error() {
609 let mut mock = MockHostBindings::new();
610
611 mock.expect_get_ledger_obj_field()
613 .with(eq(1), eq(sfield::Flags), always(), eq(4))
614 .times(1)
615 .returning(|_, _, _, _| INTERNAL_ERROR);
616
617 let _guard = setup_mock(mock);
618
619 let account = AccountRoot { slot_num: 1 };
620 let result = account.get_flags();
621
622 assert!(result.is_err());
623 assert_eq!(result.err().unwrap().code(), INTERNAL_ERROR);
624 }
625
626 #[test]
627 fn test_get_ledger_entry_type_returns_error_on_internal_error() {
628 let mut mock = MockHostBindings::new();
629
630 mock.expect_get_ledger_obj_field()
631 .with(eq(1), eq(sfield::LedgerEntryType), always(), eq(2))
632 .times(1)
633 .returning(|_, _, _, _| INTERNAL_ERROR);
634
635 let _guard = setup_mock(mock);
636
637 let account = AccountRoot { slot_num: 1 };
638 let result = account.get_ledger_entry_type();
639
640 assert!(result.is_err());
641 assert_eq!(result.err().unwrap().code(), INTERNAL_ERROR);
642 }
643
644 #[test]
645 fn test_mandatory_fields_return_error_on_invalid_field() {
646 let mut mock = MockHostBindings::new();
647
648 mock.expect_get_ledger_obj_field()
650 .with(eq(1), eq(sfield::Flags), always(), eq(4))
651 .times(1)
652 .returning(|_, _, _, _| INVALID_FIELD);
653
654 let _guard = setup_mock(mock);
655
656 let account = AccountRoot { slot_num: 1 };
657 let result = account.get_flags();
658
659 assert!(result.is_err());
660 assert_eq!(result.err().unwrap().code(), INVALID_FIELD);
661 }
662 }
663
664 mod account_fields {
665 use super::*;
666 use crate::host::setup_mock;
667
668 #[test]
669 fn test_mandatory_fields_return_ok() {
670 let mut mock = MockHostBindings::new();
671
672 expect_ledger_field(&mut mock, 1, sfield::Account, 20, 1);
674 expect_ledger_field(&mut mock, 1, sfield::OwnerCount, 4, 1);
676 expect_ledger_field(&mut mock, 1, sfield::PreviousTxnID, 32, 1);
678 expect_ledger_field(&mut mock, 1, sfield::PreviousTxnLgrSeq, 4, 1);
680 expect_ledger_field(&mut mock, 1, sfield::Sequence, 4, 1);
682 expect_ledger_field(&mut mock, 1, sfield::LedgerEntryType, 2, 1);
684
685 let _guard = setup_mock(mock);
686
687 let account = AccountRoot { slot_num: 1 };
688
689 assert!(account.get_account().is_ok());
691 assert!(account.owner_count().is_ok());
692 assert!(account.previous_txn_id().is_ok());
693 assert!(account.previous_txn_lgr_seq().is_ok());
694 assert!(account.sequence().is_ok());
695 assert!(account.ledger_entry_type().is_ok());
696 }
697
698 #[test]
699 fn test_optional_fields_return_some() {
700 let mut mock = MockHostBindings::new();
701
702 expect_ledger_field(&mut mock, 1, sfield::AccountTxnID, 32, 1);
704 expect_ledger_field(&mut mock, 1, sfield::AMMID, 32, 1);
706 expect_ledger_field(&mut mock, 1, sfield::Balance, 48, 1);
708 expect_ledger_field(&mut mock, 1, sfield::BurnedNFTokens, 4, 1);
710 expect_ledger_field(&mut mock, 1, sfield::Domain, 1024, 1);
712 expect_ledger_field(&mut mock, 1, sfield::EmailHash, 16, 1);
714 expect_ledger_field(&mut mock, 1, sfield::FirstNFTokenSequence, 4, 1);
716 expect_ledger_field(&mut mock, 1, sfield::MessageKey, 1024, 1);
718 expect_ledger_field(&mut mock, 1, sfield::MintedNFTokens, 4, 1);
720 expect_ledger_field(&mut mock, 1, sfield::NFTokenMinter, 20, 1);
722 expect_ledger_field(&mut mock, 1, sfield::RegularKey, 20, 1);
724 expect_ledger_field(&mut mock, 1, sfield::TicketCount, 4, 1);
726 expect_ledger_field(&mut mock, 1, sfield::TickSize, 1, 1);
728 expect_ledger_field(&mut mock, 1, sfield::TransferRate, 4, 1);
730 expect_ledger_field(&mut mock, 1, sfield::WalletLocator, 32, 1);
732
733 let _guard = setup_mock(mock);
734
735 let account = AccountRoot { slot_num: 1 };
736
737 assert!(account.account_txn_id().unwrap().is_some());
739 assert!(account.amm_id().unwrap().is_some());
740 assert!(account.balance().unwrap().is_some());
741 assert!(account.burned_nf_tokens().unwrap().is_some());
742 assert!(account.domain().unwrap().is_some());
743 assert!(account.email_hash().unwrap().is_some());
744 assert!(account.first_nf_token_sequence().unwrap().is_some());
745 assert!(account.message_key().unwrap().is_some());
746 assert!(account.minted_nf_tokens().unwrap().is_some());
747 assert!(account.nf_token_minter().unwrap().is_some());
748 assert!(account.regular_key().unwrap().is_some());
749 assert!(account.ticket_count().unwrap().is_some());
750 assert!(account.tick_size().unwrap().is_some());
751 assert!(account.transfer_rate().unwrap().is_some());
752 assert!(account.wallet_locator().unwrap().is_some());
753 }
754
755 #[test]
756 fn test_optional_fields_return_none_when_field_not_found() {
757 let mut mock = MockHostBindings::new();
758
759 mock.expect_get_ledger_obj_field()
761 .with(eq(1), eq(sfield::AccountTxnID), always(), eq(32))
762 .times(1)
763 .returning(|_, _, _, _| FIELD_NOT_FOUND);
764 mock.expect_get_ledger_obj_field()
766 .with(eq(1), eq(sfield::AMMID), always(), eq(32))
767 .times(1)
768 .returning(|_, _, _, _| FIELD_NOT_FOUND);
769 mock.expect_get_ledger_obj_field()
771 .with(eq(1), eq(sfield::Balance), always(), eq(48))
772 .times(1)
773 .returning(|_, _, _, _| 0);
774 mock.expect_get_ledger_obj_field()
776 .with(eq(1), eq(sfield::BurnedNFTokens), always(), eq(4))
777 .times(1)
778 .returning(|_, _, _, _| FIELD_NOT_FOUND);
779 mock.expect_get_ledger_obj_field()
781 .with(eq(1), eq(sfield::Domain), always(), eq(1024))
782 .times(1)
783 .returning(|_, _, _, _| 0);
784 mock.expect_get_ledger_obj_field()
786 .with(eq(1), eq(sfield::EmailHash), always(), eq(16))
787 .times(1)
788 .returning(|_, _, _, _| FIELD_NOT_FOUND);
789 mock.expect_get_ledger_obj_field()
791 .with(eq(1), eq(sfield::FirstNFTokenSequence), always(), eq(4))
792 .times(1)
793 .returning(|_, _, _, _| FIELD_NOT_FOUND);
794 mock.expect_get_ledger_obj_field()
796 .with(eq(1), eq(sfield::MessageKey), always(), eq(1024))
797 .times(1)
798 .returning(|_, _, _, _| 0);
799 mock.expect_get_ledger_obj_field()
801 .with(eq(1), eq(sfield::MintedNFTokens), always(), eq(4))
802 .times(1)
803 .returning(|_, _, _, _| FIELD_NOT_FOUND);
804 mock.expect_get_ledger_obj_field()
806 .with(eq(1), eq(sfield::NFTokenMinter), always(), eq(20))
807 .times(1)
808 .returning(|_, _, _, _| FIELD_NOT_FOUND);
809 mock.expect_get_ledger_obj_field()
811 .with(eq(1), eq(sfield::RegularKey), always(), eq(20))
812 .times(1)
813 .returning(|_, _, _, _| FIELD_NOT_FOUND);
814 mock.expect_get_ledger_obj_field()
816 .with(eq(1), eq(sfield::TicketCount), always(), eq(4))
817 .times(1)
818 .returning(|_, _, _, _| FIELD_NOT_FOUND);
819 mock.expect_get_ledger_obj_field()
821 .with(eq(1), eq(sfield::TickSize), always(), eq(1))
822 .times(1)
823 .returning(|_, _, _, _| FIELD_NOT_FOUND);
824 mock.expect_get_ledger_obj_field()
826 .with(eq(1), eq(sfield::TransferRate), always(), eq(4))
827 .times(1)
828 .returning(|_, _, _, _| FIELD_NOT_FOUND);
829 mock.expect_get_ledger_obj_field()
831 .with(eq(1), eq(sfield::WalletLocator), always(), eq(32))
832 .times(1)
833 .returning(|_, _, _, _| FIELD_NOT_FOUND);
834
835 let _guard = setup_mock(mock);
836
837 let account = AccountRoot { slot_num: 1 };
838
839 assert!(account.account_txn_id().unwrap().is_none());
841 assert!(account.amm_id().unwrap().is_none());
842 assert!(account.burned_nf_tokens().unwrap().is_none());
843 assert!(account.email_hash().unwrap().is_none());
844 assert!(account.first_nf_token_sequence().unwrap().is_none());
845 assert!(account.minted_nf_tokens().unwrap().is_none());
846 assert!(account.nf_token_minter().unwrap().is_none());
847 assert!(account.regular_key().unwrap().is_none());
848 assert!(account.ticket_count().unwrap().is_none());
849 assert!(account.tick_size().unwrap().is_none());
850 assert!(account.transfer_rate().unwrap().is_none());
851 assert!(account.wallet_locator().unwrap().is_none());
852
853 let balance = account.balance().unwrap();
856 assert!(balance.is_some());
857 let domain = account.domain().unwrap();
858 assert!(domain.is_some());
859 assert_eq!(domain.unwrap().len, 0);
860 let message_key = account.message_key().unwrap();
861 assert!(message_key.is_some());
862 assert_eq!(message_key.unwrap().len, 0);
863 }
864
865 #[test]
866 fn test_mandatory_fields_return_error_on_internal_error() {
867 let mut mock = MockHostBindings::new();
868
869 mock.expect_get_ledger_obj_field()
871 .with(eq(1), eq(sfield::Account), always(), eq(20))
872 .times(1)
873 .returning(|_, _, _, _| INTERNAL_ERROR);
874
875 let _guard = setup_mock(mock);
876
877 let account = AccountRoot { slot_num: 1 };
878 let result = account.get_account();
879
880 assert!(result.is_err());
881 assert_eq!(result.err().unwrap().code(), INTERNAL_ERROR);
882 }
883
884 #[test]
885 fn test_mandatory_fields_return_error_on_invalid_field() {
886 let mut mock = MockHostBindings::new();
887
888 mock.expect_get_ledger_obj_field()
890 .with(eq(1), eq(sfield::Account), always(), eq(20))
891 .times(1)
892 .returning(|_, _, _, _| INVALID_FIELD);
893
894 let _guard = setup_mock(mock);
895
896 let account = AccountRoot { slot_num: 1 };
897 let result = account.get_account();
898
899 assert!(result.is_err());
900 assert_eq!(result.err().unwrap().code(), INVALID_FIELD);
901 }
902 }
903
904 mod current_ledger_object_common_fields {
905 use super::*;
906 use crate::core::ledger_objects::current_escrow::CurrentEscrow;
907 use crate::host::setup_mock;
908
909 #[test]
910 fn test_mandatory_fields_return_ok() {
911 let mut mock = MockHostBindings::new();
912
913 expect_current_field(&mut mock, sfield::Flags, 4, 1);
915 expect_current_field(&mut mock, sfield::LedgerEntryType, 2, 1);
917
918 let _guard = setup_mock(mock);
919
920 let escrow = CurrentEscrow;
921
922 assert!(escrow.get_flags().is_ok());
924 assert!(escrow.get_ledger_entry_type().is_ok());
925 }
926
927 #[test]
928 fn test_mandatory_fields_return_error_on_internal_error() {
929 let mut mock = MockHostBindings::new();
930
931 mock.expect_get_current_ledger_obj_field()
933 .with(eq(sfield::Flags), always(), eq(4))
934 .times(1)
935 .returning(|_, _, _| INTERNAL_ERROR);
936
937 let _guard = setup_mock(mock);
938
939 let escrow = CurrentEscrow;
940 let result = escrow.get_flags();
941
942 assert!(result.is_err());
943 assert_eq!(result.err().unwrap().code(), INTERNAL_ERROR);
944 }
945
946 #[test]
947 fn test_get_ledger_entry_type_returns_error_on_internal_error() {
948 let mut mock = MockHostBindings::new();
949
950 mock.expect_get_current_ledger_obj_field()
951 .with(eq(sfield::LedgerEntryType), always(), eq(2))
952 .times(1)
953 .returning(|_, _, _| INTERNAL_ERROR);
954
955 let _guard = setup_mock(mock);
956
957 let escrow = CurrentEscrow;
958 let result = escrow.get_ledger_entry_type();
959
960 assert!(result.is_err());
961 assert_eq!(result.err().unwrap().code(), INTERNAL_ERROR);
962 }
963
964 #[test]
965 fn test_mandatory_fields_return_error_on_invalid_field() {
966 let mut mock = MockHostBindings::new();
967
968 mock.expect_get_current_ledger_obj_field()
970 .with(eq(sfield::Flags), always(), eq(4))
971 .times(1)
972 .returning(|_, _, _| INVALID_FIELD);
973
974 let _guard = setup_mock(mock);
975
976 let escrow = CurrentEscrow;
977 let result = escrow.get_flags();
978
979 assert!(result.is_err());
980 assert_eq!(result.err().unwrap().code(), INVALID_FIELD);
981 }
982 }
983
984 mod current_escrow_fields {
985 use super::*;
986 use crate::core::ledger_objects::current_escrow::CurrentEscrow;
987 use crate::host::setup_mock;
988
989 #[test]
990 fn test_mandatory_fields_return_ok() {
991 let mut mock = MockHostBindings::new();
992
993 expect_current_field(&mut mock, sfield::Account, 20, 1);
995 expect_current_field(&mut mock, sfield::Amount, 48, 1);
997 expect_current_field(&mut mock, sfield::Destination, 20, 1);
999 expect_current_field(&mut mock, sfield::OwnerNode, 8, 1);
1001 expect_current_field(&mut mock, sfield::PreviousTxnID, 32, 1);
1003 expect_current_field(&mut mock, sfield::PreviousTxnLgrSeq, 4, 1);
1005 expect_current_field(&mut mock, sfield::Data, 4096, 1);
1007
1008 let _guard = setup_mock(mock);
1009
1010 let escrow = CurrentEscrow;
1011
1012 assert!(escrow.get_account().is_ok());
1014 assert!(escrow.get_amount().is_ok());
1015 assert!(escrow.get_destination().is_ok());
1016 assert!(escrow.get_owner_node().is_ok());
1017 assert!(escrow.get_previous_txn_id().is_ok());
1018 assert!(escrow.get_previous_txn_lgr_seq().is_ok());
1019 assert!(escrow.get_data().is_ok());
1020 }
1021
1022 #[test]
1023 fn test_optional_fields_return_some() {
1024 let mut mock = MockHostBindings::new();
1025
1026 expect_current_field(&mut mock, sfield::CancelAfter, 4, 1);
1028 expect_current_field(&mut mock, sfield::Condition, 128, 1);
1030 expect_current_field(&mut mock, sfield::DestinationNode, 8, 1);
1032 expect_current_field(&mut mock, sfield::DestinationTag, 4, 1);
1034 expect_current_field(&mut mock, sfield::FinishAfter, 4, 1);
1036 expect_current_field(&mut mock, sfield::SourceTag, 4, 1);
1038 expect_current_field(&mut mock, sfield::FinishFunction, 1024, 1);
1040
1041 let _guard = setup_mock(mock);
1042
1043 let escrow = CurrentEscrow;
1044
1045 assert!(escrow.get_cancel_after().unwrap().is_some());
1047 assert!(escrow.get_condition().unwrap().is_some());
1048 assert!(escrow.get_destination_node().unwrap().is_some());
1049 assert!(escrow.get_destination_tag().unwrap().is_some());
1050 assert!(escrow.get_finish_after().unwrap().is_some());
1051 assert!(escrow.get_source_tag().unwrap().is_some());
1052 assert!(escrow.get_finish_function().unwrap().is_some());
1053 }
1054
1055 #[test]
1056 fn test_optional_fields_return_none_when_field_not_found() {
1057 let mut mock = MockHostBindings::new();
1058
1059 mock.expect_get_current_ledger_obj_field()
1061 .with(eq(sfield::CancelAfter), always(), eq(4))
1062 .times(1)
1063 .returning(|_, _, _| FIELD_NOT_FOUND);
1064 mock.expect_get_current_ledger_obj_field()
1066 .with(eq(sfield::Condition), always(), eq(128))
1067 .times(1)
1068 .returning(|_, _, _| 0);
1069 mock.expect_get_current_ledger_obj_field()
1071 .with(eq(sfield::DestinationNode), always(), eq(8))
1072 .times(1)
1073 .returning(|_, _, _| FIELD_NOT_FOUND);
1074 mock.expect_get_current_ledger_obj_field()
1076 .with(eq(sfield::DestinationTag), always(), eq(4))
1077 .times(1)
1078 .returning(|_, _, _| FIELD_NOT_FOUND);
1079 mock.expect_get_current_ledger_obj_field()
1081 .with(eq(sfield::FinishAfter), always(), eq(4))
1082 .times(1)
1083 .returning(|_, _, _| FIELD_NOT_FOUND);
1084 mock.expect_get_current_ledger_obj_field()
1086 .with(eq(sfield::SourceTag), always(), eq(4))
1087 .times(1)
1088 .returning(|_, _, _| FIELD_NOT_FOUND);
1089 mock.expect_get_current_ledger_obj_field()
1091 .with(eq(sfield::FinishFunction), always(), eq(1024))
1092 .times(1)
1093 .returning(|_, _, _| 0);
1094
1095 let _guard = setup_mock(mock);
1096
1097 let escrow = CurrentEscrow;
1098
1099 assert!(escrow.get_cancel_after().unwrap().is_none());
1101 assert!(escrow.get_condition().unwrap().is_none());
1102 assert!(escrow.get_destination_node().unwrap().is_none());
1103 assert!(escrow.get_destination_tag().unwrap().is_none());
1104 assert!(escrow.get_finish_after().unwrap().is_none());
1105 assert!(escrow.get_source_tag().unwrap().is_none());
1106
1107 let finish_function = escrow.get_finish_function().unwrap();
1109 assert!(finish_function.is_some());
1110 assert_eq!(finish_function.unwrap().len, 0);
1111 }
1112
1113 #[test]
1114 fn test_mandatory_fields_return_error_on_internal_error() {
1115 let mut mock = MockHostBindings::new();
1116
1117 mock.expect_get_current_ledger_obj_field()
1119 .with(eq(sfield::Account), always(), eq(20))
1120 .times(1)
1121 .returning(|_, _, _| INTERNAL_ERROR);
1122
1123 let _guard = setup_mock(mock);
1124
1125 let escrow = CurrentEscrow;
1126 let result = escrow.get_account();
1127
1128 assert!(result.is_err());
1129 assert_eq!(result.err().unwrap().code(), INTERNAL_ERROR);
1130 }
1131
1132 #[test]
1133 fn test_get_data_returns_error_on_internal_error() {
1134 let mut mock = MockHostBindings::new();
1135
1136 mock.expect_get_current_ledger_obj_field()
1137 .with(eq(sfield::Data), always(), eq(4096))
1138 .times(1)
1139 .returning(|_, _, _| INTERNAL_ERROR);
1140
1141 let _guard = setup_mock(mock);
1142
1143 let escrow = CurrentEscrow;
1144 let result = escrow.get_data();
1145
1146 assert!(result.is_err());
1147 assert_eq!(result.err().unwrap().code(), INTERNAL_ERROR);
1148 }
1149
1150 #[test]
1151 fn test_mandatory_fields_return_error_on_invalid_field() {
1152 let mut mock = MockHostBindings::new();
1153
1154 mock.expect_get_current_ledger_obj_field()
1156 .with(eq(sfield::Account), always(), eq(20))
1157 .times(1)
1158 .returning(|_, _, _| INVALID_FIELD);
1159
1160 let _guard = setup_mock(mock);
1161
1162 let escrow = CurrentEscrow;
1163 let result = escrow.get_account();
1164
1165 assert!(result.is_err());
1166 assert_eq!(result.err().unwrap().code(), INVALID_FIELD);
1167 }
1168 }
1169
1170 mod escrow_fields {
1171 use super::*;
1172 use crate::core::ledger_objects::escrow::Escrow;
1173 use crate::host::setup_mock;
1174
1175 #[test]
1176 fn test_mandatory_fields_return_ok() {
1177 let mut mock = MockHostBindings::new();
1178
1179 expect_ledger_field(&mut mock, 1, sfield::Account, 20, 1);
1181 expect_ledger_field(&mut mock, 1, sfield::Amount, 48, 1);
1183 expect_ledger_field(&mut mock, 1, sfield::Destination, 20, 1);
1185 expect_ledger_field(&mut mock, 1, sfield::OwnerNode, 8, 1);
1187 expect_ledger_field(&mut mock, 1, sfield::PreviousTxnID, 32, 1);
1189 expect_ledger_field(&mut mock, 1, sfield::PreviousTxnLgrSeq, 4, 1);
1191 expect_ledger_field(&mut mock, 1, sfield::Data, 4096, 1);
1193
1194 let _guard = setup_mock(mock);
1195
1196 let escrow = Escrow { slot_num: 1 };
1197
1198 assert!(escrow.get_account().is_ok());
1200 assert!(escrow.get_amount().is_ok());
1201 assert!(escrow.get_destination().is_ok());
1202 assert!(escrow.get_owner_node().is_ok());
1203 assert!(escrow.get_previous_txn_id().is_ok());
1204 assert!(escrow.get_previous_txn_lgr_seq().is_ok());
1205 assert!(escrow.get_data().is_ok());
1206 }
1207
1208 #[test]
1209 fn test_optional_fields_return_some() {
1210 let mut mock = MockHostBindings::new();
1211
1212 expect_ledger_field(&mut mock, 1, sfield::CancelAfter, 4, 1);
1214 expect_ledger_field(&mut mock, 1, sfield::Condition, 128, 1);
1216 expect_ledger_field(&mut mock, 1, sfield::DestinationNode, 8, 1);
1218 expect_ledger_field(&mut mock, 1, sfield::DestinationTag, 4, 1);
1220 expect_ledger_field(&mut mock, 1, sfield::FinishAfter, 4, 1);
1222 expect_ledger_field(&mut mock, 1, sfield::SourceTag, 4, 1);
1224 expect_ledger_field(&mut mock, 1, sfield::FinishFunction, 1024, 1);
1226
1227 let _guard = setup_mock(mock);
1228
1229 let escrow = Escrow { slot_num: 1 };
1230
1231 assert!(escrow.get_cancel_after().unwrap().is_some());
1233 assert!(escrow.get_condition().unwrap().is_some());
1234 assert!(escrow.get_destination_node().unwrap().is_some());
1235 assert!(escrow.get_destination_tag().unwrap().is_some());
1236 assert!(escrow.get_finish_after().unwrap().is_some());
1237 assert!(escrow.get_source_tag().unwrap().is_some());
1238 assert!(escrow.get_finish_function().unwrap().is_some());
1239 }
1240
1241 #[test]
1242 fn test_optional_fields_return_none_when_field_not_found() {
1243 let mut mock = MockHostBindings::new();
1244
1245 mock.expect_get_ledger_obj_field()
1247 .with(eq(1), eq(sfield::CancelAfter), always(), eq(4))
1248 .times(1)
1249 .returning(|_, _, _, _| FIELD_NOT_FOUND);
1250 mock.expect_get_ledger_obj_field()
1252 .with(eq(1), eq(sfield::Condition), always(), eq(128))
1253 .times(1)
1254 .returning(|_, _, _, _| 0);
1255 mock.expect_get_ledger_obj_field()
1257 .with(eq(1), eq(sfield::DestinationNode), always(), eq(8))
1258 .times(1)
1259 .returning(|_, _, _, _| FIELD_NOT_FOUND);
1260 mock.expect_get_ledger_obj_field()
1262 .with(eq(1), eq(sfield::DestinationTag), always(), eq(4))
1263 .times(1)
1264 .returning(|_, _, _, _| FIELD_NOT_FOUND);
1265 mock.expect_get_ledger_obj_field()
1267 .with(eq(1), eq(sfield::FinishAfter), always(), eq(4))
1268 .times(1)
1269 .returning(|_, _, _, _| FIELD_NOT_FOUND);
1270 mock.expect_get_ledger_obj_field()
1272 .with(eq(1), eq(sfield::SourceTag), always(), eq(4))
1273 .times(1)
1274 .returning(|_, _, _, _| FIELD_NOT_FOUND);
1275 mock.expect_get_ledger_obj_field()
1277 .with(eq(1), eq(sfield::FinishFunction), always(), eq(1024))
1278 .times(1)
1279 .returning(|_, _, _, _| 0);
1280
1281 let _guard = setup_mock(mock);
1282
1283 let escrow = Escrow { slot_num: 1 };
1284
1285 assert!(escrow.get_cancel_after().unwrap().is_none());
1287 assert!(escrow.get_condition().unwrap().is_none());
1288 assert!(escrow.get_destination_node().unwrap().is_none());
1289 assert!(escrow.get_destination_tag().unwrap().is_none());
1290 assert!(escrow.get_finish_after().unwrap().is_none());
1291 assert!(escrow.get_source_tag().unwrap().is_none());
1292
1293 let finish_function = escrow.get_finish_function().unwrap();
1295 assert!(finish_function.is_some());
1296 assert_eq!(finish_function.unwrap().len, 0);
1297 }
1298
1299 #[test]
1300 fn test_mandatory_fields_return_error_on_internal_error() {
1301 let mut mock = MockHostBindings::new();
1302
1303 mock.expect_get_ledger_obj_field()
1305 .with(eq(1), eq(sfield::Account), always(), eq(20))
1306 .times(1)
1307 .returning(|_, _, _, _| INTERNAL_ERROR);
1308
1309 let _guard = setup_mock(mock);
1310
1311 let escrow = Escrow { slot_num: 1 };
1312 let result = escrow.get_account();
1313
1314 assert!(result.is_err());
1315 assert_eq!(result.err().unwrap().code(), INTERNAL_ERROR);
1316 }
1317
1318 #[test]
1319 fn test_get_data_returns_error_on_internal_error() {
1320 let mut mock = MockHostBindings::new();
1321
1322 mock.expect_get_ledger_obj_field()
1323 .with(eq(1), eq(sfield::Data), always(), eq(4096))
1324 .times(1)
1325 .returning(|_, _, _, _| INTERNAL_ERROR);
1326
1327 let _guard = setup_mock(mock);
1328
1329 let escrow = Escrow { slot_num: 1 };
1330 let result = escrow.get_data();
1331
1332 assert!(result.is_err());
1333 assert_eq!(result.err().unwrap().code(), INTERNAL_ERROR);
1334 }
1335
1336 #[test]
1337 fn test_mandatory_fields_return_error_on_invalid_field() {
1338 let mut mock = MockHostBindings::new();
1339
1340 mock.expect_get_ledger_obj_field()
1342 .with(eq(1), eq(sfield::Account), always(), eq(20))
1343 .times(1)
1344 .returning(|_, _, _, _| INVALID_FIELD);
1345
1346 let _guard = setup_mock(mock);
1347
1348 let escrow = Escrow { slot_num: 1 };
1349 let result = escrow.get_account();
1350
1351 assert!(result.is_err());
1352 assert_eq!(result.err().unwrap().code(), INVALID_FIELD);
1353 }
1354 }
1355}