예제 #1
0
    def __init__(
        self,
        jsonrpc_client: JSONRPCClient,
        user_deposit_address: UserDepositAddress,
        contract_manager: ContractManager,
        proxy_manager: "ProxyManager",
    ) -> None:
        if not is_binary_address(user_deposit_address):
            raise ValueError("Expected binary address format for token nework")

        check_address_has_code(
            client=jsonrpc_client,
            address=Address(user_deposit_address),
            contract_name=CONTRACT_USER_DEPOSIT,
            expected_code=decode_hex(
                contract_manager.get_runtime_hexcode(CONTRACT_USER_DEPOSIT)),
        )

        self.client = jsonrpc_client

        self.address = user_deposit_address
        self.node_address = self.client.address
        self.contract_manager = contract_manager
        self.gas_measurements = gas_measurements(
            self.contract_manager.contracts_version)

        self.proxy_manager = proxy_manager

        self.proxy = jsonrpc_client.new_contract_proxy(
            abi=self.contract_manager.get_contract_abi(CONTRACT_USER_DEPOSIT),
            contract_address=Address(user_deposit_address),
        )

        self.deposit_lock = RLock()
예제 #2
0
    def token_network(self, address: TokenNetworkAddress) -> TokenNetwork:
        if not is_binary_address(address):
            raise ValueError("address must be a valid address")

        with self._token_network_creation_lock:
            if address not in self.address_to_token_network:
                metadata = TokenNetworkMetadata(
                    deployed_at=None,
                    abi=self.contract_manager.get_contract_abi(
                        CONTRACT_TOKEN_NETWORK),
                    gas_measurements=gas_measurements(
                        self.contract_manager.contracts_version),
                    runtime_bytecode=EVMBytecode(
                        decode_hex(
                            self.contract_manager.get_runtime_hexcode(
                                CONTRACT_TOKEN_NETWORK))),
                    address=Address(address),
                    token_network_registry_address=None,
                    filters_start_at=self.metadata.filters_start_at,
                )

                self.address_to_token_network[address] = TokenNetwork(
                    jsonrpc_client=self.client,
                    contract_manager=self.contract_manager,
                    proxy_manager=self,
                    metadata=metadata,
                )

        return self.address_to_token_network[address]
예제 #3
0
def get_required_gas_estimate(raiden: "RaidenService",
                              channels_to_open: int = 0) -> int:
    gas_estimate = _get_required_gas_estimate_for_state(raiden)
    measurements = gas_measurements(raiden.contract_manager.contracts_version)
    gas_estimate += _get_required_gas_estimate(gas_measurements=measurements,
                                               new_channels=channels_to_open)
    return gas_estimate
예제 #4
0
    def token_network_registry(
            self,
            address: TokenNetworkRegistryAddress) -> TokenNetworkRegistry:

        with self._token_network_registry_creation_lock:
            if address not in self.address_to_token_network_registry:

                metadata = SmartContractMetadata(
                    deployed_at=self.metadata.
                    token_network_registry_deployed_at,
                    address=Address(address),
                    abi=self.contract_manager.get_contract_abi(
                        CONTRACT_TOKEN_NETWORK_REGISTRY),
                    runtime_bytecode=EVMBytecode(
                        decode_hex(
                            self.contract_manager.get_runtime_hexcode(
                                CONTRACT_TOKEN_NETWORK_REGISTRY))),
                    gas_measurements=gas_measurements(
                        self.contract_manager.contracts_version),
                    filters_start_at=self.metadata.filters_start_at,
                )

                self.address_to_token_network_registry[
                    address] = TokenNetworkRegistry(rpc_client=self.client,
                                                    metadata=metadata,
                                                    proxy_manager=self)

        return self.address_to_token_network_registry[address]
예제 #5
0
def calc_claim_cost_rdn(web3: Web3, rdn_per_eth: float) -> TokenAmount:
    web3.eth.setGasPriceStrategy(rpc_gas_price_strategy)
    claim_cost_gas = gas_measurements()["OneToN.claim"]
    claim_cost_eth = claim_cost_gas * web3.eth.generateGasPrice(
    ) * GAS_COST_SAFETY_MARGIN
    claim_cost_rdn = TokenAmount(int(claim_cost_eth / rdn_per_eth))
    return claim_cost_rdn
예제 #6
0
def test_gas_json_has_enough_fields(version: Optional[str]) -> None:
    """ Check is gas.json contains enough fields """
    doc = gas_measurements(version)
    keys = {
        "CustomToken.mint",
        "CustomToken.approve",
        "CustomToken.transfer",
        "CustomToken.transferFrom",
        "MonitoringService.claimReward",
        "MonitoringService.monitor",
        "OneToN.claim",
        "OneToN.bulkClaim 1 ious",
        "OneToN.bulkClaim 6 ious",
        "SecretRegistry.registerSecret",
        "ServiceRegistry.deposit",
        "ServiceRegistry.setURL",
        "TokenNetwork DEPLOYMENT",
        "TokenNetwork.closeChannel",
        "TokenNetwork.openChannel",
        "TokenNetwork.setTotalDeposit",
        "TokenNetwork.setTotalWithdraw",
        "TokenNetwork.settleChannel",
        "TokenNetwork.unlock 1 locks",
        "TokenNetwork.unlock 6 locks",
        "TokenNetwork.updateNonClosingBalanceProof",
        "TokenNetworkRegistry DEPLOYMENT",
        "TokenNetworkRegistry createERC20TokenNetwork",
        "UserDeposit.deposit",
        "UserDeposit.deposit (increase balance)",
        "UserDeposit.planWithdraw",
        "UserDeposit.withdraw",
    }
    assert set(doc.keys()) == keys
예제 #7
0
def calc_claim_cost_rdn(web3: Web3, rdn_per_eth: float) -> TokenAmount:
    web3.eth.setGasPriceStrategy(rpc_gas_price_strategy)
    claim_cost_gas = gas_measurements()["OneToN.claim"]

    gas_price = web3.eth.generateGasPrice()
    assert gas_price is not None, "Could not generate gas price"

    claim_cost_eth = claim_cost_gas * gas_price * GAS_COST_SAFETY_MARGIN
    return TokenAmount(int(claim_cost_eth / rdn_per_eth))
예제 #8
0
def get_approximate_registration_cost(web3: Web3) -> int:
    gas_costs = gas_measurements()
    gas_cost = (
        gas_costs["CustomToken.approve"]
        + gas_costs["ServiceRegistry.deposit"]
        + gas_costs["ServiceRegistry.setURL"]
    )

    gas_price = web3.eth.generate_gas_price()
    assert gas_price is not None, "No gas price strategy set"

    return gas_cost * gas_price
예제 #9
0
def get_required_gas_estimate(raiden: "RaidenService",
                              channels_to_open: int = 0) -> int:
    num_opening_channels = 0
    num_opened_channels = 0
    num_closing_channels = 0
    num_closed_channels = 0
    num_settling_channels = 0
    num_settled_channels = 0

    # Only use the token networks that have been instantiated. Instantiating
    # the token networks here has a very high performance impact for a registry
    # with lots of tokens.
    #
    # The lock is being acquired to prevent chnages to the dictionary while
    # iterating over it.
    with raiden.proxy_manager.token_network_creation_lock:
        num_opening_channels = sum(
            token_network.opening_channels_count for token_network in
            raiden.proxy_manager.address_to_token_network.values())

    chain_state = views.state_from_raiden(raiden)
    registry_address = raiden.default_registry.address
    token_addresses = views.get_token_identifiers(chain_state,
                                                  registry_address)

    for token_address in token_addresses:
        num_opened_channels += len(
            views.get_channelstate_open(chain_state, registry_address,
                                        token_address))
        num_closing_channels += len(
            views.get_channelstate_closing(chain_state, registry_address,
                                           token_address))
        num_closed_channels += len(
            views.get_channelstate_closed(chain_state, registry_address,
                                          token_address))
        num_settling_channels += len(
            views.get_channelstate_settling(chain_state, registry_address,
                                            token_address))
        num_settled_channels += len(
            views.get_channelstate_settled(chain_state, registry_address,
                                           token_address))

    return _get_required_gas_estimate(
        gas_measurements=gas_measurements(
            raiden.contract_manager.contracts_version),
        opening_channels=num_opening_channels + channels_to_open,
        opened_channels=num_opened_channels,
        closing_channels=num_closing_channels,
        closed_channels=num_closed_channels,
        settling_channels=num_settling_channels,
        settled_channels=num_settled_channels,
    )
예제 #10
0
def check_gas_reserve(web3: Web3, private_key: str) -> None:
    """ Check periodically for gas reserve in the account """
    gas_price = web3.eth.gasPrice
    gas_limit = gas_measurements()["MonitoringService.monitor"]
    estimated_required_balance = gas_limit * gas_price * DEFAULT_GAS_BUFFER_FACTOR
    estimated_required_balance_eth = Web3.fromWei(estimated_required_balance,
                                                  "ether")
    current_balance = web3.eth.getBalance(private_key_to_address(private_key))
    if current_balance < estimated_required_balance:
        log.error(
            "Your account's balance is below the estimated gas reserve of "
            f"{estimated_required_balance_eth} Eth. You will be be unable "
            "to perform on-chain transactions and cannot monitor any channels. "
            "Please add funds to your account as soon as possible.")
예제 #11
0
def _get_required_gas_estimate_for_state(raiden: "RaidenService") -> int:
    num_opening_channels = 0
    num_opened_channels = 0
    num_closing_channels = 0
    num_closed_channels = 0
    num_settling_channels = 0
    num_settled_channels = 0

    # Only use the token networks that have been instantiated. Instantiating
    # the token networks here can have a high performance impacet for a token
    # network registry with lots of registeres tokens.
    with raiden.proxy_manager.token_network_creation_lock:
        num_opening_channels = sum(
            token_network.opening_channels_count for token_network in
            raiden.proxy_manager.address_to_token_network.values())

    chain_state = views.state_from_raiden(raiden)
    registry_address = raiden.default_registry.address
    token_addresses = views.get_token_identifiers(chain_state,
                                                  registry_address)

    for token_address in token_addresses:
        num_opened_channels += len(
            views.get_channelstate_open(chain_state, registry_address,
                                        token_address))
        num_closing_channels += len(
            views.get_channelstate_closing(chain_state, registry_address,
                                           token_address))
        num_closed_channels += len(
            views.get_channelstate_closed(chain_state, registry_address,
                                          token_address))
        num_settling_channels += len(
            views.get_channelstate_settling(chain_state, registry_address,
                                            token_address))
        num_settled_channels += len(
            views.get_channelstate_settled(chain_state, registry_address,
                                           token_address))

    return _get_required_gas_estimate(
        gas_measurements=gas_measurements(
            raiden.contract_manager.contracts_version),
        opening_channels=num_opening_channels,
        opened_channels=num_opened_channels,
        closing_channels=num_closing_channels,
        closed_channels=num_closed_channels,
        settling_channels=num_settling_channels,
        settled_channels=num_settled_channels,
    )
예제 #12
0
def _get_required_gas_estimate_for_state(raiden: "RaidenService") -> int:
    chain_state = views.state_from_raiden(raiden)
    registry_address = raiden.default_registry.address
    token_addresses = views.get_token_identifiers(chain_state,
                                                  registry_address)
    measurements = gas_measurements(raiden.contract_manager.contracts_version)

    gas_estimate = 0

    for token_address in token_addresses:
        token_network_address = views.get_token_network_address_by_token_address(
            chain_state=chain_state,
            token_network_registry_address=registry_address,
            token_address=token_address,
        )
        if token_network_address is None:
            continue

        num_opening_channels = raiden.proxy_manager.token_network(
            token_network_address).opening_channels_count
        num_opened_channels = len(
            views.get_channelstate_open(chain_state, registry_address,
                                        token_address))
        num_closing_channels = len(
            views.get_channelstate_closing(chain_state, registry_address,
                                           token_address))
        num_closed_channels = len(
            views.get_channelstate_closed(chain_state, registry_address,
                                          token_address))
        num_settling_channels = len(
            views.get_channelstate_settling(chain_state, registry_address,
                                            token_address))
        num_settled_channels = len(
            views.get_channelstate_settled(chain_state, registry_address,
                                           token_address))

        gas_estimate += _get_required_gas_estimate(
            gas_measurements=measurements,
            opening_channels=num_opening_channels,
            opened_channels=num_opened_channels,
            closing_channels=num_closing_channels,
            closed_channels=num_closed_channels,
            settling_channels=num_settling_channels,
            settled_channels=num_settled_channels,
        )

    return gas_estimate
예제 #13
0
    def token_network_from_registry(
        self,
        token_network_registry_address: TokenNetworkRegistryAddress,
        token_address: TokenAddress,
        block_identifier: BlockSpecification = "latest",
    ) -> TokenNetwork:
        token_network_registry = self.token_network_registry(
            token_network_registry_address)
        token_network_address = token_network_registry.get_token_network(
            token_address=token_address, block_identifier=block_identifier)

        if token_network_address is None:
            raise ValueError(
                f"{to_checksum_address(token_network_registry_address)} does not "
                f"have the token {to_checksum_address(token_address)} "
                f"registered.")

        with self._token_network_creation_lock:
            if token_network_address not in self.address_to_token_network:
                metadata = TokenNetworkMetadata(
                    deployed_at=None,
                    address=Address(token_network_address),
                    abi=self.contract_manager.get_contract_abi(
                        CONTRACT_TOKEN_NETWORK),
                    gas_measurements=gas_measurements(
                        self.contract_manager.contracts_version),
                    runtime_bytecode=EVMBytecode(
                        decode_hex(
                            self.contract_manager.get_runtime_hexcode(
                                CONTRACT_TOKEN_NETWORK))),
                    token_network_registry_address=
                    token_network_registry_address,
                    filters_start_at=token_network_registry.metadata.
                    filters_start_at,
                )

                self.address_to_token_network[
                    token_network_address] = TokenNetwork(
                        jsonrpc_client=self.client,
                        contract_manager=self.contract_manager,
                        proxy_manager=self,
                        metadata=metadata,
                    )

        return self.address_to_token_network[token_network_address]
예제 #14
0
    def __init__(
        self,
        jsonrpc_client: JSONRPCClient,
        user_deposit_address: UserDepositAddress,
        contract_manager: ContractManager,
        proxy_manager: "ProxyManager",
        block_identifier: BlockIdentifier,
    ) -> None:
        if not is_binary_address(user_deposit_address):
            raise ValueError("Expected binary address format for token nework")

        check_address_has_code_handle_pruned_block(
            client=jsonrpc_client,
            address=Address(user_deposit_address),
            contract_name=CONTRACT_USER_DEPOSIT,
            expected_code=decode_hex(
                contract_manager.get_runtime_hexcode(CONTRACT_USER_DEPOSIT)),
            given_block_identifier=block_identifier,
        )

        self.client = jsonrpc_client

        self.address = user_deposit_address
        self.node_address = self.client.address
        self.contract_manager = contract_manager
        self.gas_measurements = gas_measurements(
            self.contract_manager.contracts_version)

        self.proxy_manager = proxy_manager

        self.proxy = jsonrpc_client.new_contract_proxy(
            abi=self.contract_manager.get_contract_abi(CONTRACT_USER_DEPOSIT),
            contract_address=Address(user_deposit_address),
        )

        # Keeps track of the current in-flight deposits, to avoid sending
        # unecessary transactions.
        self._inflight_deposits: Dict[Address, InflightDeposit] = dict()

        # Don't allow concurrent withdraw_plan and withdraw calls.
        # This simplifies the precondition checks.
        self._withdraw_lock = Lock()