Skip to content

Commit

Permalink
committee v4 forward compatibility patch
Browse files Browse the repository at this point in the history
  • Loading branch information
gkaempfer committed Jul 4, 2022
1 parent 3cc351b commit 844ac3d
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 7 deletions.
7 changes: 6 additions & 1 deletion committee/committee/availability_gateway_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,11 @@ def _send_request(self, send_method, uri, data=None):
raise BadRequest(res.status_code, res.text)
return res.text

async def order_tree_height(self) -> int:
uri = "/availability_gateway/order_tree_height"
answer = self._send_request("GET", uri)
return int(answer)

async def get_batch_data(self, batch_id: int) -> Optional[StateUpdate]:
uri = f'/availability_gateway/get_batch_data?batch_id={batch_id}'
answer = self._send_request('GET', uri)
Expand All @@ -48,4 +53,4 @@ async def send_signature(self, batch_id: int, sig: str, member_key: str, claim_h
logger.error(f'unexpected response: {answer}')
assert False, 'Signature was not accepted'

logger.debug(f'Signature for batch {batch_id} was sent successfully')
logger.debug(f'Signature for batch {batch_id} was sent successfully')
44 changes: 40 additions & 4 deletions committee/committee/committee.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
from starkware.storage.merkle_tree import MerkleTree
from starkware.storage.storage import Storage

from .availability_gateway_client import AvailabilityGatewayClient
from .availability_gateway_client import AvailabilityGatewayClient, BadRequest
from .custom_validation import is_valid

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

class Committee:
def __init__(self, config: dict, private_key: str, storage: Storage,
merkle_storage: Storage, hash_func, availability_gateway):
merkle_storage: Storage, hash_func,
availability_gateway: AvailabilityGatewayClient):
self.storage = storage
self.merkle_storage = merkle_storage
self.hash_func = hash_func
Expand Down Expand Up @@ -145,11 +146,46 @@ async def compute_order_root(storage):
await self.storage.set_value(
self.committee_batch_info_key(batch_id), batch_info.serialize())

# In StarkEx version 4.5, the height of the order tree has changed. For an old committee
# (i.e. a committee from version 4.0 or below) to work with a version 4.5 backend, the order
# tree height must be checked against the availability gateway, and possibly changed.
# If the configured height doesn't match the height sent in response from the availability
# gateway, assert that the order tree is not validated (self.validate_orders must be False
# to swap order tree heights, otherwise the computed order root is incorrect anyway).
# This patch doesn't affect the calculation of the order tree root, only the `trades_height`
# used for signing the batch. Therefore, the patch relies on the committee trusting the
# order root sent from the AvailabilityGateway (This means that it will only work if the
# committee is not validating orders).
# This patch will be deleted in the version 4.5 committee.
logger.info("Trying to fetch trades height from the availability gateway")
# If the API of order_tree_height exists in the Availability Gateway, use it. Otherwise,
# use ORDERS_MERKLE_HEIGHT from the config (this can happen if the SE
# Availability Gateway is using an old SE version which doesn't have the
# order_tree_height API).
trades_height = self.orders_merkle_height
try:
trades_height = await self.availability_gateway.order_tree_height()
logger.info(
f"Trades height received from the Availability Gateway is {trades_height}. The "
f"trades height which is defined in the config is {self.orders_merkle_height}."
)
if self.orders_merkle_height != trades_height:
assert not validate_orders, (
f"validate_orders is {validate_orders}, but configured trades height "
f"{self.orders_merkle_height} is not equal to response from the availability "
f"gateway ({trades_height}). This indicates that the root of the order "
f"tree was computed incorrectly and the claim will not be approved by the "
f"availability gateway, so there is no point in signing and sending the "
f"signature."
)
except BadRequest:
pass

logger.info(f'Signing batch with sequence number {batch_info.sequence_number}')

availability_claim = hash_availability_claim(
batch_info.vaults_root, self.vaults_merkle_height, batch_info.orders_root,
self.orders_merkle_height, batch_info.sequence_number)
trades_height, batch_info.sequence_number)
signature = eth.Account._sign_hash(availability_claim, self.account.key).signature.hex()
return signature, availability_claim.hex()

Expand Down Expand Up @@ -221,4 +257,4 @@ async def async_hash_func(x, y):


if __name__ == '__main__':
sys.exit(asyncio.run(main()))
sys.exit(asyncio.run(main()))
15 changes: 13 additions & 2 deletions committee/committee/committee_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,22 @@
from .committee import Committee


ORDER_TREE_HEIGHT = 63


class AvailabilityGatewayClientMock:
def __init__(self):
pass

async def order_tree_height(self) -> int:
return ORDER_TREE_HEIGHT


@pytest.fixture
def committee():
config = {
'VAULTS_MERKLE_HEIGHT': 31,
'ORDERS_MERKLE_HEIGHT': 63,
'ORDERS_MERKLE_HEIGHT': ORDER_TREE_HEIGHT,
'POLLING_INTERVAL': 1,
}

Expand All @@ -24,7 +35,7 @@ def committee():
storage=MockStorage(),
merkle_storage=MockStorage(),
hash_func=async_pedersen_hash_func,
availability_gateway=None)
availability_gateway=AvailabilityGatewayClientMock())


@pytest.fixture
Expand Down

0 comments on commit 844ac3d

Please sign in to comment.