From 3c4df8a35daa11a6e67f74987a5a6d94c715bff4 Mon Sep 17 00:00:00 2001 From: Andre da Silva Date: Fri, 31 May 2024 19:34:33 -0300 Subject: [PATCH] Endpoint to download a Certificate --- linera-core/src/node.rs | 2 ++ linera-core/src/unit_tests/test_utils.rs | 24 +++++++++++++ linera-rpc/proto/rpc.proto | 3 ++ linera-rpc/src/client.rs | 9 +++++ linera-rpc/src/grpc/client.rs | 14 ++++++-- linera-rpc/src/message.rs | 34 ++++++++++++++++--- linera-rpc/src/simple/client.rs | 5 +++ linera-rpc/src/simple/server.rs | 4 ++- .../tests/snapshots/format__format.yaml.snap | 22 ++++++++---- linera-service/src/grpc_proxy.rs | 19 +++++++++-- linera-service/src/proxy.rs | 6 +++- linera-service/src/schema_export.rs | 4 +++ 12 files changed, 129 insertions(+), 17 deletions(-) diff --git a/linera-core/src/node.rs b/linera-core/src/node.rs index 062baeb85616..5a5855f47dd0 100644 --- a/linera-core/src/node.rs +++ b/linera-core/src/node.rs @@ -87,6 +87,8 @@ pub trait LocalValidatorNode { &mut self, hash: CryptoHash, ) -> Result; + + async fn download_certificate(&mut self, hash: CryptoHash) -> Result; } /// Turn an address into a validator node. diff --git a/linera-core/src/unit_tests/test_utils.rs b/linera-core/src/unit_tests/test_utils.rs index 403f1024680b..569a11acd3d6 100644 --- a/linera-core/src/unit_tests/test_utils.rs +++ b/linera-core/src/unit_tests/test_utils.rs @@ -168,6 +168,13 @@ where }) .await } + + async fn download_certificate(&mut self, hash: CryptoHash) -> Result { + self.spawn_and_receive(move |validator, sender| { + validator.do_download_certificate(hash, sender) + }) + .await + } } impl LocalValidatorClient @@ -364,6 +371,23 @@ where .map_err(Into::into); sender.send(certificate_value) } + + async fn do_download_certificate( + self, + hash: CryptoHash, + sender: oneshot::Sender>, + ) -> Result<(), Result> { + let validator = self.client.lock().await; + let certificate = validator + .state + .storage_client() + .read_certificate(hash) + .await + .map(Into::into) + .map_err(Into::into); + + sender.send(certificate) + } } #[derive(Clone)] diff --git a/linera-rpc/proto/rpc.proto b/linera-rpc/proto/rpc.proto index 5654fe799bda..2899f70337cb 100644 --- a/linera-rpc/proto/rpc.proto +++ b/linera-rpc/proto/rpc.proto @@ -57,6 +57,9 @@ service ValidatorNode { // Downloads a certificate value. rpc DownloadCertificateValue(CryptoHash) returns (CertificateValue); + + // Downloads a certificate. + rpc DownloadCertificate(CryptoHash) returns (Certificate); } // Information about the Linera crate version the validator is running diff --git a/linera-rpc/src/client.rs b/linera-rpc/src/client.rs index 170cab1e0b49..e745546708fc 100644 --- a/linera-rpc/src/client.rs +++ b/linera-rpc/src/client.rs @@ -166,4 +166,13 @@ impl ValidatorNode for Client { Client::Simple(simple_client) => simple_client.download_certificate_value(hash).await?, }) } + + async fn download_certificate(&mut self, hash: CryptoHash) -> Result { + Ok(match self { + Client::Grpc(grpc_client) => grpc_client.download_certificate(hash).await?, + + #[cfg(with_simple_network)] + Client::Simple(simple_client) => simple_client.download_certificate(hash).await?, + }) + } } diff --git a/linera-rpc/src/grpc/client.rs b/linera-rpc/src/grpc/client.rs index 32e49084bbf2..02d2c404286c 100644 --- a/linera-rpc/src/grpc/client.rs +++ b/linera-rpc/src/grpc/client.rs @@ -9,7 +9,7 @@ use linera_base::{ data_types::{Blob, HashedBlob}, identifiers::{BlobId, ChainId}, }; -use linera_chain::data_types::{self, CertificateValue, HashedCertificateValue}; +use linera_chain::data_types::{self, Certificate, CertificateValue, HashedCertificateValue}; #[cfg(web)] use linera_core::node::{ LocalNotificationStream as NotificationStream, LocalValidatorNode as ValidatorNode, @@ -165,7 +165,7 @@ impl ValidatorNode for GrpcClient { #[instrument(target = "grpc_client", skip_all, err, fields(address = self.address))] async fn handle_certificate( &mut self, - certificate: data_types::Certificate, + certificate: Certificate, hashed_certificate_values: Vec, hashed_blobs: Vec, delivery: CrossChainMessageDelivery, @@ -289,6 +289,16 @@ impl ValidatorNode for GrpcClient { .try_into()?; Ok(certificate_value.with_hash_checked(hash)?) } + + #[instrument(target = "grpc_client", skip_all, err, fields(address = self.address))] + async fn download_certificate(&mut self, hash: CryptoHash) -> Result { + Ok(self + .client + .download_certificate(>::into(hash)) + .await? + .into_inner() + .try_into()?) + } } #[cfg(not(web))] diff --git a/linera-rpc/src/message.rs b/linera-rpc/src/message.rs index 37f497cccb16..9a1dbad24dbe 100644 --- a/linera-rpc/src/message.rs +++ b/linera-rpc/src/message.rs @@ -7,7 +7,7 @@ use linera_base::{ data_types::Blob, identifiers::{BlobId, ChainId}, }; -use linera_chain::data_types::{BlockProposal, CertificateValue, LiteVote}; +use linera_chain::data_types::{BlockProposal, Certificate, CertificateValue, LiteVote}; use linera_core::{ data_types::{ChainInfoQuery, ChainInfoResponse, CrossChainRequest}, node::NodeError, @@ -27,6 +27,7 @@ pub enum RpcMessage { ChainInfoQuery(Box), DownloadBlob(Box), DownloadCertificateValue(Box), + DownloadCertificate(Box), VersionInfoQuery, // Outbound @@ -36,6 +37,7 @@ pub enum RpcMessage { VersionInfoResponse(Box), DownloadBlobResponse(Box), DownloadCertificateValueResponse(Box), + DownloadCertificateResponse(Box), // Internal to a validator CrossChainRequest(Box), @@ -62,7 +64,9 @@ impl RpcMessage { | DownloadBlob(_) | DownloadBlobResponse(_) | DownloadCertificateValue(_) - | DownloadCertificateValueResponse(_) => { + | DownloadCertificateValueResponse(_) + | DownloadCertificate(_) + | DownloadCertificateResponse(_) => { return None; } }; @@ -76,7 +80,10 @@ impl RpcMessage { use RpcMessage::*; match self { - VersionInfoQuery | DownloadBlob(_) | DownloadCertificateValue(_) => true, + VersionInfoQuery + | DownloadBlob(_) + | DownloadCertificateValue(_) + | DownloadCertificate(_) => true, BlockProposal(_) | LiteCertificate(_) | Certificate(_) @@ -87,7 +94,8 @@ impl RpcMessage { | ChainInfoResponse(_) | VersionInfoResponse(_) | DownloadBlobResponse(_) - | DownloadCertificateValueResponse(_) => false, + | DownloadCertificateValueResponse(_) + | DownloadCertificateResponse(_) => false, } } } @@ -140,6 +148,18 @@ impl TryFrom for CertificateValue { } } +impl TryFrom for Certificate { + type Error = NodeError; + fn try_from(message: RpcMessage) -> Result { + use RpcMessage::*; + match message { + DownloadCertificateResponse(certificate) => Ok(*certificate), + Error(error) => Err(*error), + _ => Err(NodeError::UnexpectedMessage), + } + } +} + impl From for RpcMessage { fn from(block_proposal: BlockProposal) -> Self { RpcMessage::BlockProposal(Box::new(block_proposal)) @@ -205,3 +225,9 @@ impl From for RpcMessage { RpcMessage::DownloadCertificateValueResponse(Box::new(certificate)) } } + +impl From for RpcMessage { + fn from(certificate: Certificate) -> Self { + RpcMessage::DownloadCertificateResponse(Box::new(certificate)) + } +} diff --git a/linera-rpc/src/simple/client.rs b/linera-rpc/src/simple/client.rs index 3510c771e436..e918f4c7e051 100644 --- a/linera-rpc/src/simple/client.rs +++ b/linera-rpc/src/simple/client.rs @@ -151,6 +151,11 @@ impl ValidatorNode for SimpleClient { .await?; Ok(certificate_value.with_hash_checked(hash)?) } + + async fn download_certificate(&mut self, hash: CryptoHash) -> Result { + self.query(RpcMessage::DownloadCertificate(Box::new(hash))) + .await + } } #[derive(Clone)] diff --git a/linera-rpc/src/simple/server.rs b/linera-rpc/src/simple/server.rs index b5979ea4310e..7b516d8bf195 100644 --- a/linera-rpc/src/simple/server.rs +++ b/linera-rpc/src/simple/server.rs @@ -301,7 +301,9 @@ where | RpcMessage::DownloadBlob(_) | RpcMessage::DownloadBlobResponse(_) | RpcMessage::DownloadCertificateValue(_) - | RpcMessage::DownloadCertificateValueResponse(_) => Err(NodeError::UnexpectedMessage), + | RpcMessage::DownloadCertificateValueResponse(_) + | RpcMessage::DownloadCertificate(_) + | RpcMessage::DownloadCertificateResponse(_) => Err(NodeError::UnexpectedMessage), }; self.server.packets_processed += 1; diff --git a/linera-rpc/tests/snapshots/format__format.yaml.snap b/linera-rpc/tests/snapshots/format__format.yaml.snap index 1c227f1a1ef7..2865415dbd32 100644 --- a/linera-rpc/tests/snapshots/format__format.yaml.snap +++ b/linera-rpc/tests/snapshots/format__format.yaml.snap @@ -766,32 +766,40 @@ RpcMessage: NEWTYPE: TYPENAME: CryptoHash 6: - VersionInfoQuery: UNIT + DownloadCertificate: + NEWTYPE: + TYPENAME: CryptoHash 7: + VersionInfoQuery: UNIT + 8: Vote: NEWTYPE: TYPENAME: LiteVote - 8: + 9: ChainInfoResponse: NEWTYPE: TYPENAME: ChainInfoResponse - 9: + 10: Error: NEWTYPE: TYPENAME: NodeError - 10: + 11: VersionInfoResponse: NEWTYPE: TYPENAME: VersionInfo - 11: + 12: DownloadBlobResponse: NEWTYPE: TYPENAME: Blob - 12: + 13: DownloadCertificateValueResponse: NEWTYPE: TYPENAME: CertificateValue - 13: + 14: + DownloadCertificateResponse: + NEWTYPE: + TYPENAME: Certificate + 15: CrossChainRequest: NEWTYPE: TYPENAME: CrossChainRequest diff --git a/linera-service/src/grpc_proxy.rs b/linera-service/src/grpc_proxy.rs index ee21c300863b..6f7b97f9d785 100644 --- a/linera-service/src/grpc_proxy.rs +++ b/linera-service/src/grpc_proxy.rs @@ -27,8 +27,8 @@ use linera_rpc::{ notifier_service_server::{NotifierService, NotifierServiceServer}, validator_node_server::{ValidatorNode, ValidatorNodeServer}, validator_worker_client::ValidatorWorkerClient, - Blob, BlobId, BlockProposal, CertificateValue, ChainInfoQuery, ChainInfoResult, - CryptoHash, HandleCertificateRequest, LiteCertificate, Notification, + Blob, BlobId, BlockProposal, Certificate, CertificateValue, ChainInfoQuery, + ChainInfoResult, CryptoHash, HandleCertificateRequest, LiteCertificate, Notification, SubscriptionRequest, VersionInfo, }, pool::GrpcConnectionPool, @@ -426,6 +426,21 @@ where .map_err(|err| Status::from_error(Box::new(err)))?; Ok(Response::new(certificate.try_into()?)) } + + #[instrument(skip_all, err(Display))] + async fn download_certificate( + &self, + request: Request, + ) -> Result, Status> { + let hash = request.into_inner().try_into()?; + let certificate = self + .0 + .storage + .read_certificate(hash) + .await + .map_err(|err| Status::from_error(Box::new(err)))?; + Ok(Response::new(certificate.try_into()?)) + } } #[async_trait] diff --git a/linera-service/src/proxy.rs b/linera-service/src/proxy.rs index 5d2fecaf7cc1..e74a27688c88 100644 --- a/linera-service/src/proxy.rs +++ b/linera-service/src/proxy.rs @@ -301,6 +301,9 @@ where .into_inner() .into(), )), + DownloadCertificate(hash) => { + Ok(Some(self.storage.read_certificate(*hash).await?.into())) + } BlockProposal(_) | LiteCertificate(_) | Certificate(_) @@ -311,7 +314,8 @@ where | ChainInfoResponse(_) | VersionInfoResponse(_) | DownloadBlobResponse(_) - | DownloadCertificateValueResponse(_) => { + | DownloadCertificateValueResponse(_) + | DownloadCertificateResponse(_) => { Err(anyhow::Error::from(NodeError::UnexpectedMessage)) } } diff --git a/linera-service/src/schema_export.rs b/linera-service/src/schema_export.rs index be6eb9f9c7f7..848789912b43 100644 --- a/linera-service/src/schema_export.rs +++ b/linera-service/src/schema_export.rs @@ -84,6 +84,10 @@ impl ValidatorNode for DummyValidatorNode { ) -> Result { Err(NodeError::UnexpectedMessage) } + + async fn download_certificate(&mut self, _: CryptoHash) -> Result { + Err(NodeError::UnexpectedMessage) + } } struct DummyValidatorNodeProvider;