mirror of https://github.com/nucypher/nucypher.git
On-chain BlockchainPolicy publication by ALice
parent
ad8bb56cff
commit
4019ab69b6
|
@ -689,18 +689,23 @@ class Miner(NucypherTokenActor):
|
|||
class PolicyAuthor(NucypherTokenActor):
|
||||
"""Alice base class for blockchain operations, mocking up new policies!"""
|
||||
|
||||
def __init__(self, checksum_address: str, *args, **kwargs) -> None:
|
||||
def __init__(self, checksum_address: str, policy_agent = None, *args, **kwargs) -> None:
|
||||
"""
|
||||
:param policy_agent: A policy agent with the blockchain attached; If not passed, A default policy
|
||||
agent and blockchain connection will be created from default values.
|
||||
:param policy_agent: A policy agent with the blockchain attached;
|
||||
If not passed, A default policy agent and blockchain connection will
|
||||
be created from default values.
|
||||
|
||||
"""
|
||||
super().__init__(checksum_address=checksum_address, *args, **kwargs)
|
||||
|
||||
# From defaults
|
||||
self.token_agent = NucypherTokenAgent(blockchain=self.blockchain)
|
||||
self.miner_agent = MinerAgent(blockchain=self.blockchain)
|
||||
self.policy_agent = PolicyAgent(blockchain=self.blockchain)
|
||||
if not policy_agent:
|
||||
# From defaults
|
||||
self.token_agent = NucypherTokenAgent(blockchain=self.blockchain)
|
||||
self.miner_agent = MinerAgent(blockchain=self.blockchain)
|
||||
self.policy_agent = PolicyAgent(blockchain=self.blockchain)
|
||||
else:
|
||||
# Injected
|
||||
self.policy_agent = policy_agent
|
||||
|
||||
def recruit(self, quantity: int, **options) -> List[str]:
|
||||
"""
|
||||
|
|
|
@ -17,11 +17,10 @@ along with nucypher. If not, see <https://www.gnu.org/licenses/>.
|
|||
|
||||
|
||||
import random
|
||||
from abc import ABC
|
||||
from typing import Generator, List, Tuple, Union
|
||||
|
||||
from constant_sorrow.constants import NO_CONTRACT_AVAILABLE
|
||||
from twisted.logger import Logger
|
||||
from typing import Generator, List, Tuple, Union
|
||||
from web3.contract import Contract
|
||||
|
||||
from nucypher.blockchain.eth.chains import Blockchain
|
||||
|
|
|
@ -104,17 +104,19 @@ class BlockchainPolicy(Policy):
|
|||
def __init__(self,
|
||||
alice: PolicyAuthor,
|
||||
value: int,
|
||||
duration: int,
|
||||
expiration: maya.MayaDT,
|
||||
initial_reward: int,
|
||||
handpicked_ursulas: set = None,
|
||||
initial_reward: int = 0, # TODO: move somewhere else?
|
||||
*args, **kwargs):
|
||||
|
||||
self.initial_reward = initial_reward
|
||||
self.lock_periods = int(calculate_period_duration(expiration))
|
||||
self.handpicked_ursulas = handpicked_ursulas or UNKNOWN_ARRANGEMENTS
|
||||
self.lock_periods = duration
|
||||
self.expiration = expiration
|
||||
self.handpicked_ursulas = handpicked_ursulas or UNKNOWN_ARRANGEMENTS
|
||||
self.value = value
|
||||
self.author = alice
|
||||
self.selection_buffer = 1.5
|
||||
|
||||
# Initial State
|
||||
self.publish_transaction = None
|
||||
|
@ -148,7 +150,7 @@ class BlockchainPolicy(Policy):
|
|||
|
||||
start_time = maya.now() # marker for timeout calculation
|
||||
|
||||
found_ursulas, unknown_addresses = set(), deque() # type: set, deque
|
||||
found_ursulas, unknown_addresses = set(), deque()
|
||||
while len(found_ursulas) < target_quantity: # until there are enough Ursulas
|
||||
|
||||
delta = maya.now() - start_time # check for a timeout
|
||||
|
@ -197,7 +199,7 @@ class BlockchainPolicy(Policy):
|
|||
selected_addresses = set()
|
||||
|
||||
# Calculate the target sample quantity
|
||||
ADDITIONAL_URSULAS = 1.5 # TODO: Make constant somewhere else
|
||||
ADDITIONAL_URSULAS = self.selection_buffer
|
||||
target_sample_quantity = self.n - len(handpicked_ursulas)
|
||||
actual_sample_quantity = math.ceil(target_sample_quantity * ADDITIONAL_URSULAS)
|
||||
|
||||
|
@ -255,20 +257,17 @@ class BlockchainPolicy(Policy):
|
|||
|
||||
def publish(self, **kwargs) -> str:
|
||||
|
||||
if self.value is NON_PAYMENT:
|
||||
self.value = 0
|
||||
|
||||
payload = {'from': self.author.checksum_public_address,
|
||||
payload = {'from': self.author.checksum_address,
|
||||
'value': self.value,
|
||||
'gas': 500_000, # TODO: Gas management
|
||||
'gasPrice': self.author.blockchain.interface.w3.eth.gasPrice}
|
||||
|
||||
prearranged_ursulas = list(a.ursula.checksum_public_address for a in self._accepted_arrangements)
|
||||
|
||||
txhash = self.author.policy_agent.contract.functions.createPolicy(self.hrac()[:16],
|
||||
self.lock_periods,
|
||||
self.initial_reward,
|
||||
prearranged_ursulas,
|
||||
).transact(payload)
|
||||
prearranged_ursulas = list(a.ursula.checksum_address for a in self._accepted_arrangements)
|
||||
policy_args = (self.hrac()[:16], # bytes16 _policyID
|
||||
self.lock_periods, # uint16 _numberOfPeriods
|
||||
self.initial_reward, # uint256 _firstPartialReward
|
||||
prearranged_ursulas) # address[] memory _nodes
|
||||
txhash = self.author.policy_agent.contract.functions.createPolicy(*policy_args).transact(payload)
|
||||
|
||||
# Capture Response
|
||||
self.alice.policy_agent.blockchain.wait_for_receipt(txhash)
|
||||
|
|
|
@ -60,8 +60,14 @@ class Arrangement:
|
|||
splitter = key_splitter + BytestringSplitter((bytes, ID_LENGTH),
|
||||
(bytes, 27))
|
||||
|
||||
def __init__(self, alice, expiration, ursula=None, arrangement_id=None,
|
||||
kfrag=UNKNOWN_KFRAG, value=None, alices_signature=None) -> None:
|
||||
def __init__(self,
|
||||
alice,
|
||||
expiration,
|
||||
ursula=None,
|
||||
arrangement_id=None,
|
||||
kfrag=UNKNOWN_KFRAG,
|
||||
value=None,
|
||||
alices_signature=None) -> None:
|
||||
"""
|
||||
:param deposit: Funds which will pay for the timeframe of this Arrangement (not the actual re-encryptions);
|
||||
a portion will be locked for each Ursula that accepts.
|
||||
|
@ -73,7 +79,7 @@ class Arrangement:
|
|||
self.expiration = expiration
|
||||
self.alice = alice
|
||||
self.uuid = uuid.uuid4()
|
||||
self.value = None
|
||||
self.value = value
|
||||
|
||||
"""
|
||||
These will normally not be set if Alice is drawing up this arrangement - she hasn't assigned a kfrag yet
|
||||
|
@ -87,7 +93,7 @@ class Arrangement:
|
|||
|
||||
@classmethod
|
||||
def from_bytes(cls, arrangement_as_bytes):
|
||||
# Still unclear how to arrive at the correct number of bytes to represent a deposit. See #148.
|
||||
# TODO #148 - Still unclear how to arrive at the correct number of bytes to represent a deposit.
|
||||
alice_verifying_key, arrangement_id, expiration_bytes = cls.splitter(arrangement_as_bytes)
|
||||
expiration = maya.parse(expiration_bytes.decode())
|
||||
alice = Alice.from_public_keys(verifying_key=alice_verifying_key)
|
||||
|
@ -231,10 +237,9 @@ class Policy:
|
|||
|
||||
def __assign_kfrags(self) -> Generator[Arrangement, None, None]:
|
||||
|
||||
# TODO
|
||||
# if len(self._accepted_arrangements) < self.n:
|
||||
# raise self.MoreKFragsThanArrangements("Not enough candidate arrangements. "
|
||||
# "Call make_arrangements to make more.")
|
||||
if len(self._accepted_arrangements) < self.n:
|
||||
raise self.MoreKFragsThanArrangements("Not enough candidate arrangements. "
|
||||
"Call make_arrangements to make more.")
|
||||
|
||||
for kfrag in self.kfrags:
|
||||
for arrangement in self._accepted_arrangements:
|
||||
|
@ -482,7 +487,7 @@ class TreasureMap:
|
|||
def add_arrangement(self, arrangement):
|
||||
if self.destinations == NO_DECRYPTION_PERFORMED:
|
||||
raise TypeError("This TreasureMap is encrypted. You can't add another node without decrypting it.")
|
||||
self.destinations[arrangement.ursula.checksum_public_address] = arrangement.id
|
||||
self.destinations[arrangement.ursula.checksum_address] = arrangement.id
|
||||
|
||||
def public_id(self):
|
||||
"""
|
||||
|
|
Loading…
Reference in New Issue