Skip to content

Commit a9f5ea6

Browse files
committed
add register blob proxy call to subsidies contract
1 parent 3c4105d commit a9f5ea6

File tree

10 files changed

+211
-59
lines changed

10 files changed

+211
-59
lines changed

contracts/subsidies/Move.lock

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ dependencies = [
4040
]
4141

4242
[move.toolchain-version]
43-
compiler-version = "1.46.0"
43+
compiler-version = "1.46.3"
4444
edition = "2024.beta"
4545
flavor = "sui"
4646

contracts/subsidies/sources/subsidies.move

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,33 @@ public fun reserve_space(
224224
storage
225225
}
226226

227+
/// Proxy Register blob by calling the system contract
228+
public fun register_blob(
229+
self: &mut Subsidies,
230+
system: &mut System,
231+
storage: Storage,
232+
blob_id: u256,
233+
root_hash: u256,
234+
size: u64,
235+
encoding_type: u8,
236+
deletable: bool,
237+
write_payment: &mut Coin<WAL>,
238+
ctx: &mut TxContext,
239+
): Blob {
240+
assert!(self.version == VERSION, EWrongVersion);
241+
let blob = system.register_blob(
242+
storage,
243+
blob_id,
244+
root_hash,
245+
size,
246+
encoding_type,
247+
deletable,
248+
write_payment,
249+
ctx,
250+
);
251+
blob
252+
}
253+
227254
entry fun migrate(subsidies: &mut Subsidies, admin_cap: &AdminCap, package_id: ID) {
228255
check_admin(subsidies, admin_cap);
229256
check_version_upgrade(subsidies);

contracts/wal/Move.lock

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ dependencies = [
2121
]
2222

2323
[move.toolchain-version]
24-
compiler-version = "1.46.0"
24+
compiler-version = "1.46.3"
2525
edition = "2024.beta"
2626
flavor = "sui"
2727

contracts/wal_exchange/Move.lock

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,6 @@ dependencies = [
3030
]
3131

3232
[move.toolchain-version]
33-
compiler-version = "1.46.0"
33+
compiler-version = "1.46.3"
3434
edition = "2024.beta"
3535
flavor = "sui"

contracts/walrus/Move.lock

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ dependencies = [
3030
]
3131

3232
[move.toolchain-version]
33-
compiler-version = "1.46.0"
33+
compiler-version = "1.46.3"
3434
edition = "2024.beta"
3535
flavor = "sui"
3636

crates/walrus-sui/src/client.rs

Lines changed: 95 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ use sui_types::{
4040
use tokio::sync::Mutex;
4141
use tokio_stream::Stream;
4242
use tracing::Level;
43-
use transaction_builder::{WalrusPtbBuilder, MAX_BURNS_PER_PTB};
43+
use transaction_builder::{ArgumentOrOwnedObject, WalrusPtbBuilder, MAX_BURNS_PER_PTB};
4444
use walrus_core::{
4545
ensure,
4646
merkle::Node as MerkleNode,
@@ -1491,15 +1491,34 @@ impl SuiContractClientInner {
14911491
tracing::debug!("no blobs to register");
14921492
return Ok(vec![]);
14931493
}
1494+
let subsidies_package_id = self.read_client.get_subsidies_package_id();
14941495

14951496
let expected_num_blobs = blob_metadata_and_storage.len();
14961497
tracing::debug!(num_blobs = expected_num_blobs, "starting to register blobs");
14971498
let mut pt_builder = self.transaction_builder()?;
14981499
// Build a ptb to include all register blob commands for all blobs.
14991500
for (blob_metadata, storage) in blob_metadata_and_storage.into_iter() {
1500-
pt_builder
1501-
.register_blob(storage.id.into(), blob_metadata, persistence)
1502-
.await?;
1501+
match subsidies_package_id {
1502+
Some(pkg_id) => {
1503+
pt_builder
1504+
.register_blob_with_subsidies(
1505+
storage.id.into(),
1506+
blob_metadata,
1507+
persistence,
1508+
pkg_id,
1509+
)
1510+
.await?;
1511+
}
1512+
None => {
1513+
pt_builder
1514+
.register_blob_without_subsidies(
1515+
storage.id.into(),
1516+
blob_metadata,
1517+
persistence,
1518+
)
1519+
.await?;
1520+
}
1521+
};
15031522
}
15041523
let (ptb, _sui_cost) = pt_builder.finish().await?;
15051524
let res = self.sign_and_send_ptb(ptb, "register_blobs").await?;
@@ -1531,48 +1550,52 @@ impl SuiContractClientInner {
15311550
persistence: BlobPersistence,
15321551
) -> SuiClientResult<Vec<Blob>> {
15331552
let subsidies_package_id = self.read_client.get_subsidies_package_id();
1534-
match subsidies_package_id {
1535-
Some(pkg_id) => {
1536-
match self
1537-
.reserve_and_register_blobs_with_subsidies(
1553+
// If no subsidies package, use the direct method
1554+
let pkg_id = match subsidies_package_id {
1555+
None => {
1556+
return self
1557+
.reserve_wo_subsidies_and_register_blobs_wo_subsidies(
15381558
epochs_ahead,
1539-
blob_metadata_list.clone(),
1559+
blob_metadata_list,
15401560
persistence,
1541-
pkg_id,
15421561
)
1543-
.await
1544-
{
1545-
Ok(result) => Ok(result),
1546-
Err(SuiClientError::TransactionExecutionError(MoveExecutionError::System(
1547-
SystemError::EWrongVersion(_),
1548-
))) => {
1549-
tracing::warn!(
1550-
"Walrus package version mismatch in subsidies call, \
1551-
falling back to direct contract call"
1552-
);
1553-
self.reserve_and_register_blobs_without_subsidies(
1554-
epochs_ahead,
1555-
blob_metadata_list.clone(),
1556-
persistence,
1557-
)
1558-
.await
1559-
}
1560-
Err(e) => Err(e),
1561-
}
1562+
.await;
15621563
}
1563-
None => {
1564-
self.reserve_and_register_blobs_without_subsidies(
1564+
Some(id) => id,
1565+
};
1566+
1567+
let result = self
1568+
.reserve_w_subsidies_and_register_blobs_w_subsidies(
1569+
epochs_ahead,
1570+
blob_metadata_list.clone(),
1571+
persistence,
1572+
pkg_id,
1573+
)
1574+
.await;
1575+
1576+
// Handle version mismatch by falling back to direct call
1577+
match result {
1578+
Ok(result) => Ok(result),
1579+
Err(SuiClientError::TransactionExecutionError(MoveExecutionError::System(
1580+
SystemError::EWrongVersion(_),
1581+
))) => {
1582+
tracing::warn!(
1583+
"Walrus package version mismatch in subsidies call,
1584+
falling back to direct contract call"
1585+
);
1586+
self.reserve_wo_subsidies_and_register_blobs_wo_subsidies(
15651587
epochs_ahead,
15661588
blob_metadata_list,
15671589
persistence,
15681590
)
15691591
.await
15701592
}
1593+
Err(e) => Err(e),
15711594
}
15721595
}
15731596

15741597
/// reserve and register blobs with subsidies
1575-
pub async fn reserve_and_register_blobs_with_subsidies(
1598+
pub async fn reserve_w_subsidies_and_register_blobs_w_subsidies(
15761599
&mut self,
15771600
epochs_ahead: EpochCount,
15781601
blob_metadata_list: Vec<BlobObjectMetadata>,
@@ -1591,12 +1614,23 @@ impl SuiContractClientInner {
15911614
.await
15921615
}) as BoxFuture<'_, SuiClientResult<Argument>>
15931616
},
1617+
|builder, storage_resource, blob_metadata, persistence| {
1618+
Box::pin(async move {
1619+
builder
1620+
.register_blob_with_subsidies(
1621+
storage_resource,
1622+
blob_metadata,
1623+
persistence,
1624+
subsidies_package_id,
1625+
)
1626+
.await
1627+
}) as BoxFuture<'_, SuiClientResult<Argument>>
1628+
},
15941629
)
15951630
.await
15961631
}
15971632

1598-
/// reserve and register blobs without subsidies
1599-
pub async fn reserve_and_register_blobs_without_subsidies(
1633+
pub async fn reserve_wo_subsidies_and_register_blobs_wo_subsidies(
16001634
&mut self,
16011635
epochs_ahead: EpochCount,
16021636
blob_metadata_list: Vec<BlobObjectMetadata>,
@@ -1614,17 +1648,29 @@ impl SuiContractClientInner {
16141648
.await
16151649
}) as BoxFuture<'_, SuiClientResult<Argument>>
16161650
},
1651+
|builder, storage_resource, blob_metadata, persistence| {
1652+
Box::pin(async move {
1653+
builder
1654+
.register_blob_without_subsidies(
1655+
storage_resource,
1656+
blob_metadata,
1657+
persistence,
1658+
)
1659+
.await
1660+
}) as BoxFuture<'_, SuiClientResult<Argument>>
1661+
},
16171662
)
16181663
.await
16191664
}
16201665

16211666
/// Common implementation for reserving and registering blobs
1622-
async fn reserve_and_register_blobs_impl<F>(
1667+
async fn reserve_and_register_blobs_impl<F, G>(
16231668
&mut self,
16241669
epochs_ahead: EpochCount,
16251670
blob_metadata_list: Vec<BlobObjectMetadata>,
16261671
persistence: BlobPersistence,
16271672
reserve_space_fn: F,
1673+
register_blob_fn: G,
16281674
) -> SuiClientResult<Vec<Blob>>
16291675
where
16301676
F: for<'a> Fn(
@@ -1633,6 +1679,13 @@ impl SuiContractClientInner {
16331679
EpochCount,
16341680
) -> BoxFuture<'a, SuiClientResult<Argument>>
16351681
+ Send,
1682+
G: for<'b> Fn(
1683+
&'b mut WalrusPtbBuilder,
1684+
ArgumentOrOwnedObject,
1685+
BlobObjectMetadata,
1686+
BlobPersistence,
1687+
) -> BoxFuture<'b, SuiClientResult<Argument>>
1688+
+ Send,
16361689
{
16371690
if blob_metadata_list.is_empty() {
16381691
tracing::debug!("no blobs to register");
@@ -1664,9 +1717,13 @@ impl SuiContractClientInner {
16641717
} else {
16651718
main_storage_arg
16661719
};
1667-
pt_builder
1668-
.register_blob(storage_arg.into(), blob_metadata, persistence)
1669-
.await?;
1720+
register_blob_fn(
1721+
&mut pt_builder,
1722+
ArgumentOrOwnedObject::from(storage_arg),
1723+
blob_metadata.clone(),
1724+
persistence,
1725+
)
1726+
.await?;
16701727
}
16711728

16721729
let (ptb, _sui_cost) = pt_builder.finish().await?;

crates/walrus-sui/src/client/read_client.rs

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -297,6 +297,7 @@ pub struct SuiReadClient {
297297
staking_obj_initial_version: OnceCell<SequenceNumber>,
298298
subsidies: Arc<RwLock<Option<Subsidies>>>,
299299
wal_type: String,
300+
buyer_subsidy_rate: u16,
300301
}
301302

302303
const MAX_POLLING_INTERVAL: Duration = Duration::from_secs(5);
@@ -315,12 +316,12 @@ impl SuiReadClient {
315316
.type_origin_map_for_package(walrus_package_id)
316317
.await?;
317318
let wal_type = sui_client.wal_type_from_package(walrus_package_id).await?;
319+
let mut buyer_subsidy_rate = 0;
318320
let subsidies = if let Some(subsidies_object_id) = contract_config.subsidies_object {
319-
let subsidies_package_id = sui_client
320-
.get_subsidies_package_id_from_subsidies_object(subsidies_object_id)
321-
.await?;
321+
let subsidies_object = sui_client.get_subsidies_object(subsidies_object_id).await?;
322+
buyer_subsidy_rate = subsidies_object.buyer_subsidy_rate;
322323
Some(Subsidies {
323-
package_id: subsidies_package_id,
324+
package_id: subsidies_object.package_id,
324325
object_id: subsidies_object_id,
325326
subsidies_obj_initial_version: OnceCell::new(),
326327
})
@@ -337,6 +338,7 @@ impl SuiReadClient {
337338
staking_obj_initial_version: OnceCell::new(),
338339
subsidies: Arc::new(RwLock::new(subsidies)),
339340
wal_type,
341+
buyer_subsidy_rate,
340342
})
341343
}
342344

@@ -505,6 +507,14 @@ impl SuiReadClient {
505507
self.sui_client.get_sui_object(node_id).await
506508
}
507509

510+
/// Returns the buyer subsidy rate.
511+
/// A 100% buyer subsidy rate means that the buyer pays 0 WAL for reserving space.
512+
/// If the subsidy contract has a register_blob function,
513+
/// then the buyer will pay 0 WAL for both reserving space and registering the blob.
514+
pub fn get_buyer_subsidy_rate(&self) -> u16 {
515+
self.buyer_subsidy_rate
516+
}
517+
508518
fn walrus_package_id(&self) -> RwLockReadGuard<ObjectID> {
509519
self.walrus_package_id
510520
.read()
@@ -772,8 +782,9 @@ impl SuiReadClient {
772782
pub async fn set_subsidies_object(&self, subsidies_object_id: ObjectID) -> SuiClientResult<()> {
773783
let subsidies_package_id = self
774784
.sui_client
775-
.get_subsidies_package_id_from_subsidies_object(subsidies_object_id)
776-
.await?;
785+
.get_subsidies_object(subsidies_object_id)
786+
.await?
787+
.package_id;
777788
*self.subsidies_mut() = Some(Subsidies {
778789
package_id: subsidies_package_id,
779790
object_id: subsidies_object_id,
@@ -1131,8 +1142,9 @@ impl ReadClient for SuiReadClient {
11311142
if let Some(subsidies) = subsidies {
11321143
let new_package_id = self
11331144
.sui_client
1134-
.get_subsidies_package_id_from_subsidies_object(subsidies.object_id)
1135-
.await?;
1145+
.get_subsidies_object(subsidies.object_id)
1146+
.await?
1147+
.package_id;
11361148

11371149
// Update the package_id if it has changed
11381150
if new_package_id != subsidies.package_id {

crates/walrus-sui/src/client/retry_client/retriable_sui_client.rs

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,11 @@ impl RetriableSuiClient {
190190
.get_coins_stream_retry(address, coin_type)
191191
.filter(|coin: &Coin| future::ready(!exclude.contains(&coin.coin_object_id)))
192192
.take_while(|coin: &Coin| {
193-
let ready = future::ready(total < amount);
193+
let ready = if amount == 0 && total == 0 {
194+
future::ready(true)
195+
} else {
196+
future::ready(total < amount)
197+
};
194198
total += coin.balance as u128;
195199
ready
196200
})
@@ -626,16 +630,15 @@ impl RetriableSuiClient {
626630
}
627631

628632
/// Checks if the Walrus subsidies object exist on chain and returns the subsidies package ID.
629-
pub(crate) async fn get_subsidies_package_id_from_subsidies_object(
633+
pub(crate) async fn get_subsidies_object(
630634
&self,
631635
subsidies_object_id: ObjectID,
632-
) -> SuiClientResult<ObjectID> {
636+
) -> SuiClientResult<Subsidies> {
633637
let subsidies_object = self
634638
.get_sui_object::<Subsidies>(subsidies_object_id)
635639
.await?;
636640

637-
let pkg_id = subsidies_object.package_id;
638-
Ok(pkg_id)
641+
Ok(subsidies_object)
639642
}
640643

641644
/// Returns the package ID from the type of the given object.

0 commit comments

Comments
 (0)