diff --git a/proxy/common_neon/solana_interactor.py b/proxy/common_neon/solana_interactor.py index 660ba9b25..56015e127 100644 --- a/proxy/common_neon/solana_interactor.py +++ b/proxy/common_neon/solana_interactor.py @@ -133,6 +133,11 @@ def collect_results(self, receipts, eth_trx=None, reason=None): @staticmethod def extract_measurements_from_receipt(receipt): + if check_for_errors(receipt): + logger.warning("Can't get measurements from receipt with error") + logger.info("Failed result: %s"%json.dumps(receipt, indent=3)) + return [] + log_messages = receipt['result']['meta']['logMessages'] transaction = receipt['result']['transaction'] accounts = transaction['message']['accountKeys'] @@ -185,19 +190,47 @@ def extract_measurements_from_receipt(receipt): return result -def check_if_program_exceeded_instructions(err_result): - err_instruction = "Program failed to complete: exceeded maximum number of instructions allowed" - err_budget = "failed: Computational budget exceeded" +def get_error_definition_from_reciept(receipt): + err_from_reciept = get_from_dict(receipt, 'result', 'meta', 'err', 'InstructionError') + if err_from_reciept is not None: + return err_from_reciept + + err_from_reciept_result = get_from_dict(receipt, 'meta', 'err', 'InstructionError') + if err_from_reciept_result is not None: + return err_from_reciept_result + + err_from_send_trx_error = get_from_dict(receipt, 'data', 'err', 'InstructionError') + if err_from_send_trx_error is not None: + return err_from_send_trx_error + + err_from_prepared_receipt = get_from_dict(receipt, 'err', 'InstructionError') + if err_from_prepared_receipt is not None: + return err_from_prepared_receipt + + return None + + - if err_result['data']['logs'][-1].find(err_instruction) >= 0 or \ - err_result['data']['logs'][-2].find(err_instruction) >= 0 or \ - err_result['data']['logs'][-1].find(err_budget) >= 0: +def check_for_errors(receipt): + if get_error_definition_from_reciept(receipt) is not None: return True return False -def check_if_storage_is_empty_error(err_result): - error_arr = get_from_dict(err_result, "data", "err", "InstructionError") +def check_if_program_exceeded_instructions(receipt): + error_arr = get_error_definition_from_reciept(receipt) + if error_arr is not None and isinstance(error_arr, list): + error_type = error_arr[1] + if isinstance(error_type, str): + if error_type == 'ProgramFailedToComplete': + return True + if error_type == 'ComputationalBudgetExceeded': + return True + return False + + +def check_if_storage_is_empty_error(receipt): + error_arr = get_error_definition_from_reciept(receipt) 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: diff --git a/proxy/common_neon/transaction_sender.py b/proxy/common_neon/transaction_sender.py index 820bfb6b3..3150ed885 100644 --- a/proxy/common_neon/transaction_sender.py +++ b/proxy/common_neon/transaction_sender.py @@ -19,7 +19,7 @@ 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, \ +from .solana_interactor import SolanaInteractor, check_if_continue_returned, check_for_errors,\ 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 @@ -321,6 +321,12 @@ def call_signed_noniterative(self): call_txs_05.add(self.create_acc_trx) call_txs_05.add(self.instruction.make_noniterative_call_transaction(len(call_txs_05.instructions))) result = self.sender.send_measured_transaction(call_txs_05, self.eth_trx, 'CallFromRawEthereumTX') + + if check_for_errors(result): + if check_if_program_exceeded_instructions(result): + raise Exception("Program failed to complete") + raise Exception(json.dumps(result['result']['meta'])) + return result['result']['transaction']['signatures'][0] @@ -359,7 +365,9 @@ def create_accounts_for_trx(self): 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') + result = self.sender.send_measured_transaction(precall_txs, self.eth_trx, 'CreateAccountsForTrx') + if check_for_errors(result): + raise Exception("Failed to create account for trx") def write_trx_to_holder_account(self): @@ -493,7 +501,7 @@ 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) + self.sender.get_measurements(result) signature = check_if_continue_returned(result) if signature: return signature