Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move Hashed to linera-base. #3064

Merged
merged 3 commits into from
Dec 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@
// Copyright (c) Zefchain Labs, Inc.
// SPDX-License-Identifier: Apache-2.0

//! A wrapper for hashable types to memoize the hash.

use std::borrow::Cow;

use custom_debug_derive::Debug;
use linera_base::crypto::{BcsHashable, CryptoHash};
use serde::{Deserialize, Serialize};

use super::CertificateValueT;
use crate::data_types::LiteValue;
use crate::crypto::{BcsHashable, CryptoHash};

/// Wrapper type around hashed instance of `T` type.
#[derive(Debug)]
Expand Down Expand Up @@ -41,28 +41,20 @@ impl<T> Hashed<T> {
Self { value, hash }
}

/// Returns the hash.
pub fn hash(&self) -> CryptoHash {
self.hash
}

/// Returns a reference to the value, without the hash.
pub fn inner(&self) -> &T {
&self.value
}

/// Consumes the hashed value and returns the value without the hash.
pub fn into_inner(self) -> T {
self.value
}

pub fn lite(&self) -> LiteValue
where
T: CertificateValueT,
{
LiteValue {
value_hash: self.hash,
chain_id: self.value.chain_id(),
kind: T::KIND,
}
}
}

impl<T: Serialize> Serialize for Hashed<T> {
Expand Down Expand Up @@ -98,6 +90,19 @@ impl<T: async_graphql::OutputType> async_graphql::TypeName for Hashed<T> {
}
}

#[async_graphql::Object(cache_control(no_cache), name_type)]
impl<T: async_graphql::OutputType + Clone> Hashed<T> {
#[graphql(derived(name = "hash"))]
async fn _hash(&self) -> CryptoHash {
self.hash()
}

#[graphql(derived(name = "value"))]
async fn _value(&self) -> T {
self.inner().clone()
}
}

impl<T> PartialEq for Hashed<T> {
fn eq(&self, other: &Self) -> bool {
self.hash() == other.hash()
Expand Down
1 change: 1 addition & 0 deletions linera-base/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ pub mod crypto;
pub mod data_types;
pub mod dyn_convert;
mod graphql;
pub mod hashed;
pub mod identifiers;
mod limited_writer;
pub mod ownership;
Expand Down
16 changes: 2 additions & 14 deletions linera-chain/src/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,14 @@ use std::fmt::Debug;
use linera_base::{
crypto::{BcsHashable, CryptoHash},
data_types::BlockHeight,
hashed::Hashed,
identifiers::ChainId,
};
use linera_execution::committee::Epoch;
use serde::{Deserialize, Serialize};
use thiserror::Error;

use crate::{data_types::ExecutedBlock, types::Hashed, ChainError};
use crate::{data_types::ExecutedBlock, ChainError};

/// Wrapper around an `ExecutedBlock` that has been validated.
#[derive(Debug, PartialEq, Eq, Clone, Deserialize, Serialize)]
Expand Down Expand Up @@ -85,19 +86,6 @@ impl ConfirmedBlock {
}
}

#[async_graphql::Object(cache_control(no_cache), name_type)]
impl Hashed<ConfirmedBlock> {
#[graphql(derived(name = "hash"))]
async fn _hash(&self) -> CryptoHash {
self.hash()
}

#[graphql(derived(name = "value"))]
async fn _value(&self) -> ConfirmedBlock {
self.inner().clone()
}
}

impl<'de> BcsHashable<'de> for ConfirmedBlock {}

impl ConfirmedBlock {
Expand Down
3 changes: 2 additions & 1 deletion linera-chain/src/certificate/confirmed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,13 @@
use linera_base::{
crypto::Signature,
data_types::Round,
hashed::Hashed,
identifiers::{BlobId, ChainId, MessageId},
};
use linera_execution::committee::{Epoch, ValidatorName};
use serde::{ser::SerializeStruct, Deserialize, Deserializer, Serialize};

use super::{generic::GenericCertificate, hashed::Hashed, Certificate};
use super::{generic::GenericCertificate, Certificate};
use crate::{
block::{ConfirmedBlock, ConversionError},
data_types::{ExecutedBlock, Medium, MessageBundle},
Expand Down
12 changes: 6 additions & 6 deletions linera-chain/src/certificate/generic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,12 @@ use custom_debug_derive::Debug;
use linera_base::{
crypto::{CryptoHash, Signature},
data_types::Round,
hashed::Hashed,
};
use linera_execution::committee::{Committee, ValidatorName};

use super::{hashed::Hashed, CertificateValueT};
use crate::ChainError;
use super::CertificateValue;
use crate::{data_types::LiteValue, ChainError};

/// Generic type representing a certificate for `value` of type `T`.
#[derive(Debug)]
Expand Down Expand Up @@ -97,7 +98,7 @@ impl<T> GenericCertificate<T> {
/// Verifies the certificate.
pub fn check(&self, committee: &Committee) -> Result<(), ChainError>
where
T: CertificateValueT,
T: CertificateValue,
{
crate::data_types::check_signatures(
self.hash(),
Expand All @@ -111,11 +112,10 @@ impl<T> GenericCertificate<T> {

pub fn lite_certificate(&self) -> crate::certificate::LiteCertificate<'_>
where
T: CertificateValueT,
T: CertificateValue,
{
let value = self.value.lite();
crate::certificate::LiteCertificate {
value,
value: LiteValue::new(&self.value),
round: self.round,
signatures: std::borrow::Cow::Borrowed(&self.signatures),
}
Expand Down
6 changes: 3 additions & 3 deletions linera-chain/src/certificate/lite.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@

use std::borrow::Cow;

use linera_base::{crypto::Signature, data_types::Round};
use linera_base::{crypto::Signature, data_types::Round, hashed::Hashed};
use linera_execution::committee::{Committee, ValidatorName};
use serde::{Deserialize, Serialize};

use super::{CertificateValueT, GenericCertificate, Hashed};
use super::{CertificateValue, GenericCertificate};
use crate::{
data_types::{check_signatures, LiteValue, LiteVote},
ChainError,
Expand Down Expand Up @@ -75,7 +75,7 @@ impl<'a> LiteCertificate<'a> {
}

/// Returns the [`GenericCertificate`] with the specified value, if it matches.
pub fn with_value<T: CertificateValueT>(
pub fn with_value<T: CertificateValue>(
self,
value: Hashed<T>,
) -> Option<GenericCertificate<T>> {
Expand Down
10 changes: 4 additions & 6 deletions linera-chain/src/certificate/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,13 @@

mod confirmed;
mod generic;
mod hashed;
mod lite;
mod timeout;
mod validated;

use std::collections::HashSet;

pub use generic::GenericCertificate;
pub use hashed::Hashed;
use linera_base::{
crypto::Signature,
data_types::{BlockHeight, Round},
Expand Down Expand Up @@ -95,7 +93,7 @@ pub enum CertificateKind {
Confirmed = 2,
}

pub trait CertificateValueT: Clone {
pub trait CertificateValue: Clone {
const KIND: CertificateKind;

fn chain_id(&self) -> ChainId;
Expand All @@ -107,7 +105,7 @@ pub trait CertificateValueT: Clone {
fn required_blob_ids(&self) -> HashSet<BlobId>;
}

impl CertificateValueT for Timeout {
impl CertificateValue for Timeout {
const KIND: CertificateKind = CertificateKind::Timeout;

fn chain_id(&self) -> ChainId {
Expand All @@ -127,7 +125,7 @@ impl CertificateValueT for Timeout {
}
}

impl CertificateValueT for ValidatedBlock {
impl CertificateValue for ValidatedBlock {
const KIND: CertificateKind = CertificateKind::Validated;

fn chain_id(&self) -> ChainId {
Expand All @@ -147,7 +145,7 @@ impl CertificateValueT for ValidatedBlock {
}
}

impl CertificateValueT for ConfirmedBlock {
impl CertificateValue for ConfirmedBlock {
const KIND: CertificateKind = CertificateKind::Confirmed;

fn chain_id(&self) -> ChainId {
Expand Down
7 changes: 2 additions & 5 deletions linera-chain/src/certificate/timeout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,15 @@
// Copyright (c) Zefchain Labs, Inc.
// SPDX-License-Identifier: Apache-2.0

use linera_base::{crypto::Signature, data_types::Round};
use linera_base::{crypto::Signature, data_types::Round, hashed::Hashed};
use linera_execution::committee::ValidatorName;
use serde::{
ser::{Serialize, SerializeStruct, Serializer},
Deserialize, Deserializer,
};

use super::{generic::GenericCertificate, Certificate};
use crate::{
block::{ConversionError, Timeout},
types::Hashed,
};
use crate::block::{ConversionError, Timeout};

impl TryFrom<Certificate> for GenericCertificate<Timeout> {
type Error = ConversionError;
Expand Down
3 changes: 1 addition & 2 deletions linera-chain/src/certificate/validated.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// Copyright (c) Zefchain Labs, Inc.
// SPDX-License-Identifier: Apache-2.0

use linera_base::{crypto::Signature, data_types::Round, identifiers::BlobId};
use linera_base::{crypto::Signature, data_types::Round, hashed::Hashed, identifiers::BlobId};
use linera_execution::committee::ValidatorName;
use serde::{
ser::{Serialize, SerializeStruct, Serializer},
Expand All @@ -13,7 +13,6 @@ use super::{generic::GenericCertificate, Certificate};
use crate::{
block::{ConversionError, ValidatedBlock},
data_types::ExecutedBlock,
types::Hashed,
};

impl GenericCertificate<ValidatedBlock> {
Expand Down
24 changes: 18 additions & 6 deletions linera-chain/src/data_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@ use linera_base::{
bcs,
crypto::{BcsHashable, BcsSignable, CryptoError, CryptoHash, KeyPair, PublicKey, Signature},
data_types::{Amount, Blob, BlockHeight, OracleResponse, Round, Timestamp},
doc_scalar, ensure, hex_debug,
doc_scalar, ensure,
hashed::Hashed,
hex_debug,
identifiers::{
Account, BlobId, BlobType, ChainId, ChannelName, Destination, GenericApplicationId,
MessageId, Owner, StreamId,
Expand All @@ -28,7 +30,7 @@ use serde::{Deserialize, Serialize};

use crate::{
types::{
CertificateKind, CertificateValueT, GenericCertificate, Hashed, LiteCertificate,
CertificateKind, CertificateValue, GenericCertificate, LiteCertificate,
ValidatedBlockCertificate,
},
ChainError,
Expand Down Expand Up @@ -439,6 +441,16 @@ pub struct LiteValue {
pub kind: CertificateKind,
}

impl LiteValue {
pub fn new<T: CertificateValue>(value: &Hashed<T>) -> Self {
Copy link
Contributor

@ma2bd ma2bd Dec 20, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: This contructor is a bit weird. What was the issue with .lite()? Would a conversion From make sense?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can change it to a conversion.

The issue with .lite() is that I can't define the method in linera-chain because Hashed is now in linera-base. And I can't define it in linera-base because it needs the CertificateValue trait, which is in linera-chain.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Personally I don't like From conversions which are not obvious. It makes it difficult to track the flow - it's impossible to look for w/ IDE's "find usage/references" feature.

LiteValue {
value_hash: value.hash(),
chain_id: value.inner().chain_id(),
kind: T::KIND,
}
}
}

#[derive(Debug, PartialEq, Eq, Hash, Clone, Serialize, Deserialize)]
struct VoteValue(CryptoHash, Round, CertificateKind);

Expand All @@ -456,7 +468,7 @@ impl<T> Vote<T> {
/// Use signing key to create a signed object.
pub fn new(value: Hashed<T>, round: Round, key_pair: &KeyPair) -> Self
where
T: CertificateValueT,
T: CertificateValue,
{
let hash_and_round = VoteValue(value.hash(), round, T::KIND);
let signature = Signature::new(&hash_and_round, key_pair);
Expand All @@ -471,10 +483,10 @@ impl<T> Vote<T> {
/// Returns the vote, with a `LiteValue` instead of the full value.
pub fn lite(&self) -> LiteVote
where
T: CertificateValueT,
T: CertificateValue,
{
LiteVote {
value: self.value.lite(),
value: LiteValue::new(&self.value),
round: self.round,
validator: self.validator,
signature: self.signature,
Expand Down Expand Up @@ -851,7 +863,7 @@ impl<'a, T> SignatureAggregator<'a, T> {
signature: Signature,
) -> Result<Option<GenericCertificate<T>>, ChainError>
where
T: CertificateValueT,
T: CertificateValue,
{
let hash_and_round = VoteValue(self.partial.hash(), self.partial.round, T::KIND);
signature.check(&hash_and_round, validator.0)?;
Expand Down
3 changes: 2 additions & 1 deletion linera-chain/src/manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ use linera_base::{
crypto::{KeyPair, PublicKey},
data_types::{ArithmeticError, Blob, BlockHeight, Round, Timestamp},
doc_scalar, ensure,
hashed::Hashed,
identifiers::{BlobId, ChainId, Owner},
ownership::ChainOwnership,
};
Expand All @@ -87,7 +88,7 @@ use serde::{Deserialize, Serialize};
use crate::{
block::{ConfirmedBlock, Timeout, ValidatedBlock},
data_types::{Block, BlockProposal, ExecutedBlock, LiteVote, Vote},
types::{Hashed, TimeoutCertificate, ValidatedBlockCertificate},
types::{TimeoutCertificate, ValidatedBlockCertificate},
ChainError,
};

Expand Down
5 changes: 3 additions & 2 deletions linera-chain/src/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
use linera_base::{
crypto::KeyPair,
data_types::{Amount, BlockHeight, Round, Timestamp},
hashed::Hashed,
identifiers::{ChainId, Owner},
};
use linera_execution::{
Expand All @@ -17,7 +18,7 @@ use linera_execution::{
use crate::{
block::ConfirmedBlock,
data_types::{Block, BlockProposal, IncomingBundle, PostedMessage, SignatureAggregator, Vote},
types::{CertificateValueT, GenericCertificate, Hashed},
types::{CertificateValue, GenericCertificate},
};

/// Creates a new child of the given block, with the same timestamp.
Expand Down Expand Up @@ -131,7 +132,7 @@ pub trait VoteTestExt<T>: Sized {
fn into_certificate(self) -> GenericCertificate<T>;
}

impl<T: CertificateValueT> VoteTestExt<T> for Vote<T> {
impl<T: CertificateValue> VoteTestExt<T> for Vote<T> {
fn into_certificate(self) -> GenericCertificate<T> {
let state = ValidatorState {
network_address: "".to_string(),
Expand Down
Loading
Loading