Skip to content

Commit

Permalink
Merge pull request #2517 from mickvandijke/feat-upgradable-smart-cont…
Browse files Browse the repository at this point in the history
…racts-and-updated-quotation-flow

Feat upgradable smart contracts and updated quotation flow
  • Loading branch information
maqi authored Dec 10, 2024
2 parents e8bb869 + 61f0f22 commit d89cca5
Show file tree
Hide file tree
Showing 17 changed files with 671 additions and 649 deletions.
494 changes: 73 additions & 421 deletions Cargo.lock

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion autonomi/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ wasm-bindgen-futures = "0.4.43"
xor_name = "5.0.0"

[dev-dependencies]
alloy = { version = "0.5.3", default-features = false, features = ["std", "reqwest-rustls-tls", "provider-anvil-node", "sol-types", "json", "signers", "contract", "signer-local", "network"] }
alloy = { version = "0.7.3", default-features = false, features = ["contract", "json-rpc", "network", "node-bindings", "provider-http", "reqwest-rustls-tls", "rpc-client", "rpc-types", "signer-local", "std"] }
ant-logging = { path = "../ant-logging", version = "0.2.40" }
ant-peers-acquisition = { path = "../ant-peers-acquisition", version = "0.5.7" }
eyre = "0.6.5"
Expand Down
14 changes: 3 additions & 11 deletions autonomi/src/client/payment.rs
Original file line number Diff line number Diff line change
@@ -1,17 +1,14 @@
use crate::client::data::PayError;
use crate::client::quote::StoreQuote;
use crate::Client;
use ant_evm::{AttoTokens, EncodedPeerId, EvmWallet, ProofOfPayment, QuoteHash, TxHash};
use std::collections::{BTreeMap, HashMap};
use ant_evm::{AttoTokens, EncodedPeerId, EvmWallet, ProofOfPayment};
use std::collections::HashMap;
use xor_name::XorName;

/// Contains the proof of payments for each XOR address and the amount paid
pub type Receipt = HashMap<XorName, (ProofOfPayment, AttoTokens)>;

pub fn receipt_from_store_quotes_and_payments(
quotes: StoreQuote,
payments: BTreeMap<QuoteHash, TxHash>,
) -> Receipt {
pub fn receipt_from_store_quotes(quotes: StoreQuote) -> Receipt {
let mut receipt = Receipt::new();

for (content_addr, quote_for_address) in quotes.0 {
Expand All @@ -22,11 +19,6 @@ pub fn receipt_from_store_quotes_and_payments(
};

for (peer_id, quote, _amount) in quote_for_address.0 {
// skip quotes that haven't been paid
if !payments.contains_key(&quote.hash()) {
continue;
}

proof_of_payment
.peer_quotes
.push((EncodedPeerId::from(peer_id), quote));
Expand Down
23 changes: 23 additions & 0 deletions autonomi/src/client/quote.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,16 @@
use super::{data::CostError, Client};
use ant_evm::payment_vault::get_market_price;
use ant_evm::{Amount, PaymentQuote, QuotePayment};
use ant_networking::target_arch::{sleep, Duration, Instant};
use ant_networking::{Network, NetworkError};
use ant_protocol::{storage::ChunkAddress, NetworkAddress};
use libp2p::PeerId;
use std::collections::HashMap;
use xor_name::XorName;

// set rate limit to 2 req/s
const TIME_BETWEEN_RPC_CALLS_IN_MS: u64 = 500;

/// A quote for a single address
pub struct QuoteForAddress(pub(crate) Vec<(PeerId, PaymentQuote, Amount)>);

Expand Down Expand Up @@ -63,15 +67,34 @@ impl Client {
.collect();
let raw_quotes_per_addr = futures::future::try_join_all(futures).await?;

debug!("Fetched store quotes: {raw_quotes_per_addr:?}");

// choose the quotes to pay for each address
let mut quotes_to_pay_per_addr = HashMap::new();
for (content_addr, raw_quotes) in raw_quotes_per_addr {
// ask smart contract for the market price
let mut prices = vec![];

// rate limit
let mut maybe_last_call: Option<Instant> = None;

for (peer, quote) in raw_quotes {
// NB TODO @mick we need to batch this smart contract call
// check if we have to wait for the rate limit
if let Some(last_call) = maybe_last_call {
let elapsed = Instant::now() - last_call;
let time_to_sleep_ms =
TIME_BETWEEN_RPC_CALLS_IN_MS as u128 - elapsed.as_millis();
if time_to_sleep_ms > 0 {
sleep(Duration::from_millis(time_to_sleep_ms as u64)).await;
}
}

let price =
get_market_price(&self.evm_network, quote.quoting_metrics.clone()).await?;

maybe_last_call = Some(Instant::now());

prices.push((peer, quote, price));
}

Expand Down
6 changes: 3 additions & 3 deletions autonomi/src/client/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
// 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 crate::client::payment::{receipt_from_store_quotes_and_payments, Receipt};
use crate::client::payment::{receipt_from_store_quotes, Receipt};
use ant_evm::{EvmWallet, ProofOfPayment};
use ant_networking::{GetRecordCfg, PutRecordCfg, VerificationKind};
use ant_protocol::{
Expand Down Expand Up @@ -174,7 +174,7 @@ impl Client {
// TODO: the error might contain some succeeded quote payments as well. These should be returned on err, so that they can be skipped when retrying.
// TODO: retry when it fails?
// Execute chunk payments
let payments = wallet
let _payments = wallet
.pay_for_quotes(quotes.payments())
.await
.map_err(|err| PayError::from(err.0))?;
Expand All @@ -190,7 +190,7 @@ impl Client {
skipped_chunks
);

let receipt = receipt_from_store_quotes_and_payments(quotes, payments);
let receipt = receipt_from_store_quotes(quotes);

Ok(receipt)
}
Expand Down
6 changes: 4 additions & 2 deletions autonomi/tests/external_signer.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
#![cfg(feature = "external-signer")]

use alloy::network::TransactionBuilder;
use alloy::providers::Provider;
use ant_evm::{QuoteHash, TxHash};
use ant_logging::LogBuilder;
use autonomi::client::archive::Metadata;
use autonomi::client::archive_private::PrivateArchive;
use autonomi::client::external_signer::encrypt_data;
use autonomi::client::payment::Receipt;
use autonomi::client::payment::{receipt_from_store_quotes_and_payments, Receipt};
use autonomi::client::vault::user_data::USER_DATA_VAULT_CONTENT_IDENTIFIER;
use autonomi::client::vault::VaultSecretKey;
use autonomi::{Client, Wallet};
Expand Down Expand Up @@ -92,7 +94,7 @@ async fn pay_for_content_addresses(
}

// Payment proofs
Ok(receipt_from_quotes_and_payments(&quotes, &payments))
Ok(receipt_from_store_quotes_and_payments(&quotes, payments))
}

// Example of how put would be done using external signers.
Expand Down
147 changes: 88 additions & 59 deletions evmlib/abi/IPaymentVault.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,19 @@
[
{
"inputs": [],
"name": "AntTokenNull",
"type": "error"
},
{
"inputs": [],
"name": "BatchLimitExceeded",
"type": "error"
},
{
"inputs": [],
"name": "InvalidInputLength",
"type": "error"
},
{
"anonymous": false,
"inputs": [
Expand All @@ -24,16 +39,6 @@
"name": "DataPaymentMade",
"type": "event"
},
{
"inputs": [],
"name": "AntTokenNull",
"type": "error"
},
{
"inputs": [],
"name": "BatchLimitExceeded",
"type": "error"
},
{
"inputs": [
{
Expand Down Expand Up @@ -120,72 +125,96 @@
{
"components": [
{
"internalType": "uint256",
"name": "closeRecordsStored",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "maxRecords",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "receivedPaymentCount",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "liveTime",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "networkDensity",
"type": "uint256"
"components": [
{
"internalType": "uint256",
"name": "closeRecordsStored",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "maxRecords",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "receivedPaymentCount",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "liveTime",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "networkDensity",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "networkSize",
"type": "uint256"
}
],
"internalType": "struct IPaymentVault.QuotingMetrics",
"name": "metrics",
"type": "tuple"
},
{
"internalType": "uint256",
"name": "networkSize",
"type": "uint256"
"components": [
{
"internalType": "address",
"name": "rewardsAddress",
"type": "address"
},
{
"internalType": "uint256",
"name": "amount",
"type": "uint256"
},
{
"internalType": "bytes32",
"name": "quoteHash",
"type": "bytes32"
}
],
"internalType": "struct IPaymentVault.DataPayment",
"name": "dataPayment",
"type": "tuple"
}
],
"internalType": "struct IPaymentVault.QuotingMetrics",
"name": "_metrics",
"type": "tuple"
},
"internalType": "struct IPaymentVault.PaymentVerification[]",
"name": "_payments",
"type": "tuple[]"
}
],
"name": "verifyPayment",
"outputs": [
{
"components": [
{
"internalType": "address",
"name": "rewardsAddress",
"type": "address"
"internalType": "bytes32",
"name": "quoteHash",
"type": "bytes32"
},
{
"internalType": "uint256",
"name": "amount",
"name": "amountPaid",
"type": "uint256"
},
{
"internalType": "bytes32",
"name": "quoteHash",
"type": "bytes32"
"internalType": "bool",
"name": "isValid",
"type": "bool"
}
],
"internalType": "struct IPaymentVault.DataPayment",
"name": "_payment",
"type": "tuple"
}
],
"name": "verifyPayment",
"outputs": [
{
"internalType": "bool",
"name": "isValid",
"type": "bool"
"internalType": "struct IPaymentVault.PaymentVerificationResult[3]",
"name": "verificationResults",
"type": "tuple[3]"
}
],
"stateMutability": "view",
"type": "function"
}
]
]
Loading

0 comments on commit d89cca5

Please sign in to comment.