bugfix: always handle transaction hashes instead of transcripts for dkg tracking. Updates mocks to return txhash instead of receipt for transcript and aggregation posting.

remotes/origin/v7.4.x
KPrasch 2024-01-28 22:28:20 +01:00 committed by Derek Pierre
parent 2a73c816be
commit 5f8d68fe08
5 changed files with 35 additions and 48 deletions

View File

@ -3,7 +3,7 @@ import random
import time
from collections import defaultdict
from decimal import Decimal
from typing import DefaultDict, Dict, List, Optional, Set, Union
from typing import DefaultDict, Dict, List, Optional, Set, Tuple, Union
import maya
from eth_typing import ChecksumAddress
@ -26,6 +26,7 @@ from nucypher_core.ferveo import (
Validator,
)
from web3 import HTTPProvider, Web3
from web3.exceptions import TransactionNotFound
from web3.types import TxReceipt
from nucypher.acumen.nicknames import Nickname
@ -320,13 +321,10 @@ class Operator(BaseActor):
return result
def publish_transcript(self, ritual_id: int, transcript: Transcript) -> HexBytes:
"""Publish a transcript to publicly available storage."""
# look up the node index for this node on the blockchain
tx_hash = self.coordinator_agent.post_transcript(
ritual_id=ritual_id,
transcript=transcript,
transacting_power=self.transacting_power,
fire_and_forget=True,
)
return tx_hash
@ -347,7 +345,6 @@ class Operator(BaseActor):
public_key=public_key,
participant_public_key=participant_public_key,
transacting_power=self.transacting_power,
fire_and_forget=True,
)
return tx_hash
@ -436,9 +433,7 @@ class Operator(BaseActor):
# publish the transcript and store the receipt
tx_hash = self.publish_transcript(ritual_id=ritual_id, transcript=transcript)
self.dkg_storage.store_transcript_receipt(
ritual_id=ritual_id, txhash_or_receipt=tx_hash
)
self.dkg_storage.store_transcript_txhash(ritual_id=ritual_id, txhash=tx_hash)
# logging
arrival = ritual.total_transcripts + 1
@ -504,9 +499,7 @@ class Operator(BaseActor):
)
# store the receipt
self.dkg_storage.store_aggregated_transcript_receipt(
ritual_id=ritual_id, txhash_or_receipt=tx_hash
)
self.dkg_storage.store_aggregation_txhash(ritual_id=ritual_id, txhash=tx_hash)
# logging
total = ritual.total_aggregations + 1

View File

@ -1,9 +1,8 @@
from collections import defaultdict
from typing import Optional, Union
from typing import Optional
from hexbytes import HexBytes
from nucypher_core.ferveo import AggregatedTranscript, Transcript
from web3.types import TxReceipt
class DKGStorage:
@ -19,19 +18,14 @@ class DKGStorage:
data = self.data["transcripts"].get(ritual_id)
if not data:
return None
transcript = Transcript.from_bytes(data)
return transcript
def store_transcript_receipt(
self, ritual_id: int, txhash_or_receipt: Union[TxReceipt, HexBytes]
) -> None:
self.data["transcript_receipts"][ritual_id] = txhash_or_receipt
def store_transcript_txhash(self, ritual_id: int, txhash: HexBytes) -> None:
self.data["transcript_tx_hashes"][ritual_id] = txhash
def get_transcript_receipt(
self, ritual_id: int
) -> Optional[Union[TxReceipt, HexBytes]]:
return self.data["transcript_receipts"].get(ritual_id)
def get_transcript_txhash(self, ritual_id: int) -> Optional[HexBytes]:
return self.data["transcript_tx_hashes"].get(ritual_id)
def store_aggregated_transcript(self, ritual_id: int, aggregated_transcript: AggregatedTranscript) -> None:
self.data["aggregated_transcripts"][ritual_id] = bytes(aggregated_transcript)
@ -46,15 +40,11 @@ class DKGStorage:
aggregated_transcript = AggregatedTranscript.from_bytes(data)
return aggregated_transcript
def store_aggregated_transcript_receipt(
self, ritual_id: int, txhash_or_receipt: Union[TxReceipt, HexBytes]
) -> None:
self.data["aggregated_transcript_receipts"][ritual_id] = txhash_or_receipt
def store_aggregation_txhash(self, ritual_id: int, txhash: HexBytes) -> None:
self.data["aggregation_tx_hashes"][ritual_id] = txhash
def get_aggregated_transcript_receipt(
self, ritual_id: int
) -> Optional[Union[TxReceipt, HexBytes]]:
return self.data["aggregated_transcript_receipts"].get(ritual_id)
def get_aggregation_txhash(self, ritual_id: int) -> Optional[HexBytes]:
return self.data["aggregation_tx_hashes"].get(ritual_id)
def store_public_key(self, ritual_id: int, public_key: bytes) -> None:
self.data["public_keys"][ritual_id] = public_key

View File

@ -111,15 +111,16 @@ def test_initiate_ritual(
assert ritual_dkg_key is None # no dkg key available until ritual is completed
def test_post_transcript(agent, transcripts, transacting_powers):
def test_post_transcript(agent, transcripts, transacting_powers, testerchain):
ritual_id = agent.number_of_rituals() - 1
for i, transacting_power in enumerate(transacting_powers):
receipt = agent.post_transcript(
txhash = agent.post_transcript(
ritual_id=ritual_id,
transcript=transcripts[i],
transacting_power=transacting_power,
)
assert receipt["status"] == 1
receipt = testerchain.wait_for_receipt(txhash)
post_transcript_events = (
agent.contract.events.TranscriptPosted().process_receipt(receipt)
)
@ -141,13 +142,18 @@ def test_post_transcript(agent, transcripts, transacting_powers):
def test_post_aggregation(
agent, aggregated_transcript, dkg_public_key, transacting_powers, cohort
agent,
aggregated_transcript,
dkg_public_key,
transacting_powers,
cohort,
testerchain,
):
ritual_id = agent.number_of_rituals() - 1
participant_public_keys = {}
for i, transacting_power in enumerate(transacting_powers):
participant_public_key = SessionStaticSecret.random().public_key()
receipt = agent.post_aggregation(
txhash = agent.post_aggregation(
ritual_id=ritual_id,
aggregated_transcript=aggregated_transcript,
public_key=dkg_public_key,
@ -155,8 +161,7 @@ def test_post_aggregation(
transacting_power=transacting_power,
)
participant_public_keys[cohort[i]] = participant_public_key
assert receipt["status"] == 1
receipt = testerchain.wait_for_receipt(txhash)
post_aggregation_events = (
agent.contract.events.AggregationPosted().process_receipt(receipt)
)

View File

@ -122,7 +122,6 @@ class MockCoordinatorAgent(MockContractAgent):
ritual_id: int,
transcript: Transcript,
transacting_power: TransactingPower,
fire_and_forget: bool = False,
) -> TxReceipt:
ritual = self.rituals[ritual_id]
operator_address = transacting_power.account
@ -143,7 +142,7 @@ class MockCoordinatorAgent(MockContractAgent):
p.provider for p in ritual.participants
], # TODO This should not be
)
return self.blockchain.FAKE_RECEIPT
return self.blockchain.FAKE_TX_HASH
def post_aggregation(
self,
@ -152,7 +151,6 @@ class MockCoordinatorAgent(MockContractAgent):
public_key: DkgPublicKey,
participant_public_key: SessionStaticKey,
transacting_power: TransactingPower,
fire_and_forget: bool = False,
) -> TxReceipt:
ritual = self.rituals[ritual_id]
operator_address = transacting_power.account
@ -179,10 +177,10 @@ class MockCoordinatorAgent(MockContractAgent):
ritual.aggregation_mismatch = True
# don't increment aggregations
# TODO Emit EndRitual here?
return self.blockchain.FAKE_RECEIPT
return self.blockchain.FAKE_TX_HASH
ritual.total_aggregations += 1
return self.blockchain.FAKE_RECEIPT
return self.blockchain.FAKE_TX_HASH
def set_provider_public_key(
self, public_key: FerveoPublicKey, transacting_power: TransactingPower

View File

@ -1,4 +1,5 @@
import pytest
from hexbytes import HexBytes
from nucypher.blockchain.eth.agents import CoordinatorAgent
from nucypher.blockchain.eth.signers.software import Web3Signer
@ -18,6 +19,8 @@ def agent(mock_contract_agency, ursulas) -> MockCoordinatorAgent:
if ursula.checksum_address == provider:
return ursula.public_keys(RitualisticPower)
coordinator_agent.post_transcript = lambda *args, **kwargs: HexBytes("deadbeef")
coordinator_agent.post_aggregation = lambda *args, **kwargs: HexBytes("deadbeef")
coordinator_agent.get_provider_public_key = mock_get_provider_public_key
return coordinator_agent
@ -144,7 +147,7 @@ def test_perform_round_1(
assert tx_hash is not None
# ensure tx hash is stored
assert ursula.dkg_storage.get_transcript_receipt(ritual_id=0) == tx_hash
assert ursula.dkg_storage.get_transcript_txhash(ritual_id=0) == tx_hash
# try again
tx_hash = ursula.perform_round_1(
@ -153,7 +156,7 @@ def test_perform_round_1(
assert tx_hash is None # no execution since pending tx already present
# clear tx hash
ursula.dkg_storage.store_transcript_receipt(ritual_id=0, txhash_or_receipt=None)
ursula.dkg_storage.store_transcript_txhash(ritual_id=0, txhash=None)
# participant already posted transcript
participant = agent.get_participant(
@ -241,16 +244,14 @@ def test_perform_round_2(
assert tx_hash is not None
# check tx hash
assert ursula.dkg_storage.get_aggregated_transcript_receipt(ritual_id=0) == tx_hash
assert ursula.dkg_storage.get_aggregation_txhash(ritual_id=0) == tx_hash
# try again
tx_hash = ursula.perform_round_2(ritual_id=0, timestamp=0)
assert tx_hash is None # no execution since pending tx already present
# clear tx hash
ursula.dkg_storage.store_aggregated_transcript_receipt(
ritual_id=0, txhash_or_receipt=None
)
ursula.dkg_storage.store_aggregation_txhash(ritual_id=0, txhash=None)
# participant already posted aggregated transcript
participant = agent.get_participant(