Skip to content

Commit 06b85c2

Browse files
s-medvedevSemen Medvedev
andauthored
Rollback to simplified iterative transaction sending #287 (#288)
* Rollback to simplified iterative transaction sending #287 * Fix merge error * Fix merge error Co-authored-by: Semen Medvedev <[email protected]>
1 parent 838b8f8 commit 06b85c2

File tree

1 file changed

+20
-265
lines changed

1 file changed

+20
-265
lines changed

proxy/plugin/solana_rest_api_tools.py

Lines changed: 20 additions & 265 deletions
Original file line numberDiff line numberDiff line change
@@ -472,30 +472,7 @@ def check_if_continue_returned(result):
472472
return (False, ())
473473

474474

475-
def call_continue_0x0d(signer, client, perm_accs, trx_accs, steps, msg, eth_trx):
476-
try:
477-
return call_continue_bucked_0x0d(signer, client, perm_accs, trx_accs, steps, msg, eth_trx)
478-
except Exception as err:
479-
logger.debug("call_continue_bucked_0x0D exception:")
480-
logger.debug(str(err))
481-
482-
try:
483-
# return call_continue_iterative_0x0d(signer, client, perm_accs, trx_accs, steps, msg)
484-
return call_continue_iterative(signer, client, perm_accs, trx_accs, steps, eth_trx)
485-
except Exception as err:
486-
logger.debug("call_continue_iterative exception:")
487-
logger.debug(str(err))
488-
489-
return sol_instr_21_cancel(signer, client, perm_accs, trx_accs, eth_trx)
490-
491-
492475
def call_continue(signer, client, perm_accs, trx_accs, steps, eth_trx):
493-
try:
494-
return call_continue_bucked(signer, client, perm_accs, trx_accs, steps, eth_trx)
495-
except Exception as err:
496-
logger.debug("call_continue_bucked exception:")
497-
logger.debug(str(err))
498-
499476
try:
500477
return call_continue_iterative(signer, client, perm_accs, trx_accs, steps, eth_trx)
501478
except Exception as err:
@@ -504,92 +481,6 @@ def call_continue(signer, client, perm_accs, trx_accs, steps, eth_trx):
504481

505482
return sol_instr_21_cancel(signer, client, perm_accs, trx_accs, eth_trx)
506483

507-
508-
def call_continue_bucked(signer, client, perm_accs, trx_accs, steps, eth_trx):
509-
while True:
510-
logger.debug("Continue bucked step:")
511-
(continue_count, instruction_count) = simulate_continue(signer, client, perm_accs, trx_accs, steps)
512-
logger.debug("Send bucked:")
513-
result_list = []
514-
try:
515-
for index in range(continue_count):
516-
trx = Transaction().add(make_continue_instruction(perm_accs, trx_accs, instruction_count, index))
517-
result = client.send_transaction(
518-
trx,
519-
signer,
520-
opts=TxOpts(skip_confirmation=True, preflight_commitment=Confirmed)
521-
)["result"]
522-
result_list.append(result)
523-
except Exception as err:
524-
if str(err).startswith("Transaction simulation failed: Error processing Instruction 0: custom program error: 0x1"):
525-
pass
526-
else:
527-
raise
528-
529-
logger.debug("Collect bucked results: {}".format(result_list))
530-
signature = None
531-
for trx in result_list:
532-
confirm_transaction(client, trx)
533-
result = client.get_confirmed_transaction(trx)
534-
535-
extra_sol_trx = False
536-
if result['result']['meta']['err']:
537-
instruction_error = result['result']['meta']['err']['InstructionError']
538-
err = instruction_error[1]
539-
if isinstance(err, dict) and err.get('Custom', 0) == 1:
540-
extra_sol_trx = True
541-
update_transaction_cost(result, eth_trx, extra_sol_trx=extra_sol_trx, reason='ContinueV02')
542-
get_measurements(result)
543-
(founded, signature_) = check_if_continue_returned(result)
544-
if founded:
545-
signature = signature_
546-
if signature:
547-
return signature
548-
549-
def call_continue_bucked_0x0d(signer, client, perm_accs, trx_accs, steps, msg, eth_trx):
550-
while True:
551-
logger.debug("Continue bucked step:")
552-
(continue_count, instruction_count) = simulate_continue_0x0d(signer, client, perm_accs, trx_accs, steps, msg)
553-
logger.debug("Send bucked:")
554-
result_list = []
555-
try:
556-
for index in range(continue_count*CONTINUE_COUNT_FACTOR):
557-
trx = Transaction().add(make_partial_call_or_continue_instruction_0x0d(perm_accs, trx_accs, instruction_count, msg, index))
558-
result = client.send_transaction(
559-
trx,
560-
signer,
561-
opts=TxOpts(skip_confirmation=True, preflight_commitment=Confirmed)
562-
)["result"]
563-
result_list.append(result)
564-
except Exception as err:
565-
if str(err).startswith("Transaction simulation failed: Error processing Instruction 0: custom program error: 0x1"):
566-
pass
567-
else:
568-
raise
569-
570-
logger.debug("Collect bucked results:")
571-
signature=None
572-
573-
574-
for trx in result_list:
575-
confirm_transaction(client, trx)
576-
result = client.get_confirmed_transaction(trx)
577-
578-
extra_sol_trx = False
579-
if result['result']['meta']['err']:
580-
instruction_error = result['result']['meta']['err']['InstructionError']
581-
err = instruction_error[1]
582-
if isinstance(err, dict) and err.get('Custom', 0) == 1:
583-
extra_sol_trx = True
584-
585-
update_transaction_cost(result, eth_trx, extra_sol_trx=extra_sol_trx, reason='PartialCallOrContinueFromRawEthereumTX')
586-
get_measurements(result)
587-
(founded, signature_) = check_if_continue_returned(result)
588-
if founded:
589-
signature = signature_
590-
if signature:
591-
return signature
592-
593484
def call_continue_iterative(signer, client, perm_accs, trx_accs, step_count, eth_trx):
594485
while True:
595486
logger.debug("Continue iterative step:")
@@ -599,15 +490,6 @@ def call_continue_iterative(signer, client, perm_accs, trx_accs, step_count, eth
599490
return signature
600491

601492

602-
# def call_continue_iterative_0x0d(signer, client, perm_accs, trx_accs, step_count, msg):
603-
# while True:
604-
# logger.debug("Continue iterative step:")
605-
# result = make_partial_call_or_continue_instruction_0x0d(signer, client, perm_accs, trx_accs, step_count, msg)
606-
# (succeed, signature) = check_if_continue_returned(result)
607-
# if succeed:
608-
# return signature
609-
610-
611493
def sol_instr_10_continue(signer, client, perm_accs, trx_accs, initial_step_count, eth_trx):
612494
step_count = initial_step_count
613495
while step_count > 0:
@@ -671,30 +553,6 @@ def make_partial_call_instruction(perm_accs, trx_accs, step_count, call_data):
671553
)
672554

673555

674-
def make_partial_call_or_continue_instruction_0x0d(perm_accs, trx_accs, step_count, call_data, index=None):
675-
data = bytearray.fromhex("0D") + perm_accs.collateral_pool_index_buf + step_count.to_bytes(8, byteorder="little") + call_data
676-
if index:
677-
data = data + index.to_bytes(8, byteorder="little")
678-
return TransactionInstruction(
679-
program_id = evm_loader_id,
680-
data = data,
681-
keys = [
682-
AccountMeta(pubkey=perm_accs.storage, is_signer=False, is_writable=True),
683-
684-
AccountMeta(pubkey=sysinstruct, is_signer=False, is_writable=False),
685-
AccountMeta(pubkey=perm_accs.operator, is_signer=True, is_writable=True),
686-
AccountMeta(pubkey=perm_accs.collateral_pool_address, is_signer=False, is_writable=True),
687-
AccountMeta(pubkey=perm_accs.operator_token, is_signer=False, is_writable=True),
688-
AccountMeta(pubkey=trx_accs.caller_token, is_signer=False, is_writable=True),
689-
AccountMeta(pubkey=system, is_signer=False, is_writable=False),
690-
691-
] + trx_accs.eth_accounts + [
692-
693-
AccountMeta(pubkey=sysinstruct, is_signer=False, is_writable=False),
694-
] + obligatory_accounts
695-
)
696-
697-
698556
def make_continue_instruction(perm_accs, trx_accs, step_count, index=None):
699557
data = bytearray.fromhex("14") + perm_accs.collateral_pool_index_buf + step_count.to_bytes(8, byteorder="little")
700558
if index:
@@ -756,102 +614,6 @@ def make_05_call_instruction(perm_accs, trx_accs, call_data):
756614
)
757615

758616

759-
def simulate_continue_0x0d(signer, client, perm_accs, trx_accs, step_count, msg):
760-
logger.debug("simulate_continue:")
761-
continue_count = 9
762-
while True:
763-
logger.debug(continue_count)
764-
blockhash = Blockhash(client.get_recent_blockhash(Confirmed)["result"]["value"]["blockhash"])
765-
trx = Transaction(recent_blockhash = blockhash)
766-
for _ in range(continue_count):
767-
trx.add(make_partial_call_or_continue_instruction_0x0d(perm_accs, trx_accs, step_count, msg))
768-
trx.sign(signer)
769-
770-
try:
771-
trx.serialize()
772-
except Exception as err:
773-
logger.debug("trx.serialize() exception")
774-
if str(err).startswith("transaction too large:"):
775-
if continue_count == 0:
776-
raise Exception("transaction too large")
777-
continue_count = continue_count // 2
778-
continue
779-
raise
780-
781-
response = client.simulate_transaction(trx, commitment=Confirmed)
782-
783-
if response["result"]["value"]["err"]:
784-
instruction_error = response["result"]["value"]["err"]["InstructionError"]
785-
err = instruction_error[1]
786-
if isinstance(err, str) and (err == "ProgramFailedToComplete" or err == "ComputationalBudgetExceeded"):
787-
step_count = step_count // 2
788-
if step_count == 0:
789-
raise Exception("cant run even one instruction")
790-
elif isinstance(err, dict) and "Custom" in err:
791-
if continue_count == 0:
792-
raise Exception("uninitialized storage account")
793-
continue_count = instruction_error[0]
794-
break
795-
else:
796-
logger.debug("Result:\n%s"%json.dumps(response, indent=3))
797-
raise Exception("unspecified error")
798-
else:
799-
# In case of long Ethereum transaction we speculative send more iterations then need
800-
continue_count = continue_count*CONTINUE_COUNT_FACTOR
801-
break
802-
803-
logger.debug("tx_count = {}, step_count = {}".format(continue_count, step_count))
804-
return (continue_count, step_count)
805-
806-
807-
def simulate_continue(signer, client, perm_accs, trx_accs, step_count):
808-
logger.debug("simulate_continue:")
809-
continue_count = 9
810-
while True:
811-
logger.debug(continue_count)
812-
blockhash = Blockhash(client.get_recent_blockhash(Confirmed)["result"]["value"]["blockhash"])
813-
trx = Transaction(recent_blockhash = blockhash)
814-
for _ in range(continue_count):
815-
trx.add(make_continue_instruction(perm_accs, trx_accs, step_count))
816-
trx.sign(signer)
817-
818-
try:
819-
trx.serialize()
820-
except Exception as err:
821-
logger.debug("trx.serialize() exception")
822-
if str(err).startswith("transaction too large:"):
823-
if continue_count == 0:
824-
raise Exception("transaction too large")
825-
continue_count = continue_count // 2
826-
continue
827-
raise
828-
829-
response = client.simulate_transaction(trx, commitment=Confirmed)
830-
831-
if response["result"]["value"]["err"]:
832-
instruction_error = response["result"]["value"]["err"]["InstructionError"]
833-
err = instruction_error[1]
834-
if isinstance(err, str) and (err == "ProgramFailedToComplete" or err == "ComputationalBudgetExceeded"):
835-
step_count = step_count // 2
836-
if step_count == 0:
837-
raise Exception("cant run even one instruction")
838-
elif isinstance(err, dict) and "Custom" in err:
839-
if continue_count == 0:
840-
raise Exception("uninitialized storage account")
841-
continue_count = instruction_error[0]
842-
break
843-
else:
844-
logger.debug("Result:\n%s"%json.dumps(response, indent=3))
845-
raise Exception("unspecified error")
846-
else:
847-
# In case of long Ethereum transaction we speculative send more iterations then need
848-
continue_count = continue_count*CONTINUE_COUNT_FACTOR
849-
break
850-
851-
logger.debug("tx_count = {}, step_count = {}".format(continue_count, step_count))
852-
return (continue_count, step_count)
853-
854-
855617
def update_transaction_cost(receipt, eth_trx, extra_sol_trx=False, reason=None):
856618
cost = receipt['result']['meta']['preBalances'][0] - receipt['result']['meta']['postBalances'][0]
857619
if eth_trx:
@@ -894,7 +656,6 @@ def update_transaction_cost(receipt, eth_trx, extra_sol_trx=False, reason=None):
894656
)
895657

896658
def create_account_list_by_emulate(signer, client, eth_trx):
897-
898659
sender_ether = bytes.fromhex(eth_trx.sender())
899660
add_keys_05 = []
900661
trx = Transaction()
@@ -1056,19 +817,21 @@ def call_signed(signer, client, eth_trx, perm_accs, steps):
1056817

1057818
(trx_accs, sender_ether, create_acc_trx) = create_account_list_by_emulate(signer, client, eth_trx)
1058819

820+
call_iterative = False
821+
call_from_holder = False
822+
1059823
if not eth_trx.toAddress:
1060824
call_from_holder = True
1061825
else:
1062-
call_from_holder = False
1063-
call_iterative = False
1064826
msg = sender_ether + eth_trx.signature() + eth_trx.unsigned_msg()
1065827

1066828
try:
1067829
logger.debug("Try single trx call")
1068830
return call_signed_noniterative(signer, client, eth_trx, perm_accs, trx_accs, msg, create_acc_trx)
1069831
except Exception as err:
1070832
logger.debug(str(err))
1071-
if str(err).find("Program failed to complete") >= 0:
833+
errStr = str(err)
834+
if "Program failed to complete" in errStr or "Computational budget exceeded" in errStr:
1072835
logger.debug("Program exceeded instructions")
1073836
call_iterative = True
1074837
elif str(err).startswith("transaction too large:"):
@@ -1077,18 +840,27 @@ def call_signed(signer, client, eth_trx, perm_accs, steps):
1077840
else:
1078841
raise
1079842

1080-
if call_from_holder:
1081-
return call_signed_with_holder_acc(signer, client, eth_trx, perm_accs, trx_accs, steps, create_acc_trx)
1082843
if call_iterative:
1083-
if USE_COMBINED_START_CONTINUE:
1084-
return call_signed_iterative_0x0d(signer, client, eth_trx, perm_accs, trx_accs, steps, msg, create_acc_trx)
1085-
else:
844+
try:
1086845
return call_signed_iterative(signer, client, eth_trx, perm_accs, trx_accs, steps, msg, create_acc_trx)
846+
except Exception as err:
847+
logger.debug(str(err))
848+
if str(err).startswith("transaction too large:"):
849+
logger.debug("Transaction too large, call call_signed_with_holder_acc():")
850+
call_from_holder = True
851+
else:
852+
raise
1087853

854+
if call_from_holder:
855+
return call_signed_with_holder_acc(signer, client, eth_trx, perm_accs, trx_accs, steps, create_acc_trx)
1088856

1089857
def call_signed_iterative(signer, client, eth_trx, perm_accs, trx_accs, steps, msg, create_acc_trx):
858+
if len(create_acc_trx.instructions):
859+
precall_txs = Transaction()
860+
precall_txs.add(create_acc_trx)
861+
send_measured_transaction(client, precall_txs, signer, eth_trx, 'CreateAccountsForTrx')
862+
1090863
precall_txs = Transaction()
1091-
precall_txs.add(create_acc_trx)
1092864
precall_txs.add(TransactionInstruction(
1093865
program_id=keccakprog,
1094866
data=make_keccak_instruction_data(len(precall_txs.instructions)+1, len(eth_trx.unsigned_msg()), data_start=13),
@@ -1103,23 +875,6 @@ def call_signed_iterative(signer, client, eth_trx, perm_accs, trx_accs, steps, m
1103875
return call_continue(signer, client, perm_accs, trx_accs, steps, eth_trx)
1104876

1105877

1106-
def call_signed_iterative_0x0d(signer, client, eth_trx, perm_accs, trx_accs, steps, msg, create_acc_trx):
1107-
precall_txs = Transaction()
1108-
precall_txs.add(create_acc_trx)
1109-
precall_txs.add(TransactionInstruction(
1110-
program_id=keccakprog,
1111-
data=make_keccak_instruction_data(len(precall_txs.instructions)+1, len(eth_trx.unsigned_msg()), data_start=13),
1112-
keys=[
1113-
AccountMeta(pubkey=keccakprog, is_signer=False, is_writable=False),
1114-
]))
1115-
precall_txs.add(make_partial_call_or_continue_instruction_0x0d(perm_accs, trx_accs, steps, msg))
1116-
1117-
logger.debug("Partial call 0x0d")
1118-
send_measured_transaction(client, precall_txs, signer, eth_trx, 'PartialCallOrContinueFromRawEthereumTX')
1119-
1120-
return call_continue_0x0d(signer, client, perm_accs, trx_accs, steps, msg, eth_trx)
1121-
1122-
1123878
def call_signed_noniterative(signer, client, eth_trx, perm_accs, trx_accs, msg, create_acc_trx):
1124879
call_txs_05 = Transaction()
1125880
call_txs_05.add(create_acc_trx)

0 commit comments

Comments
 (0)