Skip to content

Commit

Permalink
chore: tinkering with the quote flow
Browse files Browse the repository at this point in the history
  • Loading branch information
mickvandijke committed Dec 8, 2024
1 parent 4ee7f93 commit 34d7004
Show file tree
Hide file tree
Showing 9 changed files with 75 additions and 108 deletions.
3 changes: 2 additions & 1 deletion ant-evm/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ pub use evmlib::common::Address as RewardsAddress;
pub use evmlib::common::Address as EvmAddress;
pub use evmlib::common::QuotePayment;
pub use evmlib::common::{QuoteHash, TxHash};
pub use evmlib::contract::payment_vault;
pub use evmlib::cryptography;
#[cfg(feature = "external-signer")]
pub use evmlib::external_signer;
Expand All @@ -28,8 +29,8 @@ mod amount;
mod data_payments;
mod error;

pub use evmlib::quoting_metrics::QuotingMetrics;
pub use data_payments::{PaymentQuote, ProofOfPayment, QUOTE_EXPIRATION_SECS};
pub use evmlib::quoting_metrics::QuotingMetrics;

/// Types used in the public API
pub use amount::{Amount, AttoTokens};
Expand Down
15 changes: 10 additions & 5 deletions ant-node/src/put_validation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -622,8 +622,7 @@ impl Node {
))
})?
.as_secs();
// NB TODO @mick: can we check if the quote has expired with block time in evmlib? Or should nodes do it manually here? Else keep the block below
// manually check if the quote has expired

if quote_expiration_time < SystemTime::now() {
warn!("Payment quote has expired for record {pretty_key}");
return Err(Error::InvalidRequest(format!(
Expand All @@ -633,7 +632,8 @@ impl Node {

// check if payment is valid on chain
debug!("Verifying payment for record {pretty_key}");
let reward_amount = self.evm_network()
let reward_amount = self
.evm_network()
.verify_data_payment(
payment.quote.hash(),
payment.quote.quoting_metrics,
Expand All @@ -657,7 +657,10 @@ impl Node {
.set(new_value);
}
self.events_channel()
.broadcast(crate::NodeEvent::RewardReceived(AttoTokens::from(reward_amount), address.clone()));
.broadcast(crate::NodeEvent::RewardReceived(
AttoTokens::from(reward_amount),
address.clone(),
));

// vdash metric (if modified please notify at https://github.com/happybeing/vdash/issues):
info!("Total payment of {reward_amount:?} atto tokens accepted for record {pretty_key}");
Expand All @@ -666,7 +669,9 @@ impl Node {
#[cfg(feature = "loud")]
{
println!("🌟🌟🌟🌟🌟🌟🌟🌟🌟🌟 RECEIVED REWARD 🌟🌟🌟🌟🌟🌟🌟🌟🌟🌟");
println!("Total payment of {reward_amount:?} atto tokens accepted for record {pretty_key}");
println!(
"Total payment of {reward_amount:?} atto tokens accepted for record {pretty_key}"
);
println!("🌟🌟🌟🌟🌟🌟🌟🌟🌟🌟🌟🌟🌟🌟🌟🌟🌟🌟🌟🌟🌟🌟🌟🌟🌟🌟🌟🌟🌟🌟🌟🌟🌟");
}

Expand Down
2 changes: 2 additions & 0 deletions autonomi/src/client/data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,8 @@ pub enum CostError {
CouldNotGetStoreCosts(NetworkError),
#[error("Failed to serialize {0}")]
Serialization(String),
#[error("Payment vault error: {0:?}")]
PaymentVaultError(ant_evm::payment_vault::error::Error),
}

impl Client {
Expand Down
1 change: 1 addition & 0 deletions autonomi/src/client/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

pub mod address;
pub mod payment;
pub mod quote;

#[cfg(feature = "data")]
pub mod archive;
Expand Down
60 changes: 37 additions & 23 deletions autonomi/src/client/quote.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,16 @@
// KIND, either express or implied. Please review the Licences for the specific language governing
// permissions and limitations relating to use of the SAFE Network Software.

use ant_evm::{PaymentQuote, ProofOfPayment, QuoteHash, TxHash};
use super::{data::CostError, Client};
use crate::client::payment::Receipt;
use crate::EvmNetwork;
use ant_evm::payment_vault::get_quote;
use ant_evm::{Amount, AttoTokens, QuotePayment};
use ant_evm::{ProofOfPayment, QuoteHash, TxHash};
use ant_networking::{Network, NetworkError, SelectedQuotes};
use ant_protocol::{
storage::ChunkAddress,
NetworkAddress,
};
use xor_name::XorName;
use ant_protocol::{storage::ChunkAddress, NetworkAddress};
use std::collections::{BTreeMap, HashMap};

use crate::client::payment::Receipt;
use super::{data::CostError, Client};
use xor_name::XorName;

pub struct QuotesToPay {
pub nodes_to_pay: Vec<QuotePayment>,
Expand All @@ -29,6 +27,7 @@ pub struct QuotesToPay {
impl Client {
pub(crate) async fn get_store_quotes(
&self,
network: &EvmNetwork,
content_addrs: impl Iterator<Item = XorName>,
) -> Result<HashMap<XorName, QuotesToPay>, CostError> {
let futures: Vec<_> = content_addrs
Expand All @@ -39,23 +38,38 @@ impl Client {
let quotes = futures::future::try_join_all(futures).await?;

let mut quotes_to_pay_per_addr = HashMap::new();
for (content_addr, quotes) in quotes {
// NB TODO: get cost from smart contract for each quote and set this value to the median of all quotes!
let cost_per_node = Amount::from(1);

for (content_addr, selected_quotes) in quotes {
let mut prices: Vec<Amount> = vec![];

for quote in selected_quotes.quotes {
let price = get_quote(network, quote.1.quoting_metrics.clone()).await?;
prices.push(price);
}

// TODO: set the cost per node by picking the median price of the prices above @anselme
let cost_per_node = Amount::from(1);

// NB TODO: that's all the nodes except the invalid ones (rejected by smart contract)
let nodes_to_pay: Vec<_> = quotes.iter().map(|(_, q)| (q.hash(), q.rewards_address, cost_per_node)).collect();

let nodes_to_pay: Vec<_> = selected_quotes
.quotes
.iter()
.map(|(_, q)| (q.hash(), q.rewards_address, cost_per_node))
.collect();

// NB TODO: that's the lower half (quotes under or equal to the median price)
let nodes_to_upload_to = quotes.clone();
let nodes_to_upload_to = quotes.clone();

let total_cost = cost_per_node * Amount::from(nodes_to_pay.len());
quotes_to_pay_per_addr.insert(content_addr, QuotesToPay {
nodes_to_pay,
nodes_to_upload_to,
cost_per_node: AttoTokens::from_atto(cost_per_node),
total_cost: AttoTokens::from_atto(total_cost),
});
quotes_to_pay_per_addr.insert(
content_addr,
QuotesToPay {
nodes_to_pay,
nodes_to_upload_to,
cost_per_node: AttoTokens::from_atto(cost_per_node),
total_cost: AttoTokens::from_atto(total_cost),
},
);
}

Ok(quotes_to_pay_per_addr)
Expand All @@ -66,7 +80,7 @@ impl Client {
async fn fetch_store_quote(
network: &Network,
content_addr: XorName,
) -> Result<Vec<SelectedQuotes>, NetworkError> {
) -> Result<SelectedQuotes, NetworkError> {
network
.get_store_quote_from_network(
NetworkAddress::from_chunk_address(ChunkAddress::new(content_addr)),
Expand All @@ -79,7 +93,7 @@ async fn fetch_store_quote(
async fn fetch_store_quote_with_retries(
network: &Network,
content_addr: XorName,
) -> Result<(XorName, Vec<SelectedQuotes>), CostError> {
) -> Result<(XorName, SelectedQuotes), CostError> {
let mut retries = 0;

loop {
Expand Down
84 changes: 5 additions & 79 deletions autonomi/src/client/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,25 +7,22 @@
// permissions and limitations relating to use of the SAFE Network Software.

use crate::client::payment::Receipt;
use ant_evm::{EvmWallet, ProofOfPayment, QuotePayment};
use ant_networking::{
GetRecordCfg, Network, NetworkError, SelectedQuotes, PutRecordCfg, VerificationKind,
};
use ant_evm::{EvmWallet, ProofOfPayment};
use ant_networking::{GetRecordCfg, PutRecordCfg, VerificationKind};
use ant_protocol::{
messages::ChunkProof,
storage::{try_serialize_record, Chunk, ChunkAddress, RecordKind, RetryStrategy},
NetworkAddress,
storage::{try_serialize_record, Chunk, RecordKind, RetryStrategy},
};
use bytes::Bytes;
use futures::stream::{FuturesUnordered, StreamExt};
use libp2p::kad::{Quorum, Record};
use rand::{thread_rng, Rng};
use self_encryption::{decrypt_full_set, DataMap, EncryptedChunk};
use std::{collections::HashMap, future::Future, num::NonZero};
use std::{future::Future, num::NonZero};
use xor_name::XorName;

use super::{
data::{CostError, GetError, PayError, PutError, CHUNK_DOWNLOAD_BATCH_SIZE},
data::{GetError, PayError, PutError, CHUNK_DOWNLOAD_BATCH_SIZE},
Client,
};
use crate::self_encryption::DataMapLevel;
Expand Down Expand Up @@ -193,77 +190,6 @@ impl Client {

Ok((proofs, skipped_chunks))
}

pub(crate) async fn get_store_quotes(
&self,
content_addrs: impl Iterator<Item = XorName>,
) -> Result<HashMap<XorName, SelectedQuotes>, CostError> {
let futures: Vec<_> = content_addrs
.into_iter()
.map(|content_addr| fetch_store_quote_with_retries(&self.network, content_addr))
.collect();

let quotes = futures::future::try_join_all(futures).await?;

Ok(quotes.into_iter().collect::<HashMap<XorName, SelectedQuotes>>())
}
}

/// Fetch a store quote for a content address with a retry strategy.
async fn fetch_store_quote_with_retries(
network: &Network,
content_addr: XorName,
) -> Result<(XorName, SelectedQuotes), CostError> {
let mut retries = 0;

loop {
match fetch_store_quote(network, content_addr).await {
Ok(quote) => {
break Ok((content_addr, quote));
}
Err(err) if retries < 2 => {
retries += 1;
error!("Error while fetching store quote: {err:?}, retry #{retries}");
}
Err(err) => {
error!(
"Error while fetching store quote: {err:?}, stopping after {retries} retries"
);
break Err(CostError::CouldNotGetStoreQuote(content_addr));
}
}
}
}

/// Fetch a store quote for a content address.
async fn fetch_store_quote(
network: &Network,
content_addr: XorName,
) -> Result<SelectedQuotes, NetworkError> {
network
.get_store_costs_from_network(
NetworkAddress::from_chunk_address(ChunkAddress::new(content_addr)),
vec![],
)
.await
}

/// Form to be executed payments and already executed payments from a cost map.
pub(crate) fn extract_quote_payments(
cost_map: &HashMap<XorName, SelectedQuotes>,
) -> (Vec<QuotePayment>, Vec<XorName>) {
let mut to_be_paid = vec![];
let mut already_paid = vec![];

for (chunk_address, (_, _, quote)) in cost_map.iter() {
if quote.cost.is_zero() {
already_paid.push(*chunk_address);
} else {
to_be_paid.push((quote.hash(), quote.rewards_address, quote.cost.as_atto()));
}
}

(to_be_paid, already_paid)
}

pub(crate) async fn process_tasks_with_max_concurrency<I, R>(tasks: I, batch_size: usize) -> Vec<R>
Expand Down
1 change: 1 addition & 0 deletions evmlib/src/contract/payment_vault/implementation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use alloy::network::{Network, ReceiptResponse, TransactionBuilder};
use alloy::providers::Provider;
use alloy::transports::Transport;

// Payment Vault contract byte code
const BYTE_CODE: &str = "0x60a060405230608052348015610013575f5ffd5b5061001c610021565b6100d3565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000900460ff16156100715760405163f92ee8a960e01b815260040160405180910390fd5b80546001600160401b03908116146100d05780546001600160401b0319166001600160401b0390811782556040519081527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b50565b608051610ef76100f95f395f818161064d0152818161067601526107ba0152610ef75ff3fe6080604052600436106100bf575f3560e01c8063715018a61161007c578063ad3cb1cc11610057578063ad3cb1cc14610253578063b6c2141b14610290578063cd6dc687146102af578063f2fde38b146102ce575f5ffd5b8063715018a6146101d45780638da5cb5b146101e8578063a69bf4a314610224575f5ffd5b80630716326d146100c35780633c150bf214610132578063474740b1146101605780634ec42e8e146101745780634f1ef286146101ab57806352d1902d146101c0575b5f5ffd5b3480156100ce575f5ffd5b506101086100dd366004610bc4565b600260208190525f91825260409091208054600182015491909201546001600160a01b039092169183565b604080516001600160a01b0390941684526020840192909252908201526060015b60405180910390f35b34801561013d575f5ffd5b5061015261014c366004610bf1565b50600190565b604051908152602001610129565b34801561016b575f5ffd5b506101525f5481565b34801561017f575f5ffd5b50600154610193906001600160a01b031681565b6040516001600160a01b039091168152602001610129565b6101be6101b9366004610c33565b6102ed565b005b3480156101cb575f5ffd5b5061015261030c565b3480156101df575f5ffd5b506101be610327565b3480156101f3575f5ffd5b507f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546001600160a01b0316610193565b34801561022f575f5ffd5b5061024361023e366004610cf9565b61033a565b6040519015158152602001610129565b34801561025e575f5ffd5b50610283604051806040016040528060058152602001640352e302e360dc1b81525081565b6040516101299190610d37565b34801561029b575f5ffd5b506101be6102aa366004610d6c565b6103b6565b3480156102ba575f5ffd5b506101be6102c9366004610ddd565b6104a3565b3480156102d9575f5ffd5b506101be6102e8366004610e07565b610600565b6102f5610642565b6102fe826106e6565b61030882826106ee565b5050565b5f6103156107af565b505f516020610ea25f395f51905f5290565b61032f6107f8565b6103385f610853565b565b6040808201355f90815260026020818152838320845160608101865281546001600160a01b031681526001820154818401819052919093015494830194909452919290918401351480156103ae57506103966020840184610e07565b6001600160a01b0316815f01516001600160a01b0316145b949350505050565b5f5481908111156103da57604051630d67f41160e21b815260040160405180910390fd5b5f5b8181101561049d57368484838181106103f7576103f7610e22565b60600291909101915061042b9050336104136020840184610e07565b6001546001600160a01b0316919060208501356108c3565b6040808201355f90815260026020522081906104478282610e36565b505060408101356020820180359061045f9084610e07565b6001600160a01b03167ff998960b1c6f0e0e89b7bbe6b6fbf3e03e6f08eee5b8430877d8adb8e149d58060405160405180910390a4506001016103dc565b50505050565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a008054600160401b810460ff16159067ffffffffffffffff165f811580156104e85750825b90505f8267ffffffffffffffff1660011480156105045750303b155b905081158015610512575080155b156105305760405163f92ee8a960e01b815260040160405180910390fd5b845467ffffffffffffffff19166001178555831561055a57845460ff60401b1916600160401b1785555b6001600160a01b03871661058157604051632d06160b60e21b815260040160405180910390fd5b600180546001600160a01b0319166001600160a01b0389161790555f8690556105a93361091d565b6105b161092e565b83156105f757845460ff60401b19168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b50505050505050565b6106086107f8565b6001600160a01b03811661063657604051631e4fbdf760e01b81525f60048201526024015b60405180910390fd5b61063f81610853565b50565b306001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614806106c857507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166106bc5f516020610ea25f395f51905f52546001600160a01b031690565b6001600160a01b031614155b156103385760405163703e46dd60e11b815260040160405180910390fd5b61063f6107f8565b816001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa925050508015610748575060408051601f3d908101601f1916820190925261074591810190610e74565b60015b61077057604051634c9c8ce360e01b81526001600160a01b038316600482015260240161062d565b5f516020610ea25f395f51905f5281146107a057604051632a87526960e21b81526004810182905260240161062d565b6107aa8383610936565b505050565b306001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146103385760405163703e46dd60e11b815260040160405180910390fd5b3361082a7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546001600160a01b031690565b6001600160a01b0316146103385760405163118cdaa760e01b815233600482015260240161062d565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930080546001600160a01b031981166001600160a01b03848116918217845560405192169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a3505050565b604080516001600160a01b0385811660248301528416604482015260648082018490528251808303909101815260849091019091526020810180516001600160e01b03166323b872dd60e01b17905261049d90859061098b565b6109256109f7565b61063f81610a40565b6103386109f7565b61093f82610a48565b6040516001600160a01b038316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a2805115610983576107aa8282610aab565b610308610b1d565b5f5f60205f8451602086015f885af1806109aa576040513d5f823e3d81fd5b50505f513d915081156109c15780600114156109ce565b6001600160a01b0384163b155b1561049d57604051635274afe760e01b81526001600160a01b038516600482015260240161062d565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a0054600160401b900460ff1661033857604051631afcd79f60e31b815260040160405180910390fd5b6106086109f7565b806001600160a01b03163b5f03610a7d57604051634c9c8ce360e01b81526001600160a01b038216600482015260240161062d565b5f516020610ea25f395f51905f5280546001600160a01b0319166001600160a01b0392909216919091179055565b60605f5f846001600160a01b031684604051610ac79190610e8b565b5f60405180830381855af49150503d805f8114610aff576040519150601f19603f3d011682016040523d82523d5f602084013e610b04565b606091505b5091509150610b14858383610b3c565b95945050505050565b34156103385760405163b398979f60e01b815260040160405180910390fd5b606082610b5157610b4c82610b9b565b610b94565b8151158015610b6857506001600160a01b0384163b155b15610b9157604051639996b31560e01b81526001600160a01b038516600482015260240161062d565b50805b9392505050565b805115610bab5780518082602001fd5b60405163d6bda27560e01b815260040160405180910390fd5b5f60208284031215610bd4575f5ffd5b5035919050565b5f60c08284031215610beb575f5ffd5b50919050565b5f60c08284031215610c01575f5ffd5b610b948383610bdb565b6001600160a01b038116811461063f575f5ffd5b634e487b7160e01b5f52604160045260245ffd5b5f5f60408385031215610c44575f5ffd5b8235610c4f81610c0b565b9150602083013567ffffffffffffffff811115610c6a575f5ffd5b8301601f81018513610c7a575f5ffd5b803567ffffffffffffffff811115610c9457610c94610c1f565b604051601f8201601f19908116603f0116810167ffffffffffffffff81118282101715610cc357610cc3610c1f565b604052818152828201602001871015610cda575f5ffd5b816020840160208301375f602083830101528093505050509250929050565b5f5f828403610120811215610d0c575f5ffd5b610d168585610bdb565b9250606060bf1982011215610d29575f5ffd5b5060c0830190509250929050565b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f83011684010191505092915050565b5f5f60208385031215610d7d575f5ffd5b823567ffffffffffffffff811115610d93575f5ffd5b8301601f81018513610da3575f5ffd5b803567ffffffffffffffff811115610db9575f5ffd5b856020606083028401011115610dcd575f5ffd5b6020919091019590945092505050565b5f5f60408385031215610dee575f5ffd5b8235610df981610c0b565b946020939093013593505050565b5f60208284031215610e17575f5ffd5b8135610b9481610c0b565b634e487b7160e01b5f52603260045260245ffd5b8135610e4181610c0b565b81546001600160a01b0319166001600160a01b039190911617815560208201356001820155604090910135600290910155565b5f60208284031215610e84575f5ffd5b5051919050565b5f82518060208501845e5f92019182525091905056fe360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbca26469706673582212203894ca52be6e6323aa3d296efd566c7f21d1723d4c66c56aed8a5f75a96b579d64736f6c634300081c0033";

pub async fn deploy<T, P, N>(provider: &P) -> Address
Expand Down
16 changes: 16 additions & 0 deletions evmlib/src/contract/payment_vault/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,22 @@
use crate::common::Amount;
use crate::contract::payment_vault::handler::PaymentVaultHandler;
use crate::quoting_metrics::QuotingMetrics;
use crate::utils::http_provider;
use crate::Network;

pub mod error;
pub mod handler;
pub mod implementation;
pub mod interface;

pub const MAX_TRANSFERS_PER_TRANSACTION: usize = 256;

/// Helper function to return a quote for the given quoting metrics
pub async fn get_quote(
network: &Network,
quoting_metrics: QuotingMetrics,
) -> Result<Amount, error::Error> {
let provider = http_provider(network.rpc_url().clone());
let payment_vault = PaymentVaultHandler::new(*network.data_payments_address(), provider);
payment_vault.get_quote(quoting_metrics).await
}
Loading

0 comments on commit 34d7004

Please sign in to comment.