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
96
97
98
99
100
101
102
103
104
// SPDX-License-Identifier: MIT OR Apache-2.0
//! Traits required for defining custom extensions.
//!
//! User-defined extensions can be added to an operation's `Header` in order to extend the basic
//! functionality of the core p2panda data types or to encode application-specific fields which
//! should not be contained in the [`Body`](crate::Body). Extension values can themselves be derived
//! from other header material, such as `VerifingKey` or a headers' `Hash`.
//!
//! At a lower level this might be information relating to capabilities or group encryption schemes
//! which is required to enforce access-control restrictions during sync. Alternatively, extensions
//! might be used to set expiration timestamps and deletion flags in order to facilitate garbage
//! collection of stale data from the network. The core p2panda data types intentionally don't
//! enforce a single approach to such areas where there are rightly many different approaches, with
//! the most suitable being dependent on specific use-case requirements.
//!
//! Interfaces which use p2panda core data types can require certain extensions to be present on any
//! headers that their APIs accept using trait bounds. `p2panda-stream`, for example, uses the
//! [`PruneFlag`](crate::PruneFlag) in order to implement automatic network-wide garbage collection.
//!
//! Extensions are encoded on a header and sent over the wire. We need to satisfy all trait
//! requirements that `Header` requires, including `Serialize` and `Deserialize`.
//!
//! //! ## Example
//!
//! ```
//! use p2panda_core::{Body, Hash, Extension, Header, SigningKey, Timestamp};
//! use serde::{Serialize, Deserialize};
//!
//! #[derive(Clone, Debug, Serialize, Deserialize)]
//! struct LogId(Hash);
//!
//! #[derive(Clone, Debug, Default, Serialize, Deserialize)]
//! struct Expiry(u64);
//!
//! #[derive(Clone, Debug, Serialize, Deserialize)]
//! struct CustomExtensions {
//! log_id: Option<LogId>,
//! expires: Expiry,
//! }
//!
//! impl Extension<LogId> for CustomExtensions {
//! fn extract(header: &Header<Self>) -> Option<LogId> {
//! if header.seq_num == 0 {
//! return Some(LogId(header.hash()));
//! };
//!
//! header.extensions.log_id.clone()
//! }
//! }
//!
//! impl Extension<Expiry> for CustomExtensions {
//! fn extract(header: &Header<Self>) -> Option<Expiry> {
//! Some(header.extensions.expires.clone())
//! }
//! }
//!
//! let extensions = CustomExtensions {
//! log_id: None,
//! expires: Expiry(0123456),
//! };
//!
//! let signing_key = SigningKey::generate();
//! let body: Body = Body::new("Hello, Sloth!".as_bytes());
//!
//! let mut header = Header {
//! version: 1,
//! verifying_key: signing_key.verifying_key(),
//! signature: None,
//! payload_size: body.size(),
//! payload_hash: Some(body.hash()),
//! timestamp: Timestamp::now(),
//! seq_num: 0,
//! backlink: None,
//! extensions: extensions.clone(),
//! };
//!
//! header.sign(&signing_key);
//!
//! let log_id: LogId = header.extension().unwrap();
//! let expiry: Expiry = header.extension().unwrap();
//!
//! assert_eq!(header.hash(), log_id.0);
//! assert_eq!(extensions.expires.0, expiry.0);
//! ```
use Debug;
use ;
use crateHeader;
/// Trait definition of a single header extension type.
/// Super-trait defining trait bounds required by custom extensions types.
/// Blanket implementation of `Extensions` trait any type with the required bounds satisfied.