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

RPC messages work on ConfirmedBlockCertificates #2976

Open
wants to merge 9 commits into
base: main
Choose a base branch
from
56 changes: 53 additions & 3 deletions linera-chain/src/certificate/confirmed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,21 @@
// Copyright (c) Zefchain Labs, Inc.
// SPDX-License-Identifier: Apache-2.0

use linera_base::identifiers::{BlobId, ChainId, MessageId};
use linera_execution::committee::Epoch;
use linera_base::{
crypto::Signature,
data_types::Round,
identifiers::{BlobId, ChainId, MessageId},
};
use linera_execution::committee::{Epoch, ValidatorName};
use serde::{Deserialize, Deserializer, Serialize};

use super::{
generic::GenericCertificate, hashed::Hashed, Certificate, CertificateValue,
HashedCertificateValue,
};
use crate::{
block::{ConfirmedBlock, ConversionError, ValidatedBlock},
data_types::{ExecutedBlock, Medium, MessageBundle},
data_types::{is_strictly_ordered, ExecutedBlock, Medium, MessageBundle},
};

impl GenericCertificate<ConfirmedBlock> {
Expand Down Expand Up @@ -82,3 +87,48 @@ impl From<GenericCertificate<ConfirmedBlock>> for Certificate {
Certificate::new(value, round, signatures)
}
}

impl Serialize for GenericCertificate<ConfirmedBlock> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
#[derive(Debug, Serialize)]
#[serde(rename = "ConfirmedBlockCertificate")]
struct CertificateHelper<'a> {
value: &'a ConfirmedBlock,
round: Round,
signatures: &'a Vec<(ValidatorName, Signature)>,
}

let helper = CertificateHelper {
value: self.inner(),
round: self.round,
signatures: self.signatures(),
};

helper.serialize(serializer)
}
}

impl<'de> Deserialize<'de> for GenericCertificate<ConfirmedBlock> {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
#[derive(Debug, Deserialize)]
#[serde(rename = "ConfirmedBlockCertificate")]
struct CertificateHelper {
value: Hashed<ConfirmedBlock>,
round: Round,
signatures: Vec<(ValidatorName, Signature)>,
}

let helper: CertificateHelper = Deserialize::deserialize(deserializer)?;
if !is_strictly_ordered(&helper.signatures) {
Err(serde::de::Error::custom("Vector is not strictly sorted"))
} else {
Ok(Self::new(helper.value, helper.round, helper.signatures))
}
}
}
8 changes: 1 addition & 7 deletions linera-core/src/client/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1693,13 +1693,7 @@ where

let certificates: Vec<ConfirmedBlockCertificate> = remote_node
.download_certificates(info.requested_sent_certificate_hashes)
.await?
.into_iter()
.map(|c| {
ConfirmedBlockCertificate::try_from(c)
.map_err(|_| NodeError::InvalidChainInfoResponse)
})
.collect::<Result<_, _>>()?;
.await?;

if !certificates.is_empty()
&& self
Expand Down
4 changes: 4 additions & 0 deletions linera-core/src/node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,10 @@ pub enum NodeError {
#[error("We don't have the value for the certificate.")]
MissingCertificateValue,

#[error("Reponse doesn't contain requested ceritifcates: {missing}")]
// NOTE: Can't use Vec<CryptoHash> b/c we cannot write Display impl for it.
deuszx marked this conversation as resolved.
Show resolved Hide resolved
MissingCertificates { missing: String },

#[error("Validator's response to block proposal failed to include a vote")]
MissingVoteInValidatorResponse,

Expand Down
9 changes: 9 additions & 0 deletions linera-rpc/src/grpc/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -364,6 +364,15 @@ impl ValidatorNode for GrpcClient {
missing_hashes = missing_hashes[received.len()..].to_vec();
certs_collected.append(&mut received);
}
if !missing_hashes.is_empty() {
return Err(NodeError::MissingCertificates {
missing: missing_hashes
.into_iter()
.map(|hash| hash.to_string())
.collect::<Vec<_>>()
.join(", "),
});
}
afck marked this conversation as resolved.
Show resolved Hide resolved
Ok(certs_collected)
}

Expand Down
51 changes: 7 additions & 44 deletions linera-rpc/src/message.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use linera_base::{
};
use linera_chain::{
data_types::{BlockProposal, LiteVote},
types::{Certificate, ConfirmedBlock, ConfirmedBlockCertificate},
types::{ConfirmedBlock, ConfirmedBlockCertificate},
};
use linera_core::{
data_types::{ChainInfoQuery, ChainInfoResponse, CrossChainRequest},
Expand All @@ -30,8 +30,7 @@ pub enum RpcMessage {
ChainInfoQuery(Box<ChainInfoQuery>),
DownloadBlobContent(Box<BlobId>),
DownloadConfirmedBlock(Box<CryptoHash>),
DownloadCertificate(Box<CryptoHash>),
DownloadCertificates(Box<Vec<CryptoHash>>),
DownloadCertificates(Vec<CryptoHash>),
BlobLastUsedBy(Box<BlobId>),
MissingBlobIds(Box<Vec<BlobId>>),
VersionInfoQuery,
Expand All @@ -45,8 +44,7 @@ pub enum RpcMessage {
GenesisConfigHashResponse(Box<CryptoHash>),
DownloadBlobContentResponse(Box<BlobContent>),
DownloadConfirmedBlockResponse(Box<ConfirmedBlock>),
DownloadCertificateResponse(Box<Certificate>),
DownloadCertificatesResponse(Box<Vec<Certificate>>),
DownloadCertificatesResponse(Vec<ConfirmedBlockCertificate>),
BlobLastUsedByResponse(Box<CryptoHash>),
MissingBlobIdsResponse(Box<Vec<BlobId>>),

Expand Down Expand Up @@ -78,13 +76,11 @@ impl RpcMessage {
| DownloadBlobContentResponse(_)
| DownloadConfirmedBlock(_)
| DownloadConfirmedBlockResponse(_)
| DownloadCertificate(_)
| DownloadCertificates(_)
| BlobLastUsedBy(_)
| BlobLastUsedByResponse(_)
| MissingBlobIds(_)
| MissingBlobIdsResponse(_)
| DownloadCertificateResponse(_)
| DownloadCertificatesResponse(_) => {
return None;
}
Expand All @@ -105,7 +101,6 @@ impl RpcMessage {
| DownloadConfirmedBlock(_)
| BlobLastUsedBy(_)
| MissingBlobIds(_)
| DownloadCertificate(_)
| DownloadCertificates(_) => true,
BlockProposal(_)
| LiteCertificate(_)
Expand All @@ -121,7 +116,6 @@ impl RpcMessage {
| DownloadConfirmedBlockResponse(_)
| BlobLastUsedByResponse(_)
| MissingBlobIdsResponse(_)
| DownloadCertificateResponse(_)
| DownloadCertificatesResponse(_) => false,
}
}
Expand Down Expand Up @@ -171,22 +165,11 @@ impl TryFrom<RpcMessage> for ConfirmedBlock {
}
}

impl TryFrom<RpcMessage> for Certificate {
impl TryFrom<RpcMessage> for Vec<ConfirmedBlockCertificate> {
type Error = NodeError;
fn try_from(message: RpcMessage) -> Result<Self, Self::Error> {
match message {
RpcMessage::DownloadCertificateResponse(certificate) => Ok(*certificate),
RpcMessage::Error(error) => Err(*error),
_ => Err(NodeError::UnexpectedMessage),
}
}
}

impl TryFrom<RpcMessage> for Vec<Certificate> {
type Error = NodeError;
fn try_from(message: RpcMessage) -> Result<Self, Self::Error> {
match message {
RpcMessage::DownloadCertificatesResponse(certificates) => Ok(*certificates),
RpcMessage::DownloadCertificatesResponse(certificates) => Ok(certificates),
RpcMessage::Error(error) => Err(*error),
_ => Err(NodeError::UnexpectedMessage),
}
Expand Down Expand Up @@ -236,7 +219,7 @@ impl From<HandleCertificateRequest> for RpcMessage {

impl From<Vec<CryptoHash>> for RpcMessage {
fn from(hashes: Vec<CryptoHash>) -> Self {
RpcMessage::DownloadCertificates(Box::new(hashes))
RpcMessage::DownloadCertificates(hashes)
}
}

Expand Down Expand Up @@ -288,28 +271,8 @@ impl From<ConfirmedBlock> for RpcMessage {
}
}

impl From<Certificate> for RpcMessage {
fn from(certificate: Certificate) -> Self {
RpcMessage::DownloadCertificateResponse(Box::new(certificate))
}
}

impl From<ConfirmedBlockCertificate> for RpcMessage {
fn from(certificate: ConfirmedBlockCertificate) -> Self {
RpcMessage::DownloadCertificateResponse(Box::new(certificate.into()))
}
}

impl From<Vec<Certificate>> for RpcMessage {
fn from(certificates: Vec<Certificate>) -> Self {
RpcMessage::DownloadCertificatesResponse(Box::new(certificates))
}
}

impl From<Vec<ConfirmedBlockCertificate>> for RpcMessage {
fn from(certificates: Vec<ConfirmedBlockCertificate>) -> Self {
RpcMessage::DownloadCertificatesResponse(Box::new(
certificates.into_iter().map(|c| c.into()).collect(),
))
RpcMessage::DownloadCertificatesResponse(certificates)
}
}
35 changes: 25 additions & 10 deletions linera-rpc/src/simple/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -149,24 +149,39 @@ impl ValidatorNode for SimpleClient {
&self,
hash: CryptoHash,
) -> Result<ConfirmedBlockCertificate, NodeError> {
self.query::<Certificate>(RpcMessage::DownloadCertificate(Box::new(hash)))
Ok(self
.download_certificates(vec![hash])
.await?
.try_into()
.map_err(|_| NodeError::UnexpectedCertificateValue)
.into_iter()
.next()
.unwrap()) // UNWRAP: We know there is exactly one certificate, otherwise we would have an error.
}

async fn download_certificates(
&self,
hashes: Vec<CryptoHash>,
) -> Result<Vec<ConfirmedBlockCertificate>, NodeError> {
self.query::<Vec<Certificate>>(RpcMessage::DownloadCertificates(Box::new(hashes)))
.await?
.into_iter()
.map(|cert| {
cert.try_into()
.map_err(|_| NodeError::UnexpectedCertificateValue)
let certificates = self
.query::<Vec<ConfirmedBlockCertificate>>(RpcMessage::DownloadCertificates(
hashes.clone(),
))
.await?;

if certificates.len() != hashes.len() {
let missing_hashes: Vec<CryptoHash> = hashes
.into_iter()
.filter(|hash| !certificates.iter().any(|cert| cert.hash() == *hash))
.collect();
Err(NodeError::MissingCertificates {
missing: missing_hashes
.iter()
.map(|hash| hash.to_string())
.collect::<Vec<_>>()
.join(", "),
})
.collect()
} else {
Ok(certificates)
}
afck marked this conversation as resolved.
Show resolved Hide resolved
}

async fn blob_last_used_by(&self, blob_id: BlobId) -> Result<CryptoHash, NodeError> {
Expand Down
2 changes: 0 additions & 2 deletions linera-rpc/src/simple/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -310,9 +310,7 @@ where
| RpcMessage::BlobLastUsedByResponse(_)
| RpcMessage::MissingBlobIds(_)
| RpcMessage::MissingBlobIdsResponse(_)
| RpcMessage::DownloadCertificate(_)
| RpcMessage::DownloadCertificates(_)
| RpcMessage::DownloadCertificateResponse(_)
| RpcMessage::DownloadCertificatesResponse(_) => Err(NodeError::UnexpectedMessage),
};

Expand Down
Loading
Loading