mirror of https://github.com/nucypher/nucypher.git
Minimal solc compilation to web3 contracts.
parent
15be632621
commit
157bf90d96
|
@ -1,7 +1,5 @@
|
|||
import random
|
||||
from abc import ABC
|
||||
from typing import List
|
||||
|
||||
|
||||
from nkms.config.configs import EthereumConfig
|
||||
|
||||
|
@ -28,7 +26,7 @@ class TheBlockchain(ABC):
|
|||
class IsAlreadyRunning(RuntimeError):
|
||||
pass
|
||||
|
||||
def __init__(self, eth_config: EthereumConfig):
|
||||
def __init__(self, config: EthereumConfig):
|
||||
"""
|
||||
Configures a populus project and connects to blockchain.network.
|
||||
Transaction timeouts specified measured in seconds.
|
||||
|
@ -43,8 +41,7 @@ class TheBlockchain(ABC):
|
|||
raise TheBlockchain.IsAlreadyRunning(message)
|
||||
TheBlockchain.__instance = self
|
||||
|
||||
self._eth_config = eth_config
|
||||
self._chain = eth_config.provider # TODO
|
||||
self.config = config
|
||||
|
||||
@classmethod
|
||||
def get(cls):
|
||||
|
@ -53,12 +50,6 @@ class TheBlockchain(ABC):
|
|||
raise Exception('{} has not been created.'.format(class_name))
|
||||
return cls.__instance
|
||||
|
||||
def disconnect(self):
|
||||
self._chain.__exit__(None, None, None)
|
||||
|
||||
def __del__(self):
|
||||
self.disconnect()
|
||||
|
||||
def __repr__(self):
|
||||
class_name = self.__class__.__name__
|
||||
r = "{}(network={})"
|
||||
|
@ -66,17 +57,17 @@ class TheBlockchain(ABC):
|
|||
|
||||
def get_contract(self, name):
|
||||
"""
|
||||
Gets an existing contract from the network,
|
||||
Gets an existing contract from the registrar,
|
||||
or raises populus.contracts.exceptions.UnknownContract
|
||||
if there is no contract data available for the name/identifier.
|
||||
"""
|
||||
return self._chain.provider.get_contract(name)
|
||||
return self.config.provider.get_contract(name)
|
||||
|
||||
def wait_for_receipt(self, txhash, timeout=None) -> None:
|
||||
if timeout is None:
|
||||
timeout = self._default_timeout
|
||||
|
||||
result = self._chain.wait.for_receipt(txhash, timeout=timeout)
|
||||
result = self.config.wait.for_receipt(txhash, timeout=timeout)
|
||||
return result
|
||||
|
||||
|
||||
|
@ -88,7 +79,7 @@ class TesterBlockchain(TheBlockchain):
|
|||
def wait_time(self, wait_hours, step=50):
|
||||
"""Wait the specified number of wait_hours by comparing block timestamps."""
|
||||
|
||||
end_timestamp = self._chain.web3.eth.getBlock(
|
||||
end_timestamp = self.config.web3.eth.getBlock(
|
||||
self._chain.web3.eth.blockNumber).timestamp + wait_hours * 60 * 60
|
||||
while self._chain.web3.eth.getBlock(self._chain.web3.eth.blockNumber).timestamp < end_timestamp:
|
||||
self._chain.wait.for_block(self._chain.web3.eth.blockNumber + step)
|
||||
|
|
|
@ -156,7 +156,7 @@ class NuCypherKMSTokenDeployer(ContractDeployer, NuCypherTokenConfig):
|
|||
|
||||
def __init__(self, blockchain):
|
||||
super().__init__(blockchain=blockchain)
|
||||
self._creator = self.blockchain._eth_config.provider.get_accounts()[0] # TODO: make swappable
|
||||
self._creator = self.blockchain.config.provider.get_accounts()[0] # TODO: make swappable
|
||||
|
||||
def deploy(self) -> str:
|
||||
"""
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
import os
|
||||
|
||||
from os.path import join, dirname, abspath
|
||||
from solc import compile_files
|
||||
from solc import install_solc
|
||||
|
||||
from nkms.blockchain import eth
|
||||
|
||||
|
||||
class SolidityConfig:
|
||||
version = 'v0.4.20'
|
||||
|
||||
contract_names = ('Issuer',
|
||||
'NuCypherKMSToken',
|
||||
'MinersEscrow',
|
||||
'PolicyManager',
|
||||
'UserEscrow')
|
||||
|
||||
__sol_binary_path = os.path.join(os.environ['VIRTUAL_ENV'], 'bin', 'solc')
|
||||
_source_dir = join(dirname(abspath(eth.__file__)), 'sol', 'source', 'contracts')
|
||||
|
||||
def __init__(self):
|
||||
os.environ['SOLC_BINARY'] = self.__sol_binary_path
|
||||
|
||||
def install_compiler(self):
|
||||
# https://github.com/ethereum/py-solc#installing-the-solc-binary
|
||||
return install_solc(self.version)
|
||||
|
||||
|
||||
def compile_interfaces(config: SolidityConfig=SolidityConfig()) -> dict:
|
||||
|
||||
contract_paths = [os.path.join(config._source_dir, contract+'.sol') for contract in config.contract_names]
|
||||
compiled_sol = compile_files(contract_paths)
|
||||
|
||||
interfaces = dict()
|
||||
for contract_name, contract_path in zip(config.contract_names, contract_paths):
|
||||
contract_interface = compiled_sol['{}:{}'.format(contract_path, contract_name)]
|
||||
interfaces[contract_name] = contract_interface
|
||||
|
||||
return interfaces
|
|
@ -1,12 +1,16 @@
|
|||
import json
|
||||
import os
|
||||
from abc import ABC
|
||||
from pathlib import Path
|
||||
from typing import List, Union
|
||||
|
||||
import maya
|
||||
from os.path import join, dirname, abspath
|
||||
from eth_tester import EthereumTester, PyEVMBackend
|
||||
from web3 import Web3, EthereumTesterProvider
|
||||
from web3.contract import ConciseContract
|
||||
from web3.contract import Contract
|
||||
from web3.providers.tester import EthereumTesterProvider
|
||||
|
||||
from nkms.blockchain import eth
|
||||
from nkms.blockchain.eth.sol.compile import compile_interfaces, SolidityConfig
|
||||
|
||||
_DEFAULT_CONFIGURATION_DIR = os.path.join(str(Path.home()), '.nucypher')
|
||||
|
||||
|
@ -15,34 +19,48 @@ class KMSConfigurationError(RuntimeError):
|
|||
pass
|
||||
|
||||
|
||||
class BlockchainConfig(ABC):
|
||||
pass
|
||||
class KMSProvider:
|
||||
|
||||
def __init__(self, provider=None, registrar=None):
|
||||
|
||||
class EthereumConfig(BlockchainConfig):
|
||||
__solididty_source_dir = join(dirname(abspath(eth.__file__)), 'sol_source')
|
||||
__default_registrar_path = join(_DEFAULT_CONFIGURATION_DIR, 'registrar.json')
|
||||
|
||||
def __init__(self, provider, registrar_path=None):
|
||||
|
||||
if provider is None:
|
||||
# https: // github.com / ethereum / eth - tester # available-backends
|
||||
eth_tester = EthereumTester(backend=PyEVMBackend()) # TODO: Discuss backend choice
|
||||
provider = EthereumTesterProvider(ethereum_tester=eth_tester, api_endpoints=None)
|
||||
self.provider = provider
|
||||
self.w3 = Web3(self.provider)
|
||||
|
||||
if registrar_path is None:
|
||||
registrar_path = self.__default_registrar_path
|
||||
self._registrar_path = registrar_path
|
||||
self.__registrar = None
|
||||
|
||||
# Populus project config
|
||||
# self._populus_project = populus.Project(self._project_dir)
|
||||
# self.project.config['chains.mainnetrpc.contracts.backends.JSONFile.settings.file_path'] = self._registrar_path
|
||||
def __make_web3_contracts(self, contract_factory: Union[ConciseContract, Contract]=ConciseContract, address=None) -> List[Contract]:
|
||||
"""Instantiate web3 Contracts from raw contract interface data with the supplied web3 provider"""
|
||||
sol_config = SolidityConfig()
|
||||
interfaces = compile_interfaces(config=sol_config)
|
||||
|
||||
# @property
|
||||
# def project(self):
|
||||
# return self._populus_project
|
||||
if contract_factory is ConciseContract and address is None:
|
||||
raise Exception('Address must be provided when making concise contracts.')
|
||||
elif contract_factory is Contract and address is not None:
|
||||
raise Exception('Address must not be provided when making deployable, non-concise contracts')
|
||||
|
||||
web3_contracts = list()
|
||||
for contract, interface in interfaces.items():
|
||||
contract = self.w3.eth.contract(abi=interface['abi'],
|
||||
bytecode=interface['bin'],
|
||||
ContractFactoryClass=contract_factory)
|
||||
web3_contracts.append(contract)
|
||||
|
||||
return web3_contracts
|
||||
|
||||
def get_contract(self):
|
||||
pass
|
||||
|
||||
def deploy_contract(self):
|
||||
pass
|
||||
|
||||
|
||||
class StakeConfig:
|
||||
__minimum_stake_amount = 0 # TODO!!!
|
||||
__minimum_stake_duration = 0
|
||||
# __minimum_stake_amount = 0 # TODO
|
||||
# __minimum_stake_duration = 0
|
||||
|
||||
def __init__(self, amount: int, periods: int, start_datetime):
|
||||
|
||||
|
@ -54,9 +72,9 @@ class StakeConfig:
|
|||
@classmethod
|
||||
def validate_stake(cls, amount: int, periods: int, start_datetime) -> bool:
|
||||
rules = (
|
||||
(amount > cls.__minimum_stake_amount, 'Staking aount must be at least {min_amount}'),
|
||||
# (amount > cls.__minimum_stake_amount, 'Staking aount must be at least {min_amount}'), # TODO
|
||||
(start_datetime < maya.now(), 'Start date/time must not be in the past.'),
|
||||
(periods > cls.__minimum_stake_duration, 'Staking duration must be at least {}'.format(cls.__minimum_stake_duration))
|
||||
# (periods > cls.__minimum_stake_duration, 'Staking duration must be at least {}'.format(cls.__minimum_stake_duration))
|
||||
)
|
||||
|
||||
for rule, failure_message in rules:
|
||||
|
|
Loading…
Reference in New Issue