Skip to main content

diem_types/
block_metadata.rs

1// Copyright (c) The Diem Core Contributors
2// SPDX-License-Identifier: Apache-2.0
3
4use crate::{
5    account_address::AccountAddress,
6    account_config::diem_root_address,
7    event::{EventHandle, EventKey},
8};
9use diem_crypto::HashValue;
10use move_core_types::{
11    ident_str,
12    identifier::IdentStr,
13    move_resource::{MoveResource, MoveStructType},
14};
15use once_cell::sync::Lazy;
16use serde::{Deserialize, Serialize};
17
18/// Struct that will be persisted on chain to store the information of the current block.
19///
20/// The flow will look like following:
21/// 1. The executor will pass this struct to VM at the end of a block proposal.
22/// 2. The VM will use this struct to create a special system transaction that will emit an event
23///    represents the information of the current block. This transaction can't
24///    be emitted by regular users and is generated by each of the validators on the fly. Such
25///    transaction will be executed before all of the user-submitted transactions in the blocks.
26/// 3. Once that special resource is modified, the other user transactions can read the consensus
27///    info by calling into the read method of that resource, which would thus give users the
28///    information such as the current leader.
29#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
30pub struct BlockMetadata {
31    id: HashValue,
32    round: u64,
33    timestamp_usecs: u64,
34    // The vector has to be sorted to ensure consistent result among all nodes
35    previous_block_votes: Vec<AccountAddress>,
36    proposer: AccountAddress,
37}
38
39impl BlockMetadata {
40    pub fn new(
41        id: HashValue,
42        round: u64,
43        timestamp_usecs: u64,
44        previous_block_votes: Vec<AccountAddress>,
45        proposer: AccountAddress,
46    ) -> Self {
47        Self {
48            id,
49            round,
50            timestamp_usecs,
51            previous_block_votes,
52            proposer,
53        }
54    }
55
56    pub fn id(&self) -> HashValue {
57        self.id
58    }
59
60    pub fn into_inner(self) -> (u64, u64, Vec<AccountAddress>, AccountAddress) {
61        (
62            self.round,
63            self.timestamp_usecs,
64            self.previous_block_votes.clone(),
65            self.proposer,
66        )
67    }
68
69    pub fn timestamp_usec(&self) -> u64 {
70        self.timestamp_usecs
71    }
72
73    pub fn proposer(&self) -> AccountAddress {
74        self.proposer
75    }
76
77    pub fn previous_block_votes(&self) -> &Vec<AccountAddress> {
78        &self.previous_block_votes
79    }
80
81    pub fn round(&self) -> u64 {
82        self.round
83    }
84}
85
86pub fn new_block_event_key() -> EventKey {
87    EventKey::new_from_address(&diem_root_address(), 17)
88}
89
90/// The path to the new block event handle under a DiemBlock::BlockMetadata resource.
91pub static NEW_BLOCK_EVENT_PATH: Lazy<Vec<u8>> = Lazy::new(|| {
92    let mut path = DiemBlockResource::resource_path();
93    // it can be anything as long as it's referenced in AccountState::get_event_handle_by_query_path
94    path.extend_from_slice(b"/new_block_event/");
95    path
96});
97
98#[derive(Deserialize, Serialize)]
99pub struct DiemBlockResource {
100    height: u64,
101    new_block_events: EventHandle,
102}
103
104impl DiemBlockResource {
105    pub fn new_block_events(&self) -> &EventHandle {
106        &self.new_block_events
107    }
108
109    pub fn height(&self) -> u64 {
110        self.height
111    }
112}
113
114impl MoveStructType for DiemBlockResource {
115    const MODULE_NAME: &'static IdentStr = ident_str!("DiemBlock");
116    const STRUCT_NAME: &'static IdentStr = ident_str!("BlockMetadata");
117}
118
119impl MoveResource for DiemBlockResource {}
120
121#[derive(Clone, Deserialize, Serialize)]
122pub struct NewBlockEvent {
123    round: u64,
124    proposer: AccountAddress,
125    votes: Vec<AccountAddress>,
126    timestamp: u64,
127}
128
129impl NewBlockEvent {
130    pub fn new(
131        round: u64,
132        proposer: AccountAddress,
133        votes: Vec<AccountAddress>,
134        timestamp: u64,
135    ) -> Self {
136        Self {
137            round,
138            proposer,
139            votes,
140            timestamp,
141        }
142    }
143    pub fn round(&self) -> u64 {
144        self.round
145    }
146
147    pub fn proposer(&self) -> AccountAddress {
148        self.proposer
149    }
150
151    pub fn votes(&self) -> Vec<AccountAddress> {
152        self.votes.clone()
153    }
154}