Skip to content

feat: use subsidies contract to proxy register blob call #2151

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

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
150 changes: 75 additions & 75 deletions crates/walrus-sui/src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,7 @@ use sui_sdk::{
},
types::base_types::ObjectID,
};
use sui_types::{
TypeTag,
base_types::SuiAddress,
event::EventID,
transaction::{Argument, TransactionData},
};
use sui_types::{TypeTag, base_types::SuiAddress, event::EventID, transaction::TransactionData};
use tokio::sync::Mutex;
use tokio_stream::Stream;
use tracing::Level;
Expand Down Expand Up @@ -1471,14 +1466,34 @@ impl SuiContractClientInner {
return Ok(vec![]);
}

let subsidies_package_id = self.read_client.get_subsidies_package_id();

let expected_num_blobs = blob_metadata_and_storage.len();
tracing::debug!(num_blobs = expected_num_blobs, "starting to register blobs");
let mut pt_builder = self.transaction_builder()?;
// Build a ptb to include all register blob commands for all blobs.
for (blob_metadata, storage) in blob_metadata_and_storage.into_iter() {
pt_builder
.register_blob(storage.id.into(), blob_metadata, persistence)
.await?;
match subsidies_package_id {
Some(pkg_id) => {
pt_builder
.register_blob_with_subsidies(
storage.id.into(),
blob_metadata,
persistence,
pkg_id,
)
.await?;
}
None => {
pt_builder
.register_blob_without_subsidies(
storage.id.into(),
blob_metadata,
persistence,
)
.await?;
}
};
}
let transaction = pt_builder.build_transaction_data(self.gas_budget).await?;
let res = self
Expand Down Expand Up @@ -1515,11 +1530,12 @@ impl SuiContractClientInner {
match subsidies_package_id {
Some(pkg_id) => {
match self
.reserve_and_register_blobs_with_subsidies(
.reserve_and_register_blobs_inner(
epochs_ahead,
blob_metadata_list.clone(),
persistence,
pkg_id,
true,
)
.await
{
Expand All @@ -1531,90 +1547,40 @@ impl SuiContractClientInner {
"Walrus package version mismatch in subsidies call, \
falling back to direct contract call"
);
self.reserve_and_register_blobs_without_subsidies(
self.reserve_and_register_blobs_inner(
epochs_ahead,
blob_metadata_list.clone(),
persistence,
ObjectID::random(),
false,
)
.await
}
Err(e) => Err(e),
}
}
None => {
self.reserve_and_register_blobs_without_subsidies(
self.reserve_and_register_blobs_inner(
epochs_ahead,
blob_metadata_list,
persistence,
ObjectID::random(),
false,
)
.await
}
}
}

/// reserve and register blobs with subsidies
pub async fn reserve_and_register_blobs_with_subsidies(
/// reserve and register blobs inner
pub async fn reserve_and_register_blobs_inner(
&mut self,
epochs_ahead: EpochCount,
blob_metadata_list: Vec<BlobObjectMetadata>,
persistence: BlobPersistence,
subsidies_package_id: ObjectID,
with_subsidies: bool,
) -> SuiClientResult<Vec<Blob>> {
// Use helper for implementing with the subsidies approach
self.reserve_and_register_blobs_impl(
epochs_ahead,
blob_metadata_list,
persistence,
|builder, encoded_size, epochs| {
Box::pin(async move {
builder
.reserve_space_with_subsidies(encoded_size, epochs, subsidies_package_id)
.await
}) as BoxFuture<'_, SuiClientResult<Argument>>
},
)
.await
}

/// reserve and register blobs without subsidies
pub async fn reserve_and_register_blobs_without_subsidies(
&mut self,
epochs_ahead: EpochCount,
blob_metadata_list: Vec<BlobObjectMetadata>,
persistence: BlobPersistence,
) -> SuiClientResult<Vec<Blob>> {
// Use helper for implementing with the non-subsidies approach
self.reserve_and_register_blobs_impl(
epochs_ahead,
blob_metadata_list,
persistence,
|builder, encoded_size, epochs| {
Box::pin(async move {
builder
.reserve_space_without_subsidies(encoded_size, epochs)
.await
}) as BoxFuture<'_, SuiClientResult<Argument>>
},
)
.await
}

/// Common implementation for reserving and registering blobs
async fn reserve_and_register_blobs_impl<F>(
&mut self,
epochs_ahead: EpochCount,
blob_metadata_list: Vec<BlobObjectMetadata>,
persistence: BlobPersistence,
reserve_space_fn: F,
) -> SuiClientResult<Vec<Blob>>
where
F: for<'a> Fn(
&'a mut WalrusPtbBuilder,
u64,
EpochCount,
) -> BoxFuture<'a, SuiClientResult<Argument>>
+ Send,
{
if blob_metadata_list.is_empty() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggestion: This now duplicates a lot of code with reserve_and_register_blobs_without_subsidies. Can we still keep an "inner" function, but instead of passing two closures for reserve and register, we just pass a flag with_subsidies (and then make a case distinction at the relevant points in the function)?

tracing::debug!("no blobs to register");
return Ok(vec![]);
Expand All @@ -1632,8 +1598,23 @@ impl SuiContractClientInner {
let mut main_storage_arg_size = blob_metadata_list
.iter()
.fold(0, |acc, metadata| acc + metadata.encoded_size);
let main_storage_arg =
reserve_space_fn(&mut pt_builder, main_storage_arg_size, epochs_ahead).await?;

let main_storage_arg = match with_subsidies {
true => {
pt_builder
.reserve_space_with_subsidies(
main_storage_arg_size,
epochs_ahead,
subsidies_package_id,
)
.await?
}
false => {
pt_builder
.reserve_space_without_subsidies(main_storage_arg_size, epochs_ahead)
.await?
}
};

for blob_metadata in blob_metadata_list.into_iter() {
// Split off a storage resource, unless the remainder is equal to the required size.
Expand All @@ -1645,14 +1626,33 @@ impl SuiContractClientInner {
} else {
main_storage_arg
};
pt_builder
.register_blob(storage_arg.into(), blob_metadata, persistence)
.await?;

match with_subsidies {
true => {
pt_builder
.register_blob_with_subsidies(
storage_arg.into(),
blob_metadata,
persistence,
subsidies_package_id,
)
.await?
}
false => {
pt_builder
.register_blob_without_subsidies(
storage_arg.into(),
blob_metadata,
persistence,
)
.await?
}
};
}

let transaction = pt_builder.build_transaction_data(self.gas_budget).await?;
let res = self
.sign_and_send_transaction(transaction, "reserve_and_register_blobs_impl")
.sign_and_send_transaction(transaction, "reserve_and_register_blobs_inner")
.await?;
let blob_obj_ids = get_created_sui_object_ids_by_type(
&res,
Expand Down
15 changes: 9 additions & 6 deletions crates/walrus-sui/src/client/read_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -319,8 +319,9 @@ impl SuiReadClient {
let wal_type = sui_client.wal_type_from_package(walrus_package_id).await?;
let subsidies = if let Some(subsidies_object_id) = contract_config.subsidies_object {
let subsidies_package_id = sui_client
.get_subsidies_package_id_from_subsidies_object(subsidies_object_id)
.await?;
.get_subsidies_object(subsidies_object_id)
.await?
.package_id;
Some(Subsidies {
package_id: subsidies_package_id,
object_id: subsidies_object_id,
Expand Down Expand Up @@ -804,8 +805,9 @@ impl SuiReadClient {
pub async fn set_subsidies_object(&self, subsidies_object_id: ObjectID) -> SuiClientResult<()> {
let subsidies_package_id = self
.sui_client
.get_subsidies_package_id_from_subsidies_object(subsidies_object_id)
.await?;
.get_subsidies_object(subsidies_object_id)
.await?
.package_id;
*self.subsidies_mut() = Some(Subsidies {
package_id: subsidies_package_id,
object_id: subsidies_object_id,
Expand Down Expand Up @@ -1170,8 +1172,9 @@ impl ReadClient for SuiReadClient {
if let Some(subsidies) = subsidies {
let new_package_id = self
.sui_client
.get_subsidies_package_id_from_subsidies_object(subsidies.object_id)
.await?;
.get_subsidies_object(subsidies.object_id)
.await?
.package_id;

// Update the package_id if it has changed
if new_package_id != subsidies.package_id {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -887,16 +887,11 @@ impl RetriableSuiClient {
}

/// Checks if the Walrus subsidies object exist on chain and returns the subsidies package ID.
pub(crate) async fn get_subsidies_package_id_from_subsidies_object(
pub(crate) async fn get_subsidies_object(
&self,
subsidies_object_id: ObjectID,
) -> SuiClientResult<ObjectID> {
let subsidies_object = self
.get_sui_object::<Subsidies>(subsidies_object_id)
.await?;

let pkg_id = subsidies_object.package_id;
Ok(pkg_id)
) -> SuiClientResult<Subsidies> {
self.get_sui_object::<Subsidies>(subsidies_object_id).await
}

/// Returns the package ID from the type of the given object.
Expand Down
Loading