main.rs 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447
  1. // The dead code warnings create too much noise during wire-framing.
  2. // TODO: Delete this prior to release.
  3. #![allow(dead_code)]
  4. use std::{
  5. collections::HashMap,
  6. convert::TryFrom,
  7. hash::Hash as Hashable,
  8. fmt::{self, Display, Formatter},
  9. time::{Duration, SystemTime},
  10. ops::{Add, Sub}
  11. };
  12. use serde::{Serialize, Deserialize};
  13. use serde_big_array::BigArray;
  14. #[cfg(test)]
  15. mod test_helpers;
  16. #[cfg(test)]
  17. mod serde_tests;
  18. mod crypto;
  19. use crypto::{Hash, HashKind, Signature, SymKey, AsymKey, Public, Cryptotext};
  20. /// A Block tagged with its version number.
  21. #[derive(Debug, PartialEq, Serialize, Deserialize, Clone)]
  22. enum VersionedBlock {
  23. V0(Block)
  24. }
  25. /// A container which binds together ciphertext along with the metadata needed to identify,
  26. /// verify and decrypt it.
  27. #[derive(Debug, PartialEq, Serialize, Deserialize, Clone)]
  28. struct Block {
  29. /// Identifies this block and defines its location in the tree.
  30. path: Path,
  31. /// This field contains a collection of `Readcap`s indexed by the principal who holds them.
  32. /// `Readcap`s are envelopments of the key used to encrypt this block.
  33. readcaps: HashMap<Principal, Cryptotext<SymKey>>,
  34. /// This field is used to verify that the signer of this block had permission to write it.
  35. /// It contains a certificate chain that must lead back to the root key for the tree this block
  36. /// is part of.
  37. writecap: Writecap,
  38. /// The encrypted data contained in this block.
  39. body: Cryptotext<Vec<u8>>,
  40. /// The contents of the block are covered by a digital signature contained in this field.
  41. signature: Signature
  42. }
  43. /// An envelopment of a key, which is tagged with the principal who the key is meant for.
  44. #[derive(Debug, PartialEq, Serialize, Deserialize)]
  45. struct Readcap {
  46. /// The principal this `Readcap` was issued to.
  47. issued_to: Principal,
  48. /// An encipherment of a block key using the public key of the principal.
  49. key: Cryptotext<SymKey>,
  50. }
  51. impl Readcap {
  52. fn new(issued_to: Hash, key: Cryptotext<SymKey>) -> Readcap {
  53. Readcap { issued_to: Principal(issued_to), key }
  54. }
  55. }
  56. /// Verifies that a principal is authorized to write blocks in a tree.
  57. #[derive(Debug, PartialEq, Serialize, Deserialize, Clone)]
  58. struct Writecap {
  59. /// The principal this `Writecap` was issued to.
  60. issued_to: Principal,
  61. /// The path where this write caps's validity begins.
  62. path: Path,
  63. /// The point in time after which this write cap is no longer valid.
  64. expires: Epoch,
  65. /// The public key used to sign this write cap.
  66. signing_key: AsymKey<Public>,
  67. /// A digital signature which covers all of the fields in the write cap except for next.
  68. signature: Signature,
  69. /// The next write cap in the chain leading back to the root.
  70. next: Option<Box<Writecap>>,
  71. }
  72. /// Fragments are created from blocks using Erasure Encoding and stored with other nodes in the
  73. /// network to provide availability and redundancy of data.
  74. #[derive(Debug, PartialEq, Serialize, Deserialize)]
  75. struct Fragment {
  76. /// The path to the block this fragment is from.
  77. path: Path,
  78. /// The serial number of this fragment.
  79. serial: FragmentSerial,
  80. /// The actual data.
  81. body: Vec<u8>,
  82. }
  83. impl Fragment {
  84. /// Create a new fragment with the given fields. If `path_str` cannot be parsed then a failed
  85. /// `Result` is returned containing a `PathError`.
  86. fn new(path_str: &str, serial_num: u32, body: Vec<u8>) -> Result<Fragment, PathError> {
  87. let result = Path::try_from(path_str);
  88. Ok(Fragment {
  89. path: result?,
  90. serial: FragmentSerial(serial_num),
  91. body
  92. })
  93. }
  94. }
  95. /// The body of every non-leaf node in a tree contains this data structure.
  96. #[derive(Debug, PartialEq, Serialize, Deserialize)]
  97. struct Directory {
  98. /// The nodes that are attached to the tree at this block.
  99. nodes: Vec<Principal>,
  100. /// This block's descendants.
  101. children: HashMap<String, HashMap<FragmentSerial, FragmentRecord>>,
  102. }
  103. /// Keeps track of which principal is storing a fragment.
  104. #[derive(Debug, PartialEq, Serialize, Deserialize)]
  105. struct FragmentRecord {
  106. /// The fragment serial number this record is for.
  107. serial: FragmentSerial,
  108. /// The principal who is storing this fragment.
  109. stored_by: Principal,
  110. }
  111. impl FragmentRecord {
  112. /// Creates a new `FragmentRecord` whose `serial` and `stored_by` fields are set to
  113. /// the given values.
  114. fn new(serial: u32, stored_by: Hash) -> FragmentRecord {
  115. FragmentRecord {
  116. serial: FragmentSerial(serial),
  117. stored_by: Principal(stored_by),
  118. }
  119. }
  120. }
  121. /// An identifier for a security principal, which is any entity that can be authenticated.
  122. #[derive(Debug, PartialEq, Eq, Serialize, Deserialize, Hashable, Clone)]
  123. pub struct Principal(Hash);
  124. impl Principal {
  125. fn kind(&self) -> HashKind {
  126. HashKind::from(&self.0)
  127. }
  128. }
  129. /// Trait for types which are owned by a `Principal`.
  130. pub trait Owned {
  131. /// Returns the `Principal` that owns `self`, using the given hash algorithm.
  132. fn owner_of_kind(&self, kind: HashKind) -> Principal;
  133. /// Returns the `Principal` that owns `self`, using the default hash algorithm.
  134. fn owner(&self) -> Principal {
  135. self.owner_of_kind(HashKind::default())
  136. }
  137. }
  138. /// An identifier for a block in a tree.
  139. #[derive(Debug, PartialEq, Serialize, Deserialize, Clone)]
  140. struct Path {
  141. owner: Principal,
  142. components: Vec<String>,
  143. }
  144. impl Path {
  145. /// The character that is used to separate path components.
  146. const SEP: char = '/';
  147. /// The limit, in bytes, of a `Path`'s length.
  148. const BYTE_LIMIT: usize = 4096;
  149. /// Returns a result which, when successful, contains the index after the last character in the
  150. /// current path component.
  151. fn component_end<I: Iterator<Item = (usize, char)>>(
  152. start: usize, first: char, pairs: &mut I
  153. ) -> Result<usize, PathError> {
  154. if first == Path::SEP {
  155. return Err(PathError::EmptyComponent);
  156. }
  157. let end;
  158. let mut last = start;
  159. loop {
  160. match pairs.next() {
  161. Some((index, Path::SEP)) => {
  162. end = index;
  163. break;
  164. },
  165. Some((index, _)) => last = index,
  166. None => {
  167. end = last + 1;
  168. break
  169. }
  170. }
  171. }
  172. if end == start {
  173. Err(PathError::EmptyComponent)
  174. }
  175. else {
  176. Ok(end)
  177. }
  178. }
  179. /// Asserts that the number of bytes in the given string is no more than `Path::BYTE_LIMIT`.
  180. fn assert_not_too_long(string: &str) -> Result<(), PathError> {
  181. let len = string.len();
  182. if len > Path::BYTE_LIMIT {
  183. return Err(PathError::PathTooLong(len))
  184. }
  185. Ok(())
  186. }
  187. /// Returns true if `other` is a subpath of this `Path`.
  188. fn contains(&self, other: &Path) -> bool {
  189. if self.owner != other.owner {
  190. return false;
  191. };
  192. // This path must be no longer than the other path.
  193. if self.components.len() > other.components.len() {
  194. return false;
  195. }
  196. // Skip the component containing the owner.
  197. let self_iter = self.components.iter().skip(1);
  198. let other_iter = other.components.iter().skip(1);
  199. for pair in self_iter.zip(other_iter) {
  200. if pair.0 != pair.1 {
  201. return false;
  202. }
  203. }
  204. true
  205. }
  206. }
  207. impl<'s> TryFrom<&'s str> for Path {
  208. type Error = PathError;
  209. fn try_from(string: &'s str) -> Result<Path, PathError> {
  210. Path::assert_not_too_long(string)?;
  211. let mut pairs = string.char_indices();
  212. let mut components = Vec::new();
  213. let mut last_end = 0;
  214. while let Some((start, c)) = pairs.next() {
  215. let end = Path::component_end(start, c, &mut pairs)?;
  216. last_end = end;
  217. let slice = &string[start..end];
  218. components.push(slice.to_string());
  219. }
  220. // An empty component is added to the end to indicate if there was a trailing slash.
  221. if string.len() - 1 == last_end {
  222. components.push("".to_string());
  223. }
  224. let leading = components.get(0).ok_or(PathError::InvalidLeadingComponent)?;
  225. let hash = Hash::try_from(leading.as_str())
  226. .map_err(|_| PathError::InvalidLeadingComponent)?;
  227. Ok(Path {
  228. owner: Principal(hash),
  229. components,
  230. })
  231. }
  232. }
  233. impl Display for Path {
  234. fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
  235. if self.components.is_empty() {
  236. return write!(f, "");
  237. };
  238. let mut iter = self.components.iter();
  239. let first = iter.next().unwrap();
  240. let mut output = write!(f, "{}", first);
  241. for component in iter {
  242. output = write!(f, "{}{}", Path::SEP, component)
  243. }
  244. output
  245. }
  246. }
  247. /// Errors which can occur when converting a string to a `Path`.
  248. #[derive(Debug, PartialEq)]
  249. enum PathError {
  250. /// Occurs when the number of bytes in a string is greater than `Path::BYTE_LIMIT`.
  251. PathTooLong(usize),
  252. /// Indicates that a path string was empty.
  253. Empty,
  254. /// Occurs when a component in a path string was empty.
  255. EmptyComponent,
  256. /// Occurs when the leading component of a path is not in the correct format.
  257. InvalidLeadingComponent,
  258. }
  259. impl Display for PathError {
  260. fn fmt(&self, formatter: &mut Formatter<'_>) -> fmt::Result {
  261. match self {
  262. PathError::PathTooLong(length) => formatter.write_fmt(format_args!(
  263. "path contained {} bytes, which is over the {} byte limit",
  264. length,
  265. Path::BYTE_LIMIT)
  266. ),
  267. PathError::Empty => formatter.write_str("path was empty"),
  268. PathError::EmptyComponent => formatter.write_str("component of path was empty"),
  269. PathError::InvalidLeadingComponent
  270. => formatter.write_str("invalid leading path component")
  271. }
  272. }
  273. }
  274. /// An instant in time represented by the number of seconds since January 1st 1970, 00:00:00 UTC.
  275. #[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq, PartialOrd, Ord)]
  276. struct Epoch(u64);
  277. impl Epoch {
  278. /// Returns the current epoch time.
  279. fn now() -> Epoch {
  280. let now = SystemTime::now();
  281. // If the system clock is before the unix epoch, just panic.
  282. let epoch = now.duration_since(SystemTime::UNIX_EPOCH).unwrap();
  283. Epoch(epoch.as_secs())
  284. }
  285. }
  286. impl Copy for Epoch {}
  287. impl Add<Duration> for Epoch {
  288. type Output = Self;
  289. fn add(self, other: Duration) -> Self {
  290. Epoch(self.0 + other.as_secs())
  291. }
  292. }
  293. impl Sub<Duration> for Epoch {
  294. type Output = Self;
  295. fn sub(self, other: Duration) -> Self {
  296. Epoch(self.0 - other.as_secs())
  297. }
  298. }
  299. /// The serial number of a block fragment.
  300. #[derive(Debug, PartialEq, Eq, Serialize, Deserialize, Hashable)]
  301. struct FragmentSerial(u32);
  302. fn main() {
  303. println!("Hello, world!");
  304. }
  305. #[cfg(test)]
  306. mod tests {
  307. use super::*;
  308. use test_helpers::*;
  309. fn path_from_str_test_case(
  310. expected: Result<Path, PathError>, input: &str
  311. ) -> Result<(), PathError> {
  312. let result = Path::try_from(input);
  313. assert_eq!(expected, result);
  314. Ok(())
  315. }
  316. #[test]
  317. fn path_from_str_multiple_components_ok() -> Result<(), PathError> {
  318. let expected = make_path(vec!["red", "green", "blue"]);
  319. let input = format!("{}/red/green/blue", expected.owner.0);
  320. path_from_str_test_case(Ok(expected), input.as_str())?;
  321. Ok(())
  322. }
  323. #[test]
  324. fn path_from_str_one_component_ok() -> Result<(), PathError> {
  325. let expected = make_path(vec![]);
  326. let input = expected.owner.0.to_string();
  327. path_from_str_test_case(Ok(expected), input.as_str())?;
  328. Ok(())
  329. }
  330. #[test]
  331. fn path_from_str_trailing_slash_ok() -> Result<(), PathError> {
  332. // Notice the empty component at the end of this path due to the trailing slash.
  333. let expected = make_path(vec!["orange", "banana", "shotgun", ""]);
  334. let input = format!("{}/orange/banana/shotgun/", expected.owner.0);
  335. path_from_str_test_case(Ok(expected), input.as_str())?;
  336. Ok(())
  337. }
  338. #[test]
  339. fn path_from_str_path_too_long_fail() -> Result<(), PathError> {
  340. let principal = make_principal();
  341. let input = format!("{}/{}", principal.0, "*".repeat(4097));
  342. let expected = Err(PathError::PathTooLong(input.len()));
  343. path_from_str_test_case(expected, input.as_str())?;
  344. Ok(())
  345. }
  346. #[test]
  347. fn path_from_str_multiple_slashes_fail() -> Result<(), PathError> {
  348. let expected = Err(PathError::EmptyComponent);
  349. let input = format!("{}//orange", make_principal().0);
  350. path_from_str_test_case(expected, input.as_str())?;
  351. Ok(())
  352. }
  353. #[test]
  354. fn path_from_str_leading_slash_fail() -> Result<(), PathError> {
  355. let expected = Err(PathError::EmptyComponent);
  356. let input = format!("/{}/orange/banana/shotgun", make_principal().0);
  357. path_from_str_test_case(expected, input.as_str())?;
  358. Ok(())
  359. }
  360. #[test]
  361. fn path_round_trip() -> Result<(), PathError> {
  362. let expected = make_path(vec!["interstitial", "inter-related", "intersections"]);
  363. let actual = Path::try_from(expected.to_string().as_str())?;
  364. assert_eq!(expected, actual);
  365. Ok(())
  366. }
  367. #[test]
  368. fn path_contains_true() {
  369. let larger = make_path(vec!["apps"]);
  370. let smaller = make_path(vec!["apps", "bohdi"]);
  371. assert!(larger.contains(&smaller));
  372. }
  373. #[test]
  374. fn path_contains_true_only_owner() {
  375. let larger = make_path(vec![]);
  376. let smaller = make_path(vec![]);
  377. assert!(larger.contains(&smaller));
  378. }
  379. #[test]
  380. fn path_contains_false_self_is_longer() {
  381. let first = make_path(vec!["apps", "bohdi"]);
  382. let second = make_path(vec!["apps"]);
  383. assert!(!first.contains(&second));
  384. }
  385. #[test]
  386. fn path_contains_false_same_owners() {
  387. let first = make_path(vec!["apps"]);
  388. let second = make_path(vec!["nodes"]);
  389. assert!(!first.contains(&second));
  390. }
  391. #[test]
  392. fn path_contains_false_different_owners() {
  393. let first = make_path(vec!["apps"]);
  394. let mut second = make_path(vec!["apps"]);
  395. second.owner = Principal(Hash::Sha2_256(PRINCIPAL2));
  396. assert!(!first.contains(&second));
  397. }
  398. }