snarkvm_console_program/data/record/
bytes.rs1use super::*;
17
18impl<N: Network, Private: Visibility> FromBytes for Record<N, Private> {
19 fn read_le<R: Read>(mut reader: R) -> IoResult<Self> {
21 let variant = U8::<N>::new(u8::read_le(&mut reader)?);
23
24 let version = match *variant {
26 0 | 1 => U8::zero(),
27 2 | 3 => U8::one(),
28 4.. => return Err(error(format!("Failed to decode record variant ({variant}) for the version"))),
29 };
30
31 let owner = match *variant {
33 0 | 2 => Owner::Public(Address::read_le(&mut reader)?),
34 1 | 3 => Owner::Private(Private::read_le(&mut reader)?),
35 4.. => return Err(error(format!("Failed to decode record variant ({variant}) for the owner"))),
36 };
37
38 let num_entries = u8::read_le(&mut reader)?;
40 let mut data = IndexMap::with_capacity(num_entries as usize);
42 for _ in 0..num_entries {
43 let identifier = Identifier::<N>::read_le(&mut reader)?;
45 let num_bytes = u16::read_le(&mut reader)?;
47 let mut bytes = Vec::new();
49 (&mut reader).take(num_bytes as u64).read_to_end(&mut bytes)?;
50 let entry = Entry::read_le(&mut bytes.as_slice())?;
52 data.insert(identifier, entry);
54 }
55
56 let nonce = Group::read_le(&mut reader)?;
58
59 let reserved = [Identifier::from_str("owner").map_err(|e| error(e.to_string()))?];
61 if has_duplicates(data.keys().chain(reserved.iter())) {
63 return Err(error("Duplicate entry type found in record"));
64 }
65 if data.len() > N::MAX_DATA_ENTRIES {
67 return Err(error("Failed to parse record - too many entries"));
68 }
69
70 Ok(Self { owner, data, nonce, version })
71 }
72}
73
74impl<N: Network, Private: Visibility> ToBytes for Record<N, Private> {
75 fn write_le<W: Write>(&self, mut writer: W) -> IoResult<()> {
77 let variant = match (*self.version, self.owner.is_public()) {
79 (0, true) => 0u8,
80 (0, false) => 1u8,
81 (1, true) => 2u8,
82 (1, false) => 3u8,
83 (_, _) => {
84 return Err(error(format!(
85 "Failed to encode record - variant mismatch (version = {}, hiding = {}, owner = {})",
86 self.version,
87 self.is_hiding(),
88 self.owner.is_public()
89 )));
90 }
91 };
92
93 #[cfg(debug_assertions)]
94 {
95 let is_version_correct = match (!self.is_hiding(), self.owner.is_public()) {
97 (true, true) => variant == 0,
98 (true, false) => variant == 1,
99 (false, true) => variant == 2,
100 (false, false) => variant == 3,
101 };
102 if !is_version_correct {
103 return Err(error(format!(
104 "Failed to encode record - version mismatch (version = {}, hiding = {}, owner = {})",
105 self.version,
106 self.is_hiding(),
107 self.owner.is_public()
108 )));
109 }
110 }
111
112 variant.write_le(&mut writer)?;
114
115 match &self.owner {
117 Owner::Public(owner) => owner.write_le(&mut writer)?,
118 Owner::Private(owner) => owner.write_le(&mut writer)?,
119 };
120
121 u8::try_from(self.data.len()).or_halt_with::<N>("Record length exceeds u8::MAX").write_le(&mut writer)?;
123 for (entry_name, entry_value) in &self.data {
125 entry_name.write_le(&mut writer)?;
127 let bytes = entry_value.to_bytes_le().map_err(|e| error(e.to_string()))?;
129 u16::try_from(bytes.len())
131 .or_halt_with::<N>("Record entry exceeds u16::MAX bytes")
132 .write_le(&mut writer)?;
133 bytes.write_le(&mut writer)?;
135 }
136
137 self.nonce.write_le(&mut writer)
139 }
140}
141
142#[cfg(test)]
143mod tests {
144 use super::*;
145 use snarkvm_console_network::MainnetV0;
146
147 type CurrentNetwork = MainnetV0;
148
149 #[test]
150 fn test_bytes() -> Result<()> {
151 let expected = Record::<CurrentNetwork, Plaintext<CurrentNetwork>>::from_str(
153 "{ owner: aleo1d5hg2z3ma00382pngntdp68e74zv54jdxy249qhaujhks9c72yrs33ddah.private, token_amount: 100u64.private, _nonce: 0group.public }",
154 )?;
155
156 let expected_bytes = expected.to_bytes_le()?;
158 assert_eq!(expected, Record::read_le(&expected_bytes[..])?);
159
160 let expected = Record::<CurrentNetwork, Plaintext<CurrentNetwork>>::from_str(
162 "{ owner: aleo1d5hg2z3ma00382pngntdp68e74zv54jdxy249qhaujhks9c72yrs33ddah.private, token_amount: 100u64.private, _nonce: 0group.public, _version: 1u8.public }",
163 )?;
164
165 let expected_bytes = expected.to_bytes_le()?;
167 assert_eq!(expected, Record::read_le(&expected_bytes[..])?);
168 Ok(())
169 }
170}