mirror of https://github.com/nucypher/nucypher.git
Ursula confirms ritual participation before responding to a decryption request
parent
a1d6ae77f9
commit
c7105b52db
|
@ -644,7 +644,13 @@ class CoordinatorAgent(EthereumContractAgent):
|
|||
return receipt
|
||||
|
||||
@contract_api(TRANSACTION)
|
||||
def post_transcript(self, ritual_id: int, transcript: bytes, node_index: int, transacting_power: TransactingPower) -> TxReceipt:
|
||||
def post_transcript(
|
||||
self,
|
||||
ritual_id: int,
|
||||
transcript: bytes,
|
||||
node_index: int,
|
||||
transacting_power: TransactingPower
|
||||
) -> TxReceipt:
|
||||
contract_function: ContractFunction = self.contract.functions.postTranscript(
|
||||
ritualId=ritual_id,
|
||||
nodeIndex=node_index,
|
||||
|
@ -659,16 +665,17 @@ class CoordinatorAgent(EthereumContractAgent):
|
|||
self,
|
||||
ritual_id: int,
|
||||
node_index: int,
|
||||
aggregated_transcript: AggregatedTranscript,
|
||||
aggregated_transcript: bytes,
|
||||
transacting_power: TransactingPower,
|
||||
) -> TxReceipt:
|
||||
contract_function: ContractFunction = self.contract.functions.postAggregation(
|
||||
ritualId=ritual_id,
|
||||
nodeIndex=node_index,
|
||||
aggregatedTranscript=bytes(aggregated_transcript),
|
||||
aggregatedTranscript=aggregated_transcript,
|
||||
)
|
||||
receipt = self.blockchain.send_transaction(
|
||||
contract_function=contract_function, transacting_power=transacting_power
|
||||
contract_function=contract_function,
|
||||
transacting_power=transacting_power
|
||||
)
|
||||
return receipt
|
||||
|
||||
|
|
|
@ -1,17 +1,7 @@
|
|||
import os
|
||||
import time
|
||||
from typing import Callable, List, Optional, Tuple, Type, Union
|
||||
|
||||
from eth_typing import ChecksumAddress
|
||||
from ferveo_py import (
|
||||
AggregatedTranscript,
|
||||
DecryptionShare,
|
||||
Dkg,
|
||||
Keypair,
|
||||
PublicKey,
|
||||
Transcript,
|
||||
)
|
||||
from twisted.internet import threads
|
||||
from typing import Callable, List, Optional, Tuple, Type, Union
|
||||
from web3 import Web3
|
||||
from web3.contract import Contract, ContractEvent
|
||||
from web3.datastructures import AttributeDict
|
||||
|
@ -60,7 +50,7 @@ class EventScannerTask(SimpleTask):
|
|||
raise args[0]
|
||||
|
||||
|
||||
class RitualTracker:
|
||||
class ActiveRitualTracker:
|
||||
|
||||
MAX_CHUNK_SIZE = 10000
|
||||
|
||||
|
@ -68,8 +58,9 @@ class RitualTracker:
|
|||
ritualist,
|
||||
eth_provider: BaseProvider,
|
||||
contract: Contract,
|
||||
start_block: int = 0,
|
||||
persistent: bool = False):
|
||||
start_block: int = 0, # TODO: use a start block that correlates to the ritual timeout
|
||||
persistent: bool = False # TODO: use persistent storage?
|
||||
):
|
||||
|
||||
self.log = Logger("RitualTracker")
|
||||
|
||||
|
|
|
@ -15,7 +15,8 @@ from cryptography.hazmat.primitives.serialization import Encoding
|
|||
from cryptography.x509 import Certificate, NameOID
|
||||
from eth_typing.evm import ChecksumAddress
|
||||
from eth_utils import to_checksum_address
|
||||
from ferveo_py import Ciphertext, DecryptionShare, combine_decryption_shares, decrypt_with_shared_secret
|
||||
from ferveo_py import Ciphertext, DecryptionShare, combine_decryption_shares, decrypt_with_shared_secret, \
|
||||
ExternalValidator, Transcript
|
||||
from pathlib import Path
|
||||
from queue import Queue
|
||||
from twisted.internet import reactor
|
||||
|
@ -38,7 +39,7 @@ import nucypher
|
|||
from nucypher.acumen.nicknames import Nickname
|
||||
from nucypher.acumen.perception import ArchivedFleetState, RemoteUrsulaStatus
|
||||
from nucypher.blockchain.eth.actors import Operator, PolicyAuthor, Ritualist
|
||||
from nucypher.blockchain.eth.agents import ContractAgency, PREApplicationAgent
|
||||
from nucypher.blockchain.eth.agents import ContractAgency, PREApplicationAgent, CoordinatorAgent
|
||||
from nucypher.blockchain.eth.interfaces import BlockchainInterfaceFactory
|
||||
from nucypher.blockchain.eth.registry import BaseContractRegistry
|
||||
from nucypher.blockchain.eth.signers.software import Web3Signer
|
||||
|
@ -50,6 +51,7 @@ from nucypher.characters.banners import (
|
|||
)
|
||||
from nucypher.characters.base import Character, Learner
|
||||
from nucypher.config.storages import NodeStorage
|
||||
from nucypher.crypto.ferveo.dkg import aggregate_transcripts
|
||||
from nucypher.crypto.keypairs import HostingKeypair
|
||||
from nucypher.crypto.powers import (
|
||||
DecryptingPower,
|
||||
|
@ -1121,6 +1123,14 @@ class Ursula(Teacher, Character, Operator, Ritualist):
|
|||
balance_eth=balance_eth,
|
||||
)
|
||||
|
||||
def as_external_validator(self) -> ExternalValidator:
|
||||
"""Returns an ExternalValidator instance for this Ursula for use in DKG operations."""
|
||||
validator = ExternalValidator(
|
||||
address=self.checksum_address,
|
||||
public_key=self.public_keys(RitualisticPower)
|
||||
)
|
||||
return validator
|
||||
|
||||
|
||||
class LocalUrsulaStatus(NamedTuple):
|
||||
nickname: Nickname
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
|
||||
|
||||
import requests
|
||||
import socket
|
||||
|
||||
|
|
|
@ -143,18 +143,23 @@ def _make_rest_app(this_node, log: Logger) -> Flask:
|
|||
decryption_request = ThresholdDecryptionRequest.from_bytes(request.data)
|
||||
|
||||
# Deserialize and instantiate ConditionLingo from the request data
|
||||
lingo = ConditionLingo.from_list(json.loads(str(decryption_request.conditions)))
|
||||
|
||||
# requester-supplied condition eval context
|
||||
# evaluate the conditions for this ciphertext
|
||||
lingo = ConditionLingo.from_list(json.loads(str(decryption_request.conditions)))
|
||||
context = None
|
||||
if decryption_request.context:
|
||||
context = json.loads(str(decryption_request.context)) or dict()
|
||||
|
||||
# evaluate the conditions for this ciphertext
|
||||
error = evaluate_condition_lingo(lingo, context)
|
||||
if error:
|
||||
return Response(error.message, status=error.status_code)
|
||||
|
||||
# TODO: confirm this node is tracking the ritual and is an authorized recipient
|
||||
# dkg_public_key = this_node.dkg_storage.get_public_key(decryption_request.ritual_id)
|
||||
ritual = this_node.coordinator_agent.get_ritual(decryption_request.ritual_id, with_participants=True)
|
||||
participants = [p.node for p in ritual.participants]
|
||||
if this_node.checksum_address not in participants:
|
||||
return Response(f'Node not part of ritual {decryption_request.ritual_id}', status=HTTPStatus.FORBIDDEN)
|
||||
|
||||
# derive the decryption share
|
||||
decryption_share = this_node.derive_decryption_share(
|
||||
ritual_id=decryption_request.ritual_id,
|
||||
|
@ -163,6 +168,7 @@ def _make_rest_app(this_node, log: Logger) -> Flask:
|
|||
)
|
||||
|
||||
# return the decryption share
|
||||
# TODO: encrypt the response with the requester's public key # 3079
|
||||
response = ThresholdDecryptionResponse(decryption_share=decryption_share)
|
||||
return Response(bytes(response), headers={'Content-Type': 'application/octet-stream'})
|
||||
|
||||
|
|
Loading…
Reference in New Issue