Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
50 commits
Select commit Hold shift + click to select a range
5a3e9a6
Use neonlabsorg/evm_loader:stable image for build
Oct 12, 2021
e59efe2
Merge remote-tracking branch 'origin/develop'
Oct 19, 2021
44dd154
Merge remote-tracking branch 'origin/develop'
Oct 21, 2021
21d20a1
Launch all uniswap tests for master branch
vasiliy-zaznobin Nov 16, 2021
4e03e73
Merge remote-tracking branch 'origin/develop'
Nov 16, 2021
e496b27
VERSION = (0, 4, 0)
vasiliy-zaznobin Nov 16, 2021
fe41d64
EVM_LOADER_REVISION:=v0.4.0
vasiliy-zaznobin Nov 16, 2021
5467c50
EVM_LOADER_REVISION:=stable
vasiliy-zaznobin Nov 16, 2021
e15d847
Merge remote-tracking branch 'origin/develop'
vasiliy-zaznobin Dec 7, 2021
2416591
NEON_PROXY_PKG_VERSION = '0.5.0'
vasiliy-zaznobin Dec 7, 2021
168e428
VERSION = (0, 4, 0)
vasiliy-zaznobin Nov 16, 2021
3125645
EVM_LOADER_REVISION:=v0.4.0
vasiliy-zaznobin Nov 16, 2021
07f175d
EVM_LOADER_REVISION:=stable
vasiliy-zaznobin Nov 16, 2021
0bbb26b
289 implement eth get storage at (#298)
ivandzen Nov 18, 2021
7841b07
#256 create and airdrop eth account (#259)
rozhkovdmitrii Nov 18, 2021
ce05c81
#305 Remove extra args from ether2program (#309)
rozhkovdmitrii Nov 19, 2021
6ca860a
Change default logDB postgress pass (#317)
rozhkovdmitrii Nov 23, 2021
b3b322f
#311 Create account and airdrop on gas estimation if it's preset
rozhkovdmitrii Nov 24, 2021
c860ed0
neonbals/neon-evm#371 Update STORAGE_ACCOUNT_INFO_LAYOUT (#315)
sinev-valentine Nov 24, 2021
9bb3f89
319 add neon cli version handler (#325)
vasiliy-zaznobin Nov 24, 2021
081bc75
fix storage account check (#327)
sinev-valentine Nov 24, 2021
7845ca9
#320 add neon proxy version handler (#323)
vasiliy-zaznobin Nov 25, 2021
f299c57
313 concurrent execution of solana program dump (#314)
ivandzen Nov 25, 2021
0a5dc2d
fix scripts (#329)
ivandzen Nov 25, 2021
7964cad
#318 JSON_RPC "params" field may be omitted (#322)
mich-master Nov 26, 2021
01df8a4
#336 indexer refactoring (#340)
ivandzen Dec 2, 2021
d9a8e51
#333 fix indexer errors (#334)
otselnik Dec 2, 2021
f4b178c
#291 Proxy refactoring (#324)
otselnik Dec 2, 2021
5ced809
#337 сreate base airdropper service (#343)
ivandzen Dec 3, 2021
ae7b392
#337 fix running airdropper (#347)
ivandzen Dec 6, 2021
9feca6a
#351 fix canceller droping running transactions (#352)
otselnik Dec 6, 2021
2f0a0df
349 improve neon proxy logging to filter a request and the correspond…
vasiliy-zaznobin Dec 6, 2021
3b36864
#349 Fix using log sending solana transaction (#353)
vasiliy-zaznobin Dec 6, 2021
6bb8509
#295 iterative execution (#332)
otselnik Dec 6, 2021
56044ea
#354 Check result for errors (#355)
otselnik Dec 7, 2021
0bad34c
#360 pass transaction too large upper (#361)
otselnik Dec 7, 2021
9e8344c
NEON_PROXY_PKG_VERSION = '0.5.0'
vasiliy-zaznobin Dec 7, 2021
981c178
Merge remote-tracking branch 'origin/develop->master_0.5.0' into deve…
vasiliy-zaznobin Dec 7, 2021
4c87c95
Merge pull request #362 from neonlabsorg/develop->master_0.5.0
vasiliy-zaznobin Dec 7, 2021
2ccfcce
Merge remote-tracking branch 'origin/develop' into develop->master_0.…
vasiliy-zaznobin Dec 8, 2021
28881d2
Merge pull request #363 from neonlabsorg/develop->master_0.5.0-rc2
vasiliy-zaznobin Dec 8, 2021
3771577
Merge remote-tracking branch 'origin/develop' into develop->master_0.…
vasiliy-zaznobin Dec 13, 2021
1e4c4ab
Merge pull request #372 from neonlabsorg/develop->master_0.5.0_rc3
vasiliy-zaznobin Dec 13, 2021
cacf6f8
Master 0.5.0 rc4 (#380)
vasiliy-zaznobin Dec 16, 2021
5ce4d3d
0.5.0-rc4 (#386)
vasiliy-zaznobin Dec 16, 2021
6a3dbd9
Neon-proxy/v0.5.0 (#388)
vasiliy-zaznobin Dec 17, 2021
424cf24
Merge remote-tracking branch 'origin/master' into master_v0.5.0->develop
vasiliy-zaznobin Dec 17, 2021
5aef94b
Neon-proxy/v0.5.1-dev
vasiliy-zaznobin Dec 17, 2021
03c051b
stable->latest
vasiliy-zaznobin Dec 17, 2021
3e43911
VERSION = (0, 5, 1)
vasiliy-zaznobin Dec 17, 2021
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
Next Next commit
#295 iterative execution (#332)
* #291 extract transaction sender class

* #291 move perm accs to transaction sender

* #291 fix state

* #291 fix errors

* #291 merge fixes

* #291 refactoring

* #291 move EXTRA_GAS to environment

* #291 capitalize CONFIRMATION_CHECK_DELAY

* #291 sort imports

* #291 relative paths

* #291 Should be fixed in #326

* #291 testing chnages

* fix storage account check

* #291 rename `trx_with_create_and_airdrop` -> `make_trx_with_create_and_airdrop`

* #295 fix state

* #291 iterative combined

* #295 do not get measurments

* #291 pull request fixes

* #295 turn combined instructions ON

* #295 make neon_instructions return transasactions

* #291 merge fix

* #295 get rid of `USE_COMBINED_START_CONTINUE`

* #295 requested fixes

* #295 call_continue_bucked refactoring

* #295 fix

* #295 leave only combined iterative transactions

* #295 move constants into class

* #295 refactoring

Co-authored-by: sinev-valentine <[email protected]>
  • Loading branch information
2 people authored and vasiliy-zaznobin committed Dec 7, 2021
commit 6bb8509c24b84f23577d2f5993e6c3de98261d47
1 change: 1 addition & 0 deletions proxy/common_neon/errors.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ def getError(self):
if self.data: error['data'] = self.data
return error


class SolanaErrors(Enum):
AccountNotFound = "Invalid param: could not find account"

Expand Down
58 changes: 31 additions & 27 deletions proxy/common_neon/neon_instruction.py
Original file line number Diff line number Diff line change
Expand Up @@ -283,14 +283,17 @@ def make_noniterative_call_transaction(self, length_before: int = 0) -> Transact
return trx


def make_partial_call_instruction(self) -> TransactionInstruction:
return TransactionInstruction(
def make_continue_transaction(self, steps, index=None) -> Transaction:
data = bytearray.fromhex("14") + self.collateral_pool_index_buf + steps.to_bytes(8, byteorder="little")
if index:
data = data + index.to_bytes(8, byteorder="little")

return Transaction().add(TransactionInstruction(
program_id = EVM_LOADER_ID,
data = bytearray.fromhex("13") + self.collateral_pool_index_buf + int(0).to_bytes(8, byteorder="little") + self.msg,
data = data,
keys = [
AccountMeta(pubkey=self.storage, is_signer=False, is_writable=True),

AccountMeta(pubkey=SYSVAR_INSTRUCTION_PUBKEY, is_signer=False, is_writable=False),
AccountMeta(pubkey=self.operator_account, is_signer=True, is_writable=True),
AccountMeta(pubkey=self.collateral_pool_address, is_signer=False, is_writable=True),
AccountMeta(pubkey=self.operator_neon_address, is_signer=False, is_writable=True),
Expand All @@ -301,28 +304,19 @@ def make_partial_call_instruction(self) -> TransactionInstruction:

AccountMeta(pubkey=SYSVAR_INSTRUCTION_PUBKEY, is_signer=False, is_writable=False),
] + obligatory_accounts
)


def make_iterative_call_transaction(self, length_before: int = 0) -> Transaction:
trx = Transaction()
trx.add(self.make_keccak_instruction(length_before + 1, len(self.eth_trx.unsigned_msg()), 13))
trx.add(self.make_partial_call_instruction())
return trx
))


def make_call_from_account_instruction(self) -> Transaction:
def make_cancel_transaction(self) -> Transaction:
return Transaction().add(TransactionInstruction(
program_id = EVM_LOADER_ID,
data = bytearray.fromhex("16") + self.collateral_pool_index_buf + int(0).to_bytes(8, byteorder="little"),
data = bytearray.fromhex("15") + self.eth_trx.nonce.to_bytes(8, 'little'),
keys = [
AccountMeta(pubkey=self.holder, is_signer=False, is_writable=True),
AccountMeta(pubkey=self.storage, is_signer=False, is_writable=True),

AccountMeta(pubkey=self.operator_account, is_signer=True, is_writable=True),
AccountMeta(pubkey=self.collateral_pool_address, is_signer=False, is_writable=True),
AccountMeta(pubkey=self.operator_neon_address, is_signer=False, is_writable=True),
AccountMeta(pubkey=self.caller_token, is_signer=False, is_writable=True),
AccountMeta(pubkey=INCINERATOR_PUBKEY, is_signer=False, is_writable=True),
AccountMeta(pubkey=SYS_PROGRAM_ID, is_signer=False, is_writable=False),

] + self.eth_accounts + [
Expand All @@ -332,17 +326,15 @@ def make_call_from_account_instruction(self) -> Transaction:
))


def make_continue_instruction(self, steps, index=None) -> Transaction:
data = bytearray.fromhex("14") + self.collateral_pool_index_buf + steps.to_bytes(8, byteorder="little")
if index:
data = data + index.to_bytes(8, byteorder="little")

return Transaction().add(TransactionInstruction(
def make_partial_call_or_continue_instruction(self, steps: int = 0) -> TransactionInstruction:
data = bytearray.fromhex("0D") + self.collateral_pool_index_buf + steps.to_bytes(8, byteorder="little") + self.msg
return TransactionInstruction(
program_id = EVM_LOADER_ID,
data = data,
keys = [
AccountMeta(pubkey=self.storage, is_signer=False, is_writable=True),

AccountMeta(pubkey=SYSVAR_INSTRUCTION_PUBKEY, is_signer=False, is_writable=False),
AccountMeta(pubkey=self.operator_account, is_signer=True, is_writable=True),
AccountMeta(pubkey=self.collateral_pool_address, is_signer=False, is_writable=True),
AccountMeta(pubkey=self.operator_neon_address, is_signer=False, is_writable=True),
Expand All @@ -353,19 +345,31 @@ def make_continue_instruction(self, steps, index=None) -> Transaction:

AccountMeta(pubkey=SYSVAR_INSTRUCTION_PUBKEY, is_signer=False, is_writable=False),
] + obligatory_accounts
))
)


def make_cancel_instruction(self) -> Transaction:
def make_partial_call_or_continue_transaction(self, steps: int = 0, length_before: int = 0) -> Transaction:
trx = Transaction()
trx.add(self.make_keccak_instruction(length_before + 1, len(self.eth_trx.unsigned_msg()), 13))
trx.add(self.make_partial_call_or_continue_instruction(steps))
return trx


def make_partial_call_or_continue_from_account_data(self, steps, index=None) -> Transaction:
data = bytearray.fromhex("0E") + self.collateral_pool_index_buf + steps.to_bytes(8, byteorder='little')
if index:
data = data + index.to_bytes(8, byteorder="little")
return Transaction().add(TransactionInstruction(
program_id = EVM_LOADER_ID,
data = bytearray.fromhex("15") + self.eth_trx.nonce.to_bytes(8, 'little'),
data = data,
keys = [
AccountMeta(pubkey=self.holder, is_signer=False, is_writable=True),
AccountMeta(pubkey=self.storage, is_signer=False, is_writable=True),

AccountMeta(pubkey=self.operator_account, is_signer=True, is_writable=True),
AccountMeta(pubkey=self.collateral_pool_address, is_signer=False, is_writable=True),
AccountMeta(pubkey=self.operator_neon_address, is_signer=False, is_writable=True),
AccountMeta(pubkey=self.caller_token, is_signer=False, is_writable=True),
AccountMeta(pubkey=INCINERATOR_PUBKEY, is_signer=False, is_writable=True),
AccountMeta(pubkey=SYS_PROGRAM_ID, is_signer=False, is_writable=False),

] + self.eth_accounts + [
Expand Down
14 changes: 13 additions & 1 deletion proxy/common_neon/solana_interactor.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,20 @@
import re
import time

from solana.rpc.api import Client as SolanaClient
from solana.rpc.commitment import Confirmed
from solana.rpc.types import TxOpts

from .costs import update_transaction_cost
from .utils import get_from_dict
from ..environment import EVM_LOADER_ID, CONFIRMATION_CHECK_DELAY, LOG_SENDING_SOLANA_TRANSACTION

logger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG)


class SolanaInteractor:
def __init__(self, signer, client) -> None:
def __init__(self, signer, client: SolanaClient) -> None:
self.signer = signer
self.client = client

Expand Down Expand Up @@ -194,6 +196,16 @@ def check_if_program_exceeded_instructions(err_result):
return False


def check_if_storage_is_empty_error(err_result):
error_arr = get_from_dict(err_result, "data", "err", "InstructionError")
if error_arr is not None and isinstance(error_arr, list):
error_dict = error_arr[1]
if isinstance(error_dict, dict) and 'Custom' in error_dict:
if error_dict['Custom'] == 1 or error_dict['Custom'] == 4:
return True
return False


def check_if_continue_returned(result):
tx_info = result['result']
accounts = tx_info["transaction"]["message"]["accountKeys"]
Expand Down
139 changes: 109 additions & 30 deletions proxy/common_neon/transaction_sender.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import json
import logging
import math
import os
import rlp
import time
Expand All @@ -18,7 +19,8 @@
from .emulator_interactor import call_emulated
from .layouts import ACCOUNT_INFO_LAYOUT
from .neon_instruction import NeonInstruction
from .solana_interactor import SolanaInteractor, check_if_continue_returned, check_if_program_exceeded_instructions
from .solana_interactor import SolanaInteractor, check_if_continue_returned, \
check_if_program_exceeded_instructions, check_if_storage_is_empty_error
from ..environment import EVM_LOADER_ID
from ..plugin.eth_proto import Trx as EthTrx

Expand Down Expand Up @@ -67,7 +69,7 @@ def execute(self):
try:
if call_iterative:
try:
return iterative_executor.call_signed_iterative()
return iterative_executor.call_signed_iterative_combined()
except Exception as err:
logger.debug(str(err))
if str(err).startswith("transaction too large:"):
Expand All @@ -77,7 +79,7 @@ def execute(self):
raise

if call_from_holder:
return iterative_executor.call_signed_with_holder_acc()
return iterative_executor.call_signed_with_holder_combined()
finally:
self.free_perm_accs()

Expand All @@ -93,7 +95,7 @@ def create_noniterative_executor(self):

def create_iterative_executor(self):
self.instruction.init_iterative(self.storage, self.holder, self.perm_accs_id)
return IterativeTransactionSender(self.sender, self.instruction, self.create_acc_trx, self.eth_trx, self.steps)
return IterativeTransactionSender(self.sender, self.instruction, self.create_acc_trx, self.eth_trx, self.steps, self.steps_emulated)


def init_perm_accs(self):
Expand Down Expand Up @@ -302,6 +304,8 @@ def create_account_list_by_emulate(self):
AccountMeta(pubkey=self.caller_token, is_signer=False, is_writable=True),
] + add_keys_05

self.steps_emulated = output_json["steps_executed"]


class NoniterativeTransactionSender:
def __init__(self, solana_interactor: SolanaInteractor, neon_instruction: NeonInstruction, create_acc_trx: Transaction, eth_trx: EthTrx):
Expand All @@ -321,53 +325,52 @@ def call_signed_noniterative(self):


class IterativeTransactionSender:
def __init__(self, solana_interactor: SolanaInteractor, neon_instruction: NeonInstruction, create_acc_trx: Transaction, eth_trx: EthTrx, steps: int):
CONTINUE_REGULAR = 'ContinueV02'
CONTINUE_COMBINED = 'PartialCallOrContinueFromRawEthereumTX'
CONTINUE_HOLDER_COMB = 'ExecuteTrxFromAccountDataIterativeOrContinue'

def __init__(self, solana_interactor: SolanaInteractor, neon_instruction: NeonInstruction, create_acc_trx: Transaction, eth_trx: EthTrx, steps: int, steps_emulated: int):
self.sender = solana_interactor
self.instruction = neon_instruction
self.create_acc_trx = create_acc_trx
self.eth_trx = eth_trx
self.steps = steps
self.steps_emulated = steps_emulated
self.instruction_type = self.CONTINUE_REGULAR


def call_signed_iterative(self):
if len(self.create_acc_trx.instructions):
precall_txs = Transaction()
precall_txs.add(self.create_acc_trx)
self.sender.send_measured_transaction(precall_txs, self.eth_trx, 'CreateAccountsForTrx')

call_txs = self.instruction.make_iterative_call_transaction()

logger.debug("Partial call")
self.sender.send_measured_transaction(call_txs, self.eth_trx, 'PartialCallFromRawEthereumTXv02')

def call_signed_iterative_combined(self):
self.create_accounts_for_trx()
self.instruction_type = self.CONTINUE_COMBINED
return self.call_continue()


def call_signed_with_holder_acc(self):
def call_signed_with_holder_combined(self):
self.write_trx_to_holder_account()
if len(self.create_acc_trx.instructions):
precall_txs = Transaction()
precall_txs.add(self.create_acc_trx)
self.sender.send_measured_transaction(precall_txs, self.eth_trx, 'create_accounts_for_deploy')
self.create_accounts_for_trx()
self.instruction_type = self.CONTINUE_HOLDER_COMB
return self.call_continue()

# ExecuteTrxFromAccountDataIterative
logger.debug("ExecuteTrxFromAccountDataIterative:")
call_txs = self.instruction.make_call_from_account_instruction()
self.sender.send_measured_transaction(call_txs, self.eth_trx, 'ExecuteTrxFromAccountDataIterativeV02')

return self.call_continue()
def create_accounts_for_trx(self):
length = len(self.create_acc_trx.instructions)
if length == 0:
return
logger.debug(f"Create account for trx: {length}")
precall_txs = Transaction()
precall_txs.add(self.create_acc_trx)
self.sender.send_measured_transaction(precall_txs, self.eth_trx, 'CreateAccountsForTrx')


def write_trx_to_holder_account(self):
logger.debug('write_trx_to_holder_account')
msg = self.eth_trx.signature() + len(self.eth_trx.unsigned_msg()).to_bytes(8, byteorder="little") + self.eth_trx.unsigned_msg()

# Write transaction to transaction holder account
offset = 0
receipts = []
rest = msg
while len(rest):
(part, rest) = (rest[:1000], rest[1000:])
# logger.debug("sender_sol %s %s %s", sender_sol, holder, acc.public_key())
trx = self.instruction.make_write_transaction(offset, part)
receipts.append(self.sender.send_transaction_unconfirmed(trx))
offset += len(part)
Expand All @@ -377,6 +380,19 @@ def write_trx_to_holder_account(self):


def call_continue(self):
return_result = None
try:
return_result = self.call_continue_bucked()
except Exception as err:
logger.debug("call_continue_bucked_combined exception: {}".format(str(err)))

if return_result is not None:
return return_result

return self.call_continue_iterative()


def call_continue_iterative(self):
try:
return self.call_continue_step_by_step()
except Exception as err:
Expand All @@ -398,7 +414,7 @@ def call_continue_step_by_step(self):
def call_continue_step(self):
step_count = self.steps
while step_count > 0:
trx = self.instruction.make_continue_instruction(step_count)
trx = self.instruction.make_continue_transaction(step_count)

logger.debug("Step count {}".format(step_count))
try:
Expand All @@ -413,8 +429,71 @@ def call_continue_step(self):


def call_cancel(self):
trx = self.instruction.make_cancel_instruction()
trx = self.instruction.make_cancel_transaction()

logger.debug("Cancel")
result = self.sender.send_measured_transaction(trx, self.eth_trx, 'CancelWithNonce')
return result['result']['transaction']['signatures'][0]


def call_continue_bucked(self):
logger.debug("Send bucked combined: %s", self.instruction_type)
steps = self.steps

receipts = []
for index in range(math.ceil(self.steps_emulated/self.steps) + self.addition_count()):
try:
trx = self.make_bucked_trx(steps, index)
receipts.append(self.sender.send_transaction_unconfirmed(trx))
except SendTransactionError as err:
logger.error(f"Failed to call continue bucked, error: {err.result}")
if check_if_storage_is_empty_error(err.result):
pass
elif check_if_program_exceeded_instructions(err.result):
steps = int(steps * 90 / 100)
else:
raise
except Exception as err:
logger.debug(str(err))
if str(err).startswith('failed to get recent blockhash'):
pass
else:
raise

return self.collect_bucked_results(receipts, self.instruction_type)


def addition_count(self):
'''
How many transactions are needed depending on trx type:
CONTINUE_COMBINED: 2 (1 for begin and 1 for decreased steps)
CONTINUE_HOLDER_COMB: 1 for begin
0 otherwise
'''
addition_count = 0
if self.instruction_type == self.CONTINUE_COMBINED:
addition_count = 2
elif self.instruction_type == self.CONTINUE_HOLDER_COMB:
addition_count = 1
return addition_count


def make_bucked_trx(self, steps, index):
if self.instruction_type == self.CONTINUE_REGULAR:
return self.instruction.make_continue_transaction(steps, index)
elif self.instruction_type == self.CONTINUE_COMBINED:
return self.instruction.make_partial_call_or_continue_transaction(steps - index)
elif self.instruction_type == self.CONTINUE_HOLDER_COMB:
return self.instruction.make_partial_call_or_continue_from_account_data(steps, index)
else:
raise Exception("Unknown continue type: {}".format(self.instruction_type))


def collect_bucked_results(self, receipts, reason):
logger.debug(f"Collected bucked results: {receipts}")
result_list = self.sender.collect_results(receipts, eth_trx=self.eth_trx, reason=reason)
for result in result_list:
# self.sender.get_measurements(result)
signature = check_if_continue_returned(result)
if signature:
return signature
1 change: 0 additions & 1 deletion proxy/environment.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@

NEW_USER_AIRDROP_AMOUNT = int(os.environ.get("NEW_USER_AIRDROP_AMOUNT", "0"))
CONFIRMATION_CHECK_DELAY = float(os.environ.get("NEON_CONFIRMATION_CHECK_DELAY", "0.1"))
USE_COMBINED_START_CONTINUE = os.environ.get("USE_COMBINED_START_CONTINUE", "NO") == "YES"
CONTINUE_COUNT_FACTOR = int(os.environ.get("CONTINUE_COUNT_FACTOR", "3"))
TIMEOUT_TO_RELOAD_NEON_CONFIG = int(os.environ.get("TIMEOUT_TO_RELOAD_NEON_CONFIG", "3600"))
MINIMAL_GAS_PRICE=int(os.environ.get("MINIMAL_GAS_PRICE", 1))*10**9
Expand Down
Loading