Skip to content

Commit 478b072

Browse files
committed
committee v4 forward compatibility patch
1 parent 3cc351b commit 478b072

File tree

3 files changed

+55
-6
lines changed

3 files changed

+55
-6
lines changed

committee/committee/availability_gateway_client.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,11 @@ def _send_request(self, send_method, uri, data=None):
3131
raise BadRequest(res.status_code, res.text)
3232
return res.text
3333

34+
async def order_tree_height(self) -> int:
35+
uri = "/availability_gateway/order_tree_height"
36+
answer = await self._send_request("GET", uri)
37+
return int(answer)
38+
3439
async def get_batch_data(self, batch_id: int) -> Optional[StateUpdate]:
3540
uri = f'/availability_gateway/get_batch_data?batch_id={batch_id}'
3641
answer = self._send_request('GET', uri)

committee/committee/committee.py

Lines changed: 37 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
from starkware.storage.merkle_tree import MerkleTree
2222
from starkware.storage.storage import Storage
2323

24-
from .availability_gateway_client import AvailabilityGatewayClient
24+
from .availability_gateway_client import AvailabilityGatewayClient, BadRequest
2525
from .custom_validation import is_valid
2626

2727
logger = logging.getLogger(__package__)
@@ -44,7 +44,8 @@ def deserialize(cls, data: bytes) -> 'CommitteeBatchInfo':
4444

4545
class 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

223256
if __name__ == '__main__':
224-
sys.exit(asyncio.run(main()))
257+
sys.exit(asyncio.run(main()))

committee/committee/committee_test.py

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,22 @@
1010
from .committee import Committee
1111

1212

13+
ORDER_TREE_HEIGHT = 63
14+
15+
16+
class AvailabilityGatewayClientMock:
17+
def __init__(self):
18+
pass
19+
20+
async def order_tree_height(self) -> int:
21+
return ORDER_TREE_HEIGHT
22+
23+
1324
@pytest.fixture
1425
def committee():
1526
config = {
1627
'VAULTS_MERKLE_HEIGHT': 31,
17-
'ORDERS_MERKLE_HEIGHT': 63,
28+
'ORDERS_MERKLE_HEIGHT': ORDER_TREE_HEIGHT,
1829
'POLLING_INTERVAL': 1,
1930
}
2031

@@ -24,7 +35,7 @@ def committee():
2435
storage=MockStorage(),
2536
merkle_storage=MockStorage(),
2637
hash_func=async_pedersen_hash_func,
27-
availability_gateway=None)
38+
availability_gateway=AvailabilityGatewayClientMock())
2839

2940

3041
@pytest.fixture

0 commit comments

Comments
 (0)