On-chain BlockchainPolicy publication by ALice

pull/984/head
Kieran Prasch 2019-06-04 18:40:11 +03:00
parent ad8bb56cff
commit 4019ab69b6
No known key found for this signature in database
GPG Key ID: 199AB839D4125A62
4 changed files with 42 additions and 34 deletions

View File

@ -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]:
"""

View File

@ -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

View File

@ -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)

View File

@ -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):
"""