Skip to content

Commit

Permalink
Merge pull request maidsafe#2677 from mickvandijke/verify-data-type
Browse files Browse the repository at this point in the history
feat: verify quote and proof data type
  • Loading branch information
maqi authored Jan 29, 2025
2 parents 16271f7 + 5d910ff commit 8ba9e28
Show file tree
Hide file tree
Showing 6 changed files with 70 additions and 9 deletions.
11 changes: 11 additions & 0 deletions ant-evm/src/data_payments.rs
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,17 @@ impl ProofOfPayment {
}
true
}

/// Verifies whether all quotes were made for the expected data type.
pub fn verify_data_type(&self, data_type: u32) -> bool {
for (_, quote) in self.peer_quotes.iter() {
if quote.quoting_metrics.data_type != data_type {
return false;
}
}

true
}
}

/// A payment quote to store data given by a node to a client
Expand Down
8 changes: 7 additions & 1 deletion ant-networking/src/event/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ use libp2p::{
};

use ant_evm::{PaymentQuote, ProofOfPayment};
use ant_protocol::storage::DataTypes;
#[cfg(feature = "open-metrics")]
use ant_protocol::CLOSE_GROUP_SIZE;
use ant_protocol::{
Expand Down Expand Up @@ -137,7 +138,12 @@ pub enum NetworkEvent {
/// Fresh replicate to fetch
FreshReplicateToFetch {
holder: NetworkAddress,
keys: Vec<(NetworkAddress, ValidationType, Option<ProofOfPayment>)>,
keys: Vec<(
NetworkAddress,
DataTypes,
ValidationType,
Option<ProofOfPayment>,
)>,
},
}

Expand Down
7 changes: 7 additions & 0 deletions ant-networking/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -432,12 +432,19 @@ impl Network {
if !storage_proofs.is_empty() {
debug!("Storage proofing during GetStoreQuote to be implemented.");
}

// Check the quote itself is valid.
if !quote.check_is_signed_by_claimed_peer(peer) {
warn!("Received invalid quote from {peer_address:?}, {quote:?}");
continue;
}

// Check if the returned data type matches the request
if quote.quoting_metrics.data_type != data_type {
warn!("Received invalid quote from {peer_address:?}, {quote:?}. Data type did not match the request.");
continue;
}

all_quotes.push((peer_address.clone(), quote.clone()));
quotes_to_pay.push((peer, quote));
}
Expand Down
28 changes: 26 additions & 2 deletions ant-node/src/put_validation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ impl Node {
let payment_res = self
.payment_for_us_exists_and_is_still_valid(
&chunk.network_address(),
DataTypes::Chunk,
payment.clone(),
)
.await;
Expand All @@ -53,6 +54,7 @@ impl Node {
// did not manage to get this chunk as yet
self.replicate_valid_fresh_record(
record_key,
DataTypes::Chunk,
ValidationType::Chunk,
Some(payment),
);
Expand Down Expand Up @@ -83,6 +85,7 @@ impl Node {
.log();
self.replicate_valid_fresh_record(
record_key,
DataTypes::Chunk,
ValidationType::Chunk,
Some(payment),
);
Expand Down Expand Up @@ -116,6 +119,7 @@ impl Node {
let payment_res = self
.payment_for_us_exists_and_is_still_valid(
&scratchpad.network_address(),
DataTypes::Scratchpad,
payment.clone(),
)
.await;
Expand Down Expand Up @@ -206,7 +210,11 @@ impl Node {
// However, if the GraphEntry is already present, the incoming one shall be
// appended with the existing one, if content is different.
if let Err(err) = self
.payment_for_us_exists_and_is_still_valid(&net_addr, payment.clone())
.payment_for_us_exists_and_is_still_valid(
&net_addr,
DataTypes::GraphEntry,
payment.clone(),
)
.await
{
if already_exists {
Expand All @@ -226,6 +234,7 @@ impl Node {
.log();
self.replicate_valid_fresh_record(
record.key.clone(),
DataTypes::GraphEntry,
ValidationType::NonChunk(content_hash),
Some(payment),
);
Expand Down Expand Up @@ -283,7 +292,11 @@ impl Node {
// The pointer may already exist during the replication.
// The payment shall get deposit to self even if the pointer already exists.
if let Err(err) = self
.payment_for_us_exists_and_is_still_valid(&net_addr, payment.clone())
.payment_for_us_exists_and_is_still_valid(
&net_addr,
DataTypes::Pointer,
payment.clone(),
)
.await
{
if already_exists {
Expand Down Expand Up @@ -502,6 +515,7 @@ impl Node {
// but must have an existing copy to update.
self.replicate_valid_fresh_record(
scratchpad_key,
DataTypes::Scratchpad,
ValidationType::NonChunk(content_hash),
payment,
);
Expand Down Expand Up @@ -600,6 +614,7 @@ impl Node {
pub(crate) async fn payment_for_us_exists_and_is_still_valid(
&self,
address: &NetworkAddress,
data_type: DataTypes,
payment: ProofOfPayment,
) -> Result<()> {
let key = address.to_record_key();
Expand All @@ -624,6 +639,14 @@ impl Node {
)));
}

// verify data type matches
if !payment.verify_data_type(data_type.get_index()) {
warn!("Payment quote has wrong data type for record {pretty_key}");
return Err(Error::InvalidRequest(format!(
"Payment quote has wrong data type for record {pretty_key}"
)));
}

// verify the claimed payees are all known to us within the certain range.
let closest_k_peers = self.network().get_closest_k_value_local_peers().await?;
let mut payees = payment.payees();
Expand Down Expand Up @@ -800,6 +823,7 @@ impl Node {
let content_hash = XorName::from_content(&record.value);
self.replicate_valid_fresh_record(
key.clone(),
DataTypes::Pointer,
ValidationType::NonChunk(content_hash),
payment,
);
Expand Down
17 changes: 12 additions & 5 deletions ant-node/src/replication.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
use crate::{error::Result, node::Node};
use ant_evm::ProofOfPayment;
use ant_networking::{GetRecordCfg, Network};
use ant_protocol::storage::DataTypes;
use ant_protocol::{
messages::{Cmd, Query, QueryResponse, Request, Response},
storage::ValidationType,
Expand Down Expand Up @@ -104,7 +105,8 @@ impl Node {
pub(crate) fn replicate_valid_fresh_record(
&self,
paid_key: RecordKey,
record_type: ValidationType,
data_type: DataTypes,
validation_type: ValidationType,
payment: Option<ProofOfPayment>,
) {
let network = self.network().clone();
Expand Down Expand Up @@ -159,7 +161,7 @@ impl Node {

let our_peer_id = network.peer_id();
let our_address = NetworkAddress::from_peer(our_peer_id);
let keys = vec![(data_addr, record_type.clone(), payment)];
let keys = vec![(data_addr, data_type, validation_type.clone(), payment)];

for peer_id in replicate_candidates {
debug!("Replicating fresh record {pretty_key:?} to {peer_id:?}");
Expand All @@ -181,16 +183,21 @@ impl Node {
pub(crate) fn fresh_replicate_to_fetch(
&self,
holder: NetworkAddress,
keys: Vec<(NetworkAddress, ValidationType, Option<ProofOfPayment>)>,
keys: Vec<(
NetworkAddress,
DataTypes,
ValidationType,
Option<ProofOfPayment>,
)>,
) {
let node = self.clone();
let _handle = spawn(async move {
let mut new_keys = vec![];
for (addr, val_type, payment) in keys {
for (addr, data_type, val_type, payment) in keys {
if let Some(payment) = payment {
// Payment must be valid
match node
.payment_for_us_exists_and_is_still_valid(&addr, payment)
.payment_for_us_exists_and_is_still_valid(&addr, data_type, payment)
.await
{
Ok(_) => {}
Expand Down
8 changes: 7 additions & 1 deletion ant-protocol/src/messages/cmd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
// permissions and limitations relating to use of the SAFE Network Software.
#![allow(clippy::mutable_key_type)] // for Bytes in NetworkAddress

use crate::storage::DataTypes;
use crate::{storage::ValidationType, NetworkAddress};
use ant_evm::ProofOfPayment;
use serde::{Deserialize, Serialize};
Expand Down Expand Up @@ -35,7 +36,12 @@ pub enum Cmd {
/// Holder of the replication keys.
holder: NetworkAddress,
/// Keys of copy that shall be replicated.
keys: Vec<(NetworkAddress, ValidationType, Option<ProofOfPayment>)>,
keys: Vec<(
NetworkAddress,
DataTypes,
ValidationType,
Option<ProofOfPayment>,
)>,
},
/// Notify the peer it is now being considered as BAD due to the included behaviour
PeerConsideredAsBad {
Expand Down

0 comments on commit 8ba9e28

Please sign in to comment.