Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Use solana instead of client
  • Loading branch information
afalaleev committed Feb 22, 2022
commit d538a20a5d17be88746f7961db46e9469025b35d
38 changes: 10 additions & 28 deletions proxy/common_neon/address.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from __future__ import annotations

import random
import base64

from eth_keys import keys as eth_keys
from hashlib import sha256
Expand All @@ -8,9 +9,8 @@
from typing import NamedTuple

from .layouts import ACCOUNT_INFO_LAYOUT
from ..environment import neon_cli, ETH_TOKEN_MINT_ID, EVM_LOADER_ID
from ..environment import ETH_TOKEN_MINT_ID, EVM_LOADER_ID
from .constants import ACCOUNT_SEED_VERSION
from solana.rpc.commitment import Confirmed


class EthereumAddress:
Expand Down Expand Up @@ -60,35 +60,17 @@ def getTokenAddr(account):
return get_associated_token_address(PublicKey(account), ETH_TOKEN_MINT_ID)


class AccountInfo(NamedTuple):
class AccountInfoLayout(NamedTuple):
ether: eth_keys.PublicKey
trx_count: int
code_account: PublicKey
state: int

def is_payed(self) -> bool:
return self.state != 0

@staticmethod
def frombytes(data):
def frombytes(data) -> AccountInfoLayout:
cont = ACCOUNT_INFO_LAYOUT.parse(data)
return AccountInfo(cont.ether, int.from_bytes(cont.trx_count, 'little'), PublicKey(cont.code_account), cont.state)


def _getAccountData(client, account, expected_length, owner=None):
info = client.get_account_info(account, commitment=Confirmed)['result']['value']
if info is None:
raise Exception("Can't get information about {}".format(account))

data = base64.b64decode(info['data'][0])
if len(data) < expected_length:
raise Exception("Wrong data length for account data {}".format(account))
return data


def getAccountInfo(client, eth_account: EthereumAddress):
account_sol, nonce = ether2program(eth_account)
info = _getAccountData(client, account_sol, ACCOUNT_INFO_LAYOUT.sizeof())
return AccountInfo.frombytes(info)


def isPayed(client, address: str):
acc_info: AccountInfo = getAccountInfo(client, EthereumAddress(address))
return acc_info.state != 0
return AccountInfoLayout(cont.ether, int.from_bytes(cont.trx_count, 'little'),
PublicKey(cont.code_account), cont.state)
33 changes: 14 additions & 19 deletions proxy/common_neon/estimate.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,34 +59,30 @@ def iteration_info(self) -> Tuple[int, int]:
final_steps = EVM_STEPS
return final_steps, full_step_iterations

@logged_group("neon.Proxy")
def simple_neon_tx_strategy(self, *, logger):
def simple_neon_tx_strategy(self):
gas = evm_step_cost(2) * (self.tx_sender.steps_emulated if self.tx_sender.steps_emulated > EVM_STEPS else EVM_STEPS)
logger.debug(f'estimate simple_neon_tx_strategy: {gas}')
self.debug(f'estimate simple_neon_tx_strategy: {gas}')
return gas

@logged_group("neon.Proxy")
def iterative_neon_tx_strategy(self, *, logger):
def iterative_neon_tx_strategy(self):
begin_iteration = 1
final_steps, full_step_iterations = self.iteration_info()
steps = begin_iteration * EVM_STEPS + full_step_iterations * self.step_count + final_steps
gas = steps * evm_step_cost(1)
logger.debug(f'estimate iterative_neon_tx_strategy: {gas}')
self.debug(f'estimate iterative_neon_tx_strategy: {gas}')
return gas

@logged_group("neon.Proxy")
def holder_neon_tx_strategy(self, *, logger):
def holder_neon_tx_strategy(self):
begin_iteration = 1
msg = get_holder_msg(self.tx_sender.eth_tx)
holder_iterations = math.ceil(len(msg) / HOLDER_MSG_SIZE)
final_steps, full_step_iterations = self.iteration_info()
steps = (begin_iteration + holder_iterations) * EVM_STEPS + full_step_iterations * self.step_count + final_steps
gas = steps * evm_step_cost(1)
logger.debug(f'estimate holder_neon_tx_strategy: {gas}')
self.debug(f'estimate holder_neon_tx_strategy: {gas}')
return gas

@logged_group("neon.Proxy")
def allocated_space(self, *, logger):
def allocated_space(self):
space = 0
for s in self.tx_sender._create_account_list:
if s.NAME == NeonCreateContractTxStage.NAME:
Expand All @@ -95,14 +91,13 @@ def allocated_space(self, *, logger):
space += ACCOUNT_MAX_SIZE + SPL_TOKEN_ACCOUNT_SIZE + ACCOUNT_STORAGE_OVERHEAD * 2

space += self.tx_sender.unpaid_space
logger.debug(f'allocated space: {space}')
self.debug(f'allocated space: {space}')
return space

@logged_group("neon.Proxy")
def estimate(self, *, logger):
def estimate(self):
self.tx_sender.operator_key = PublicKey(os.urandom(32))
self.tx_sender._call_emulated(self.sender)
self.tx_sender._parse_accounts_list();
self.tx_sender._parse_accounts_list()

gas_for_trx = max(self.simple_neon_tx_strategy(), self.iterative_neon_tx_strategy(), self.holder_neon_tx_strategy())
gas_for_space = self.allocated_space() * EVM_BYTE_COST
Expand All @@ -112,8 +107,8 @@ def estimate(self, *, logger):
# if gas < 21000:
# gas = 21000

logger.debug(f'extra_gas: {EXTRA_GAS}')
logger.debug(f'gas_for_space: {gas_for_space}')
logger.debug(f'gas_for_trx: {gas_for_trx}')
logger.debug(f'estimated gas: {gas}')
self.debug(f'extra_gas: {EXTRA_GAS}')
self.debug(f'gas_for_space: {gas_for_space}')
self.debug(f'gas_for_trx: {gas_for_trx}')
self.debug(f'estimated gas: {gas}')
return hex(gas)
6 changes: 3 additions & 3 deletions proxy/common_neon/solana_interactor.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@

from ..common_neon.layouts import ACCOUNT_INFO_LAYOUT
from ..common_neon.address import EthereumAddress, ether2program
from ..common_neon.address import AccountInfo as NeonAccountInfo
from ..common_neon.address import AccountInfoLayout as AccountInfoLayout


class SolTxError(Exception):
Expand Down Expand Up @@ -244,15 +244,15 @@ def get_token_account_balance_list(self, pubkey_list: [Union[str, PublicKey]], c

return balance_list

def get_neon_account_info(self, eth_account: EthereumAddress) -> Optional[NeonAccountInfo]:
def get_account_info_layout(self, eth_account: EthereumAddress) -> Optional[AccountInfoLayout]:
account_sol, nonce = ether2program(eth_account)
info = self.get_account_info(account_sol)
if info is None:
return None
elif len(info.data) < ACCOUNT_INFO_LAYOUT.sizeof():
raise RuntimeError(f"Wrong data length for account data {account_sol}: " +
f"{len(info.data)} < {ACCOUNT_INFO_LAYOUT.sizeof()}")
return NeonAccountInfo.frombytes(info.data)
return AccountInfoLayout.frombytes(info.data)

def get_multiple_rent_exempt_balances_for_size(self, size_list: [int], commitment='confirmed') -> [int]:
opts = {
Expand Down
6 changes: 3 additions & 3 deletions proxy/common_neon/transaction_sender.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
from solana.blockhash import Blockhash
from solana.account import Account as SolanaAccount

from .address import accountWithSeed, getTokenAddr, EthereumAddress, isPayed
from .address import accountWithSeed, getTokenAddr, EthereumAddress
from ..common_neon.errors import EthereumError
from .constants import STORAGE_SIZE, EMPTY_STORAGE_TAG, FINALIZED_STORAGE_TAG, ACCOUNT_SEED_VERSION
from .emulator_interactor import call_emulated
Expand Down Expand Up @@ -446,7 +446,7 @@ def _validate_whitelist(self):
raise Exception(f'Contract account {self.deployed_contract} is not allowed for deployment')

def _validate_tx_count(self):
info = self.solana.get_neon_account_info(EthereumAddress(self.eth_sender))
info = self.solana.get_account_info_layout(EthereumAddress(self.eth_sender))
if not info:
return

Expand Down Expand Up @@ -565,7 +565,7 @@ def _parse_accounts_list(self):
elif account_desc["storage_increment"]:
self.unpaid_space += account_desc["storage_increment"]

if not isPayed(self.solana.client, account_desc['address']):
if not self.solana.get_account_info_layout(account_desc['address']).is_payed():
self.debug(f'found losted account {account_desc["account"]}')
self.unpaid_space += ACCOUNT_MAX_SIZE + SPL_TOKEN_ACCOUNT_SIZE + ACCOUNT_STORAGE_OVERHEAD * 2

Expand Down
2 changes: 1 addition & 1 deletion proxy/plugin/solana_rest_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -265,7 +265,7 @@ def eth_call(self, obj, tag):
def eth_getTransactionCount(self, account, tag):
self.debug('eth_getTransactionCount: %s', account)
try:
acc_info = self._solana.get_neon_account_info(EthereumAddress(account))
acc_info = self._solana.get_account_info_layout(EthereumAddress(account))
return hex(acc_info.trx_count)
except Exception as err:
self.debug(f"eth_getTransactionCount: Can't get account info: {err}")
Expand Down