2121from starkware .storage .merkle_tree import MerkleTree
2222from starkware .storage .storage import Storage
2323
24- from .availability_gateway_client import AvailabilityGatewayClient
24+ from .availability_gateway_client import AvailabilityGatewayClient , BadRequest
2525from .custom_validation import is_valid
2626
2727logger = logging .getLogger (__package__ )
@@ -44,7 +44,8 @@ def deserialize(cls, data: bytes) -> 'CommitteeBatchInfo':
4444
4545class Committee :
4646 def __init__ (self , config : dict , private_key : str , storage : Storage ,
47- merkle_storage : Storage , hash_func , availability_gateway ):
47+ merkle_storage : Storage , hash_func ,
48+ availability_gateway : AvailabilityGatewayClient ):
4849 self .storage = storage
4950 self .merkle_storage = merkle_storage
5051 self .hash_func = hash_func
@@ -145,11 +146,43 @@ async def compute_order_root(storage):
145146 await self .storage .set_value (
146147 self .committee_batch_info_key (batch_id ), batch_info .serialize ())
147148
149+ # In StarkEx version 4.5, the height of the order tree has changed. For an old committee
150+ # (i.e. a committee from version 4.0 or below) to work with a version 4.5 backend, the order
151+ # tree height must be checked against the availability gateway, and possibly changed.
152+ # If the configured height doesn't match the height sent in response from the availability
153+ # gateway, assert that the order tree is not validated (self.validate_orders must be False
154+ # to swap order tree heights, otherwise the computed order root is incorrect anyway) and
155+ # that the new height is the expected height in version 4.5 (which is 251).
156+ # This will work when the committee is not validating orders, because in that case, the root
157+ # provided by the availability gateway is the correct root (of the height-251 tree), so when
158+ # the committee blindly signs this root along with the correct height, the claim will be
159+ # approved.
160+ # This patch will be deleted in the version 4.5 committee.
161+ logger .info ("Trying to fetch trades height from the availability gateway" )
162+ # If the API of order_tree_height exist in the Availability Gateway use it. Otherwise,
163+ # stick with the configured configured_trades_height (this can happen if the SE
164+ # Availability Gateway is using an old SE version whcih don't have the
165+ # order_tree_height API).
166+ trades_height = self .orders_merkle_height
167+ try :
168+ trades_height = await self .availability_gateway .order_tree_height ()
169+ if self .orders_merkle_height != trades_height :
170+ assert not validate_orders , (
171+ f"validate_orders is { validate_orders } , but configured trades height "
172+ f"{ self .orders_merkle_height } is not equal to response from the availability "
173+ f"gateway ({ trades_height } ). This indicates that the root of the order "
174+ f"tree was computed incorrectly and the claim will not be approved by the "
175+ f"availability gateway, so there is no point in signing and sending the "
176+ f"signature."
177+ )
178+ except BadRequest :
179+ pass
180+
148181 logger .info (f'Signing batch with sequence number { batch_info .sequence_number } ' )
149182
150183 availability_claim = hash_availability_claim (
151184 batch_info .vaults_root , self .vaults_merkle_height , batch_info .orders_root ,
152- self . orders_merkle_height , batch_info .sequence_number )
185+ trades_height , batch_info .sequence_number )
153186 signature = eth .Account ._sign_hash (availability_claim , self .account .key ).signature .hex ()
154187 return signature , availability_claim .hex ()
155188
@@ -221,4 +254,4 @@ async def async_hash_func(x, y):
221254
222255
223256if __name__ == '__main__' :
224- sys .exit (asyncio .run (main ()))
257+ sys .exit (asyncio .run (main ()))
0 commit comments