Skip to content

Commit 7faf3f8

Browse files
authored
Certificate handler methods work with generic certificate type. (#2921)
* Generalize functions to work on GenericCertificate * RM HashedCertificateValue from value_cache_tests.rs * Fix compilation * HashedCertificateValue constructors map to new types * Fix tests * Use Either in full_certificate fn * Replace Has with CertificateValueT * Fix compilation under benchmark feature * RM unnecessary trait bounds * Fix name * RM asyn_trait, replace with correct approach * Pin it on me * Fix tests * clippy * Update validators after submitting proposal. * Rename inner to executed_block * Reformat in usage of instrument macro * RM unnecessary intermediate variables * Fix comment * s/CertificateProcessor/ProcessableCertificate/g * fmt * Return ConfirmedBlock value from Storage (#2950) * Return ConfirmedBlock value from Storage * s/read_hashed_certificate_value/read_hashed_confirmed_block/g * RM unused TryFrom impl * Simplify ValidatorNode API. (#2960) * RM unused endpoint * Fix field numbering in proto definitions * download_certificate API returns ConfirmedBlockCertifiate
1 parent fa6a739 commit 7faf3f8

File tree

51 files changed

+920
-798
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

51 files changed

+920
-798
lines changed

linera-chain/src/block.rs

Lines changed: 60 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,19 @@
44

55
use std::fmt::Debug;
66

7-
use linera_base::{crypto::BcsHashable, data_types::BlockHeight, identifiers::ChainId};
7+
use linera_base::{
8+
crypto::{BcsHashable, CryptoHash},
9+
data_types::BlockHeight,
10+
identifiers::ChainId,
11+
};
812
use linera_execution::committee::Epoch;
913
use serde::{Deserialize, Serialize};
1014
use thiserror::Error;
1115

1216
use crate::{
1317
data_types::ExecutedBlock,
14-
types::{CertificateValue, Has, Hashed, HashedCertificateValue},
18+
types::{CertificateValue, Hashed, HashedCertificateValue},
19+
ChainError,
1520
};
1621

1722
/// Wrapper around an `ExecutedBlock` that has been validated.
@@ -35,21 +40,13 @@ impl ValidatedBlock {
3540
pub fn into_inner(self) -> ExecutedBlock {
3641
self.executed_block
3742
}
38-
}
39-
40-
impl BcsHashable for ValidatedBlock {}
4143

42-
impl Has<ChainId> for ValidatedBlock {
43-
fn get(&self) -> &ChainId {
44-
&self.executed_block.block.chain_id
44+
pub fn to_log_str(&self) -> &'static str {
45+
"validated_block"
4546
}
4647
}
4748

48-
impl From<ValidatedBlock> for HashedCertificateValue {
49-
fn from(value: ValidatedBlock) -> Self {
50-
HashedCertificateValue::new_validated(value.executed_block)
51-
}
52-
}
49+
impl BcsHashable for ValidatedBlock {}
5350

5451
impl TryFrom<HashedCertificateValue> for Hashed<ValidatedBlock> {
5552
type Error = ConversionError;
@@ -72,9 +69,28 @@ pub struct ConfirmedBlock {
7269
executed_block: ExecutedBlock,
7370
}
7471

75-
impl From<ConfirmedBlock> for HashedCertificateValue {
76-
fn from(value: ConfirmedBlock) -> Self {
77-
HashedCertificateValue::new_confirmed(value.executed_block)
72+
#[async_graphql::Object(cache_control(no_cache))]
73+
impl ConfirmedBlock {
74+
#[graphql(derived(name = "executed_block"))]
75+
async fn _executed_block(&self) -> ExecutedBlock {
76+
self.executed_block.clone()
77+
}
78+
79+
async fn status(&self) -> String {
80+
"confirmed".to_string()
81+
}
82+
}
83+
84+
#[async_graphql::Object(cache_control(no_cache), name_type)]
85+
impl Hashed<ConfirmedBlock> {
86+
#[graphql(derived(name = "hash"))]
87+
async fn _hash(&self) -> CryptoHash {
88+
self.hash()
89+
}
90+
91+
#[graphql(derived(name = "value"))]
92+
async fn _value(&self) -> ConfirmedBlock {
93+
self.inner().clone()
7894
}
7995
}
8096

@@ -115,19 +131,40 @@ impl ConfirmedBlock {
115131
}
116132

117133
/// Returns a reference to the `ExecutedBlock` contained in this `ConfirmedBlock`.
118-
pub fn inner(&self) -> &ExecutedBlock {
134+
pub fn executed_block(&self) -> &ExecutedBlock {
119135
&self.executed_block
120136
}
121137

122138
/// Consumes this `ConfirmedBlock`, returning the `ExecutedBlock` it contains.
123139
pub fn into_inner(self) -> ExecutedBlock {
124140
self.executed_block
125141
}
126-
}
127142

128-
impl Has<ChainId> for ConfirmedBlock {
129-
fn get(&self) -> &ChainId {
130-
&self.executed_block.block.chain_id
143+
pub fn to_log_str(&self) -> &'static str {
144+
"confirmed_block"
145+
}
146+
147+
/// Creates a `HashedCertificateValue` without checking that this is the correct hash!
148+
pub fn with_hash_unchecked(self, hash: CryptoHash) -> Hashed<ConfirmedBlock> {
149+
Hashed::unchecked_new(self, hash)
150+
}
151+
152+
fn with_hash(self) -> Hashed<Self> {
153+
let hash = CryptoHash::new(&self);
154+
Hashed::unchecked_new(self, hash)
155+
}
156+
157+
/// Creates a `HashedCertificateValue` checking that this is the correct hash.
158+
pub fn with_hash_checked(self, hash: CryptoHash) -> Result<Hashed<ConfirmedBlock>, ChainError> {
159+
let hashed_certificate_value = self.with_hash();
160+
if hashed_certificate_value.hash() == hash {
161+
Ok(hashed_certificate_value)
162+
} else {
163+
Err(ChainError::CertificateValueHashMismatch {
164+
expected: hash,
165+
actual: hashed_certificate_value.hash(),
166+
})
167+
}
131168
}
132169
}
133170

@@ -146,11 +183,9 @@ impl Timeout {
146183
epoch,
147184
}
148185
}
149-
}
150186

151-
impl From<Timeout> for HashedCertificateValue {
152-
fn from(value: Timeout) -> Self {
153-
HashedCertificateValue::new_timeout(value.chain_id, value.height, value.epoch)
187+
pub fn to_log_str(&self) -> &'static str {
188+
"timeout"
154189
}
155190
}
156191

@@ -167,12 +202,6 @@ impl TryFrom<HashedCertificateValue> for Hashed<Timeout> {
167202

168203
impl BcsHashable for Timeout {}
169204

170-
impl Has<ChainId> for Timeout {
171-
fn get(&self) -> &ChainId {
172-
&self.chain_id
173-
}
174-
}
175-
176205
/// Failure to convert a [`HashedCertificateValue`] into one of the block types.
177206
#[derive(Clone, Copy, Debug, Error)]
178207
pub enum ConversionError {

linera-chain/src/certificate/confirmed.rs

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use super::{
1010
HashedCertificateValue,
1111
};
1212
use crate::{
13-
block::{ConfirmedBlock, ValidatedBlock},
13+
block::{ConfirmedBlock, ConversionError, ValidatedBlock},
1414
data_types::{ExecutedBlock, Medium, MessageBundle},
1515
};
1616

@@ -29,7 +29,7 @@ impl GenericCertificate<ConfirmedBlock> {
2929

3030
/// Returns reference to the `ExecutedBlock` contained in this certificate.
3131
pub fn executed_block(&self) -> &ExecutedBlock {
32-
self.inner().inner()
32+
self.inner().executed_block()
3333
}
3434

3535
/// Returns whether this value contains the message with the specified ID.
@@ -57,7 +57,7 @@ impl GenericCertificate<ConfirmedBlock> {
5757
}
5858

5959
impl TryFrom<Certificate> for GenericCertificate<ConfirmedBlock> {
60-
type Error = &'static str;
60+
type Error = ConversionError;
6161

6262
fn try_from(cert: Certificate) -> Result<Self, Self::Error> {
6363
let hash = cert.hash();
@@ -68,18 +68,17 @@ impl TryFrom<Certificate> for GenericCertificate<ConfirmedBlock> {
6868
round,
6969
signatures,
7070
)),
71-
_ => Err("Expected a confirmed block certificate"),
71+
_ => Err(ConversionError::ConfirmedBlock),
7272
}
7373
}
7474
}
7575

7676
impl From<GenericCertificate<ConfirmedBlock>> for Certificate {
7777
fn from(cert: GenericCertificate<ConfirmedBlock>) -> Certificate {
7878
let (value, round, signatures) = cert.destructure();
79-
Certificate::new(
80-
HashedCertificateValue::new_confirmed(value.into_inner().into_inner()),
81-
round,
82-
signatures,
83-
)
79+
let hash = value.hash();
80+
let value =
81+
Hashed::unchecked_new(CertificateValue::ConfirmedBlock(value.into_inner()), hash);
82+
Certificate::new(value, round, signatures)
8483
}
8584
}

linera-chain/src/certificate/generic.rs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use linera_base::{
99
};
1010
use linera_execution::committee::{Committee, ValidatorName};
1111

12-
use super::hashed::Hashed;
12+
use super::{hashed::Hashed, CertificateValueT};
1313
use crate::ChainError;
1414

1515
/// Generic type representing a certificate for `value` of type `T`.
@@ -99,6 +99,18 @@ impl<T> GenericCertificate<T> {
9999
crate::data_types::check_signatures(self.hash(), self.round, &self.signatures, committee)?;
100100
Ok(())
101101
}
102+
103+
pub fn lite_certificate(&self) -> crate::certificate::LiteCertificate<'_>
104+
where
105+
T: CertificateValueT,
106+
{
107+
let value = self.value.lite();
108+
crate::certificate::LiteCertificate {
109+
value,
110+
round: self.round,
111+
signatures: std::borrow::Cow::Borrowed(&self.signatures),
112+
}
113+
}
102114
}
103115

104116
impl<T: Clone> Clone for GenericCertificate<T> {

linera-chain/src/certificate/hashed.rs

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,13 @@
22
// Copyright (c) Zefchain Labs, Inc.
33
// SPDX-License-Identifier: Apache-2.0
44

5+
use std::borrow::Cow;
6+
57
use custom_debug_derive::Debug;
6-
use linera_base::{
7-
crypto::{BcsHashable, CryptoHash},
8-
identifiers::ChainId,
9-
};
8+
use linera_base::crypto::{BcsHashable, CryptoHash};
109
use serde::{de::DeserializeOwned, Deserialize, Serialize};
1110

11+
use super::CertificateValueT;
1212
use crate::data_types::LiteValue;
1313

1414
/// Wrapper type around hashed instance of `T` type.
@@ -55,11 +55,11 @@ impl<T> Hashed<T> {
5555

5656
pub fn lite(&self) -> LiteValue
5757
where
58-
T: Has<ChainId>,
58+
T: CertificateValueT,
5959
{
6060
LiteValue {
6161
value_hash: self.hash,
62-
chain_id: *self.value.get(),
62+
chain_id: self.value.chain_id(),
6363
}
6464
}
6565
}
@@ -91,6 +91,12 @@ impl<T: Clone> Clone for Hashed<T> {
9191
}
9292
}
9393

94+
impl<T: async_graphql::OutputType> async_graphql::TypeName for Hashed<T> {
95+
fn type_name() -> Cow<'static, str> {
96+
format!("Hashed{}", T::type_name(),).into()
97+
}
98+
}
99+
94100
#[cfg(with_testing)]
95101
impl<T> PartialEq for Hashed<T> {
96102
fn eq(&self, other: &Self) -> bool {
@@ -100,8 +106,3 @@ impl<T> PartialEq for Hashed<T> {
100106

101107
#[cfg(with_testing)]
102108
impl<T> Eq for Hashed<T> {}
103-
104-
/// A constraint summing a value of type `T`.
105-
pub trait Has<T> {
106-
fn get(&self) -> &T;
107-
}

linera-chain/src/certificate/lite.rs

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,11 @@
44

55
use std::borrow::Cow;
66

7-
use linera_base::{crypto::Signature, data_types::Round, identifiers::ChainId};
7+
use linera_base::{crypto::Signature, data_types::Round};
88
use linera_execution::committee::{Committee, ValidatorName};
99
use serde::{Deserialize, Serialize};
1010

11-
use super::{GenericCertificate, Has, Hashed};
11+
use super::{CertificateValueT, GenericCertificate, Hashed};
1212
use crate::{
1313
data_types::{check_signatures, LiteValue, LiteVote},
1414
ChainError,
@@ -74,8 +74,12 @@ impl<'a> LiteCertificate<'a> {
7474
}
7575

7676
/// Returns the [`GenericCertificate`] with the specified value, if it matches.
77-
pub fn with_value<T: Has<ChainId>>(self, value: Hashed<T>) -> Option<GenericCertificate<T>> {
78-
if &self.value.chain_id != value.inner().get() || self.value.value_hash != value.hash() {
77+
pub fn with_value<T: CertificateValueT>(
78+
self,
79+
value: Hashed<T>,
80+
) -> Option<GenericCertificate<T>> {
81+
if self.value.chain_id != value.inner().chain_id() || self.value.value_hash != value.hash()
82+
{
7983
return None;
8084
}
8185
Some(GenericCertificate::new(

0 commit comments

Comments
 (0)