mirror of https://github.com/nucypher/nucypher.git
Include worker address sync in Stake; Blockchain to/from dict payload, Geth tranction formatting and signging.
parent
7d3c80ae2b
commit
3bc659b66f
|
@ -145,8 +145,6 @@ class Deployer(NucypherTokenActor):
|
|||
|
||||
def __init__(self,
|
||||
blockchain: BlockchainDeployerInterface,
|
||||
client_password: str = None,
|
||||
device = NO_STAKING_DEVICE,
|
||||
deployer_address: str = None,
|
||||
client_password: str = None,
|
||||
bare: bool = True
|
||||
|
@ -174,7 +172,6 @@ class Deployer(NucypherTokenActor):
|
|||
|
||||
# TODO: Does this class want to be a Character implementing PowerUp consumption?
|
||||
self.transacting_power = TransactingPower(blockchain=blockchain,
|
||||
device=device,
|
||||
password=client_password,
|
||||
account=deployer_address)
|
||||
self.transacting_power.activate()
|
||||
|
|
|
@ -31,6 +31,9 @@ from nucypher.crypto.api import sha256_digest
|
|||
class Agency(type):
|
||||
__agents = dict()
|
||||
|
||||
class NoAgency(Exception):
|
||||
pass
|
||||
|
||||
def __call__(cls, *args, **kwargs):
|
||||
if cls not in cls.__agents:
|
||||
cls.__agents[cls] = super().__call__(*args, **kwargs)
|
||||
|
@ -44,6 +47,13 @@ class Agency(type):
|
|||
def agents(cls):
|
||||
return cls.__agents
|
||||
|
||||
@classmethod
|
||||
def get_agent(mcs, cls):
|
||||
try:
|
||||
return mcs.__agents[cls]
|
||||
except KeyError:
|
||||
raise mcs.NoAgency
|
||||
|
||||
|
||||
class EthereumContractAgent:
|
||||
"""
|
||||
|
|
|
@ -197,20 +197,20 @@ class Web3Client:
|
|||
return self.w3.eth.coinbase
|
||||
|
||||
def wait_for_receipt(self, transaction_hash: str, timeout: int) -> dict:
|
||||
receipt = self.w3.eth.waitForTransactionReceipt(transaction_hash, timeout=timeout)
|
||||
receipt = self.w3.eth.waitForTransactionReceipt(transaction_hash=transaction_hash, timeout=timeout)
|
||||
return receipt
|
||||
|
||||
def sign_transaction(self, transaction: dict):
|
||||
raise NotImplementedError
|
||||
|
||||
def get_transaction(self, transaction_hash) -> str:
|
||||
return self.w3.eth.getTransaction(transaction_hash)
|
||||
return self.w3.eth.getTransaction(transaction_hash=transaction_hash)
|
||||
|
||||
def send_transaction(self, transaction: dict) -> str:
|
||||
return self.w3.eth.sendTransaction(transaction)
|
||||
return self.w3.eth.sendTransaction(transaction=transaction)
|
||||
|
||||
def send_raw_transaction(self, transaction: bytes) -> str:
|
||||
return self.w3.eth.sendRawTransaction(transaction)
|
||||
return self.w3.eth.sendRawTransaction(raw_transaction=transaction)
|
||||
|
||||
def sync(self,
|
||||
timeout: int = 120,
|
||||
|
@ -258,6 +258,9 @@ class Web3Client:
|
|||
"""
|
||||
return self.w3.eth.sign(account, data=message)
|
||||
|
||||
def sign_transaction(self, transaction: dict) -> bytes:
|
||||
raise NotImplementedError
|
||||
|
||||
|
||||
class GethClient(Web3Client):
|
||||
|
||||
|
@ -270,6 +273,8 @@ class GethClient(Web3Client):
|
|||
return self.w3.geth.admin.peers()
|
||||
|
||||
def unlock_account(self, address, password):
|
||||
# if self.is_local:
|
||||
# return True
|
||||
return self.w3.geth.personal.unlockAccount(address, password)
|
||||
|
||||
def sign_transaction(self, transaction: dict) -> bytes:
|
||||
|
@ -323,6 +328,10 @@ class EthereumTesterClient(Web3Client):
|
|||
def sync(self, *args, **kwargs):
|
||||
return True
|
||||
|
||||
def new_account(self, password: str):
|
||||
insecure_account = self.w3.provider.ethereum_tester.add_account(os.urandom(32).hex(), password=password)
|
||||
return insecure_account
|
||||
|
||||
def sign_transaction(self, transaction: dict):
|
||||
# Get signing key of test account
|
||||
address = to_canonical_address(transaction['from'])
|
||||
|
@ -410,17 +419,20 @@ class NuCypherGethDevProcess(NuCypherGethProcess):
|
|||
self.data_dir = get_chain_data_dir(base_dir=base_dir, name=self._CHAIN_NAME)
|
||||
|
||||
ipc_path = os.path.join(self.data_dir, 'geth.ipc')
|
||||
self.geth_kwargs = {'ipc_path': ipc_path}
|
||||
super().__init__(geth_kwargs=self.geth_kwargs, *args, **kwargs)
|
||||
self.geth_kwargs.update({'dev': True})
|
||||
self.geth_kwargs = {'ipc_path': ipc_path,
|
||||
'data_dir': self.data_dir}
|
||||
|
||||
super().__init__(geth_kwargs=self.geth_kwargs, *args, **kwargs)
|
||||
self.command = [*self.command, '--dev']
|
||||
|
||||
def start(self, timeout: int = 30, extra_delay: int = 1):
|
||||
self.LOG.info("STARTING GETH DEV NOW")
|
||||
BaseGethProcess.start(self) # <--- START GETH
|
||||
time.sleep(extra_delay) # give it a second
|
||||
self.wait_for_ipc(timeout=timeout)
|
||||
if not self.is_running:
|
||||
self.LOG.info("STARTING GETH DEV PROCESS NOW")
|
||||
BaseGethProcess.start(self) # <--- START GETH
|
||||
time.sleep(extra_delay) # give it a second
|
||||
self.wait_for_ipc(timeout=timeout)
|
||||
else:
|
||||
self.LOG.info("RECONNECTING TO GETH DEV PROCESS")
|
||||
|
||||
|
||||
class NuCypherGethDevnetProcess(NuCypherGethProcess):
|
||||
|
|
|
@ -164,9 +164,8 @@ class NucypherTokenDeployer(ContractDeployer):
|
|||
"""
|
||||
self.check_deployment_readiness()
|
||||
|
||||
_contract, deployment_txhash = self.blockchain.deploy_contract(
|
||||
self.contract_name,
|
||||
self.__economics.erc20_total_supply)
|
||||
_contract, deployment_txhash = self.blockchain.deploy_contract(self.contract_name,
|
||||
self.__economics.erc20_total_supply)
|
||||
|
||||
self._contract = _contract
|
||||
return {'txhash': deployment_txhash}
|
||||
|
|
|
@ -34,9 +34,10 @@ from eth_tester import EthereumTester
|
|||
from eth_utils import to_checksum_address, to_canonical_address
|
||||
from twisted.logger import Logger
|
||||
from web3 import Web3, WebsocketProvider, HTTPProvider, IPCProvider
|
||||
from web3.contract import ConciseContract
|
||||
from web3.contract import Contract, ContractFunction, ContractConstructor
|
||||
from web3.exceptions import TimeExhausted, ValidationError
|
||||
from web3.contract import Contract, ContractFunction
|
||||
from web3.contract import ContractConstructor
|
||||
from web3.exceptions import TimeExhausted
|
||||
from web3.exceptions import ValidationError
|
||||
from web3.middleware import geth_poa_middleware
|
||||
|
||||
from nucypher.blockchain.eth.clients import Web3Client, NuCypherGethProcess
|
||||
|
@ -65,11 +66,11 @@ class BlockchainInterface:
|
|||
TIMEOUT = 180 # seconds
|
||||
NULL_ADDRESS = '0x' + '0' * 40
|
||||
|
||||
_instance = NO_BLOCKCHAIN_CONNECTION
|
||||
_instance = NO_BLOCKCHAIN_CONNECTION.bool_value(False)
|
||||
process = NO_PROVIDER_PROCESS.bool_value(False)
|
||||
Web3 = Web3
|
||||
|
||||
_contract_factory = ConciseContract
|
||||
_contract_factory = Contract
|
||||
|
||||
class InterfaceError(Exception):
|
||||
pass
|
||||
|
@ -163,20 +164,33 @@ class BlockchainInterface:
|
|||
self.client = NO_BLOCKCHAIN_CONNECTION
|
||||
self.transacting_power = transacting_power
|
||||
self.registry = registry
|
||||
|
||||
BlockchainInterface._instance = self
|
||||
|
||||
def __repr__(self):
|
||||
r = '{name}({uri})'.format(name=self.__class__.__name__, uri=self.provider_uri)
|
||||
return r
|
||||
|
||||
def _configure_registry(self, fetch_registry: bool = True):
|
||||
@classmethod
|
||||
def from_dict(cls, payload: dict) -> 'BlockchainInterface':
|
||||
registry = EthereumContractRegistry(registry_filepath=payload['registry_filepath'])
|
||||
blockchain = cls(provider_uri=payload['provider_uri'],
|
||||
registry=registry)
|
||||
return blockchain
|
||||
|
||||
def to_dict(self) -> dict:
|
||||
payload = dict(provider_uri=self.provider_uri,
|
||||
poa=self.poa,
|
||||
registry_filepath=self.registry.filepath)
|
||||
return payload
|
||||
|
||||
def _configure_registry(self, fetch_registry: bool = True) -> None:
|
||||
RegistryClass = EthereumContractRegistry._get_registry_class(local=self.client.is_local)
|
||||
if fetch_registry:
|
||||
registry = RegistryClass.from_latest_publication()
|
||||
else:
|
||||
registry = RegistryClass()
|
||||
self.registry = registry
|
||||
self.log.info("Using contract registry {}".format(self.registry.filepath))
|
||||
|
||||
@property
|
||||
def is_connected(self) -> bool:
|
||||
|
@ -187,7 +201,7 @@ class BlockchainInterface:
|
|||
return False
|
||||
return self.client.is_connected
|
||||
|
||||
def disconnect(self):
|
||||
def disconnect(self) -> None:
|
||||
if self._provider_process:
|
||||
self._provider_process.stop()
|
||||
self._provider_process = NO_PROVIDER_PROCESS
|
||||
|
@ -232,14 +246,14 @@ class BlockchainInterface:
|
|||
else:
|
||||
self.attach_middleware()
|
||||
|
||||
# Establish contact with NuCypher contracts
|
||||
if not self.registry:
|
||||
self._configure_registry(fetch_registry=fetch_registry)
|
||||
|
||||
# Wait for chaindata sync
|
||||
if sync_now:
|
||||
self.client.sync()
|
||||
|
||||
# Establish contact with NuCypher contracts
|
||||
if not self.registry:
|
||||
self._configure_registry()
|
||||
|
||||
return self.is_connected
|
||||
|
||||
@property
|
||||
|
@ -304,7 +318,9 @@ class BlockchainInterface:
|
|||
payload.update({'chainId': int(self.client.chain_id),
|
||||
'nonce': nonce,
|
||||
'from': sender_address,
|
||||
'gasPrice': self.client.w3.eth.gasPrice})
|
||||
'gasPrice': self.client.w3.eth.gasPrice,
|
||||
# 'gas': 0, # TODO: Gas Management
|
||||
})
|
||||
|
||||
# Get interface name
|
||||
try:
|
||||
|
@ -461,8 +477,6 @@ class BlockchainDeployerInterface(BlockchainInterface):
|
|||
self.__recompile = recompile
|
||||
self.__sol_compiler = compiler
|
||||
|
||||
self.log.info("Using contract registry {}".format(self.registry.filepath))
|
||||
|
||||
if self.__recompile is True:
|
||||
# Execute the compilation if we're recompiling
|
||||
# Otherwise read compiled contract data from the registry
|
||||
|
|
|
@ -2,7 +2,15 @@ from _pydecimal import Decimal
|
|||
from typing import Union, Tuple, Callable, List
|
||||
|
||||
import maya
|
||||
from constant_sorrow.constants import NEW_STAKE, NO_STAKING_RECEIPT, NOT_STAKING, UNKNOWN_STAKES, NO_STAKES, EMPTY_STAKING_SLOT
|
||||
from constant_sorrow.constants import (
|
||||
NEW_STAKE,
|
||||
NO_STAKING_RECEIPT,
|
||||
NOT_STAKING,
|
||||
UNKNOWN_STAKES,
|
||||
NO_STAKES,
|
||||
EMPTY_STAKING_SLOT,
|
||||
UNKNOWN_WORKER_STATUS
|
||||
)
|
||||
from eth_utils import currency, is_checksum_address
|
||||
from twisted.internet import task, reactor
|
||||
from twisted.logger import Logger
|
||||
|
@ -149,6 +157,7 @@ class Stake:
|
|||
|
||||
# Stake Metadata
|
||||
self.owner_address = checksum_address
|
||||
self.worker_address = UNKNOWN_WORKER_STATUS
|
||||
self.index = index
|
||||
self.value = value
|
||||
self.start_period = start_period
|
||||
|
@ -161,7 +170,7 @@ class Stake:
|
|||
|
||||
# Agency
|
||||
self.staking_agent = None
|
||||
self.token_agent = NucypherTokenAgent()
|
||||
self.token_agent = NucypherTokenAgent() # TODO: Use Agency
|
||||
self.blockchain = self.token_agent.blockchain
|
||||
|
||||
# Economics
|
||||
|
@ -215,6 +224,9 @@ class Stake:
|
|||
start_period=start_period,
|
||||
end_period=end_period,
|
||||
value=NU(value, 'NuNit'))
|
||||
|
||||
agent = StakingEscrowAgent()
|
||||
instance.worker_address = agent.get_worker_from_staker(staker_address=checksum_address)
|
||||
return instance
|
||||
|
||||
def to_stake_info(self) -> Tuple[int, int, int]:
|
||||
|
@ -304,9 +316,9 @@ class Stake:
|
|||
"""Update this stakes attributes with on-chain values."""
|
||||
|
||||
if not self.staking_agent:
|
||||
self.staking_agent = StakingEscrowAgent()
|
||||
self.staking_agent = StakingEscrowAgent(blockchain=self.blockchain)
|
||||
if not self.token_agent:
|
||||
self.token_agent = NucypherTokenAgent()
|
||||
self.token_agent = NucypherTokenAgent(blockchain=self.blockchain)
|
||||
|
||||
# Read from blockchain
|
||||
stake_info = self.staking_agent.get_substake_info(staker_address=self.owner_address,
|
||||
|
@ -320,6 +332,7 @@ class Stake:
|
|||
# Mutate the instance with the on-chain values
|
||||
self.end_period = last_period
|
||||
self.value = NU.from_nunits(locked_value)
|
||||
self.worker_address = self.staking_agent.get_worker_from_staker(staker_address=self.owner_address)
|
||||
|
||||
@classmethod
|
||||
def __deposit(cls, staker, amount: int, lock_periods: int) -> Tuple[str, str]:
|
||||
|
|
Loading…
Reference in New Issue