libblockchain/
block.rs

1// The MIT License (MIT)
2//
3// Copyright (c) 2017 Doublify Technologies
4//
5// Permission is hereby granted, free of charge, to any person obtaining a copy
6// of this software and associated documentation files (the "Software"), to deal
7// in the Software without restriction, including without limitation the rights
8// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9// copies of the Software, and to permit persons to whom the Software is
10// furnished to do so, subject to the following conditions:
11//
12// The above copyright notice and this permission notice shall be included in
13// all copies or substantial portions of the Software.
14//
15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21// THE SOFTWARE.
22
23//! A `Block` implementation.
24
25use std::collections::hash_map::DefaultHasher;
26use std::hash::{Hash, Hasher};
27
28use chrono::{DateTime, Utc};
29
30/// A `Block` representation.
31#[derive(Clone, Debug, Hash, PartialEq)]
32pub struct Block<T: Hash> {
33    /// An height identifier of the given `Block`.
34    pub id: u64,
35
36    /// A binding of the given `Block`.
37    pub value: T,
38
39    /// An identifier of the previous `Block` in the [`Chain`].
40    ///
41    /// [`Chain`]: struct.Chain.html
42    pub previous_id: u64,
43
44    /// A timespec that the given `Block` was created.
45    pub timestamp: DateTime<Utc>,
46}
47
48impl<T: Hash> Block<T> {
49    /// Creates a new `Block`.
50    pub fn new(id: u64, value: T, previous_id: u64) -> Block<T> {
51        let timestamp = Utc::now();
52
53        Block {
54            id,
55            value,
56            previous_id,
57            timestamp,
58        }
59    }
60
61    /// Returns `true` if the given `Block` is trusty for the next `Block`.
62    ///
63    /// # Examples
64    ///
65    /// ```rust
66    /// use libblockchain::Block;
67    ///
68    /// let block0 = Block::new(0, vec![0; 256], 0);
69    /// let block1 = block0.next(vec![1, 2]);
70    ///
71    /// assert!(block1.is_trusty_for(&block0))
72    /// ```
73    pub fn is_trusty_for(&self, other: &Block<T>) -> bool {
74        self.previous_id == gen_id(other)
75    }
76
77    /// Constructs the next `Block`.
78    ///
79    /// # Examples
80    ///
81    /// ```rust
82    /// use libblockchain::Block;
83    ///
84    /// let block0 = Block::new(0, vec![0; 256], 0);
85    /// let block1 = block0.next(vec![1, 2]);
86    ///
87    /// println!("{:?}", block1)
88    /// ```
89    pub fn next(&self, value: T) -> Block<T> {
90        let id = self.id + 1;
91
92        let previous_id = gen_id(&self);
93
94        let timestamp = Utc::now();
95
96        Block {
97            id,
98            value,
99            previous_id,
100            timestamp,
101        }
102    }
103}
104
105fn gen_id<T: Hash>(t: &T) -> u64 {
106    let mut sip = DefaultHasher::default();
107
108    t.hash(&mut sip);
109
110    sip.finish()
111}