diff --git a/src/_zkapauthorizer/_storage_client.py b/src/_zkapauthorizer/_storage_client.py index 21e2fed5343dca9ce030a898dc56eb0fa137c88a..8b41b21b6b9115104b51380f479459ab1e7cfa4e 100644 --- a/src/_zkapauthorizer/_storage_client.py +++ b/src/_zkapauthorizer/_storage_client.py @@ -40,9 +40,9 @@ from .storage_common import ( add_lease_message, allocate_buckets_message, get_required_new_passes_for_mutable_write, - has_writes, pass_value_attribute, required_passes, + get_write_sharenums, slot_testv_and_readv_and_writev_message, ) @@ -443,7 +443,8 @@ class ZKAPAuthorizerStorageClient(object): ) in tw_vectors.items() } - if has_writes(tw_vectors): + write_sharenums = get_write_sharenums(tw_vectors) + if len(write_sharenums) > 0: # When performing writes, if we're increasing the storage # requirement, we need to spend more passes. Unfortunately we # don't know what the current storage requirements are at this @@ -465,6 +466,9 @@ class ZKAPAuthorizerStorageClient(object): sharenum: stat.size for (sharenum, stat) in stats.items() if stat.lease_expiration > now + # Also, the size of any share we're not writing to doesn't + # matter. + and sharenum in write_sharenums } # Determine the cost of the new storage for the operation. num_passes = get_required_new_passes_for_mutable_write( diff --git a/src/_zkapauthorizer/_storage_server.py b/src/_zkapauthorizer/_storage_server.py index 607dacac6fe515eeda75e87805cf477c216638a8..367120a5ce4d1b9663a67683d723bf8618d05505 100644 --- a/src/_zkapauthorizer/_storage_server.py +++ b/src/_zkapauthorizer/_storage_server.py @@ -56,6 +56,7 @@ from .storage_common import ( get_required_new_passes_for_mutable_write, pass_value_attribute, required_passes, + get_write_sharenums, slot_testv_and_readv_and_writev_message, ) @@ -763,25 +764,8 @@ def get_writev_price(storage_server, pass_value, storage_index, tw_vectors, now) get_share_sizes( storage_server, storage_index, - # Consider the size of *all* shares even if they're not being - # written. If they have an unexpired lease then we can apply some - # or all of the remainder of the value of that lease towards this - # operation. - # - # For example, if there are 5 0.5 MB shares already present then 5 - # ZKAPs (assuming a ZKAP value of 1 MB-month) have been spent to - # store them while only 2.5 MB of storage has been allocated. - # This means we could accept another 2.5 MB of data for storage at - # no cost to the client while still having been completely paid - # for the storage committed. - # - # This is sort of a weird trick to try to reduce the impact of - # ZKAP value lost to the rounding scheme in use. There's a good - # chance there are better solutions waiting to be discovered that - # would obsolete this logic. Note that whatever the logic here, - # it must agree with the client-side logic so that both server and - # client come to the same conclusion regarding price. - sharenums=None, + # Here's how we restrict the result to only written shares. + sharenums=get_write_sharenums(tw_vectors), ), ) diff --git a/src/_zkapauthorizer/storage_common.py b/src/_zkapauthorizer/storage_common.py index 554c3551d8308fa10720f36cfc46024ad962a737..5060f3a0cd82d25579d6b01fa4bb223fad4b5184 100644 --- a/src/_zkapauthorizer/storage_common.py +++ b/src/_zkapauthorizer/storage_common.py @@ -203,7 +203,7 @@ def has_writes(tw_vectors): ) -def get_sharenums(tw_vectors): +def get_write_sharenums(tw_vectors): """ :param tw_vectors: See ``allmydata.interfaces.TestAndWriteVectorsForShares``. diff --git a/src/_zkapauthorizer/tests/strategies.py b/src/_zkapauthorizer/tests/strategies.py index 567c94405e6aac2009255ead776784e22ab95bad..d14a62dfb110223846b4b8a772ea6e3dfe3a59e2 100644 --- a/src/_zkapauthorizer/tests/strategies.py +++ b/src/_zkapauthorizer/tests/strategies.py @@ -809,7 +809,10 @@ def slot_test_and_write_vectors(): slot_test_vectors(), slot_data_vectors(), one_of( + # The new length might be omitted completely. just(None), + # Or it might be given as an integer. Allow a zero size which + # means "delete this share" in this context. sizes(), ), )