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
use crate::{Ledger, TransactionLocation, COL_TRANSACTION_LOCATION};
use snarkvm_algorithms::traits::LoadableMerkleParameters;
use snarkvm_objects::{errors::StorageError, BlockHeaderHash, LedgerScheme, Storage, Transaction};
use snarkvm_utilities::{
bytes::{FromBytes, ToBytes},
has_duplicates,
to_bytes,
};
impl<T: Transaction, P: LoadableMerkleParameters, S: Storage> Ledger<T, P, S> {
pub fn get_transaction_location(&self, transaction_id: &[u8]) -> Result<Option<TransactionLocation>, StorageError> {
match self.storage.get(COL_TRANSACTION_LOCATION, &transaction_id)? {
Some(transaction_locator) => {
let transaction_location = TransactionLocation::read(&transaction_locator[..])?;
Ok(Some(transaction_location))
}
None => Ok(None),
}
}
pub fn get_transaction(&self, transaction_id: &[u8]) -> Result<Option<T>, StorageError> {
match self.get_transaction_location(&transaction_id)? {
Some(transaction_location) => {
let block_transactions =
self.get_block_transactions(&BlockHeaderHash(transaction_location.block_hash))?;
Ok(Some(block_transactions.0[transaction_location.index as usize].clone()))
}
None => Ok(None),
}
}
pub fn get_transaction_bytes(&self, transaction_id: &[u8]) -> Result<Vec<u8>, StorageError> {
match self.get_transaction(transaction_id)? {
Some(transaction) => Ok(to_bytes![transaction]?),
None => Err(StorageError::InvalidTransactionId(hex::encode(&transaction_id))),
}
}
pub fn transaction_conflicts(&self, transaction: &T) -> bool {
let transaction_serial_numbers = transaction.old_serial_numbers();
let transaction_commitments = transaction.new_commitments();
let transaction_memo = transaction.memorandum();
if has_duplicates(transaction_serial_numbers) {
return true;
}
if has_duplicates(transaction_commitments) {
return true;
}
if self.contains_memo(transaction_memo) {
return true;
}
for sn in transaction_serial_numbers {
if self.contains_sn(sn) {
return true;
}
}
for cm in transaction_commitments {
if self.contains_cm(cm) {
return true;
}
}
false
}
}