Skip to content

Commit c093ed4

Browse files
impl emulate deploy trx (#219)
* impl emulate deploy trx * add debug info * add debug info * fix call_signed * remove debug info * remove deploy_contract() * remove unused code
1 parent cc6a40a commit c093ed4

File tree

2 files changed

+64
-117
lines changed

2 files changed

+64
-117
lines changed

proxy/plugin/solana_rest_api.py

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
import threading
2828
from .solana_rest_api_tools import EthereumAddress, create_account_with_seed, evm_loader_id, getTokens, \
2929
getAccountInfo, solana_cli, call_signed, solana_url, call_emulated, \
30-
Trx, deploy_contract, EthereumError, create_collateral_pool_address, getTokenAddr, STORAGE_SIZE, neon_config_load
30+
Trx, EthereumError, create_collateral_pool_address, getTokenAddr, STORAGE_SIZE, neon_config_load
3131
from solana.rpc.commitment import Commitment, Confirmed
3232
from web3 import Web3
3333
import logging
@@ -395,10 +395,7 @@ def eth_sendRawTransaction(self, rawTrx):
395395
logger.debug('Eth Hash: %s', eth_signature)
396396

397397
try:
398-
if (not trx.toAddress):
399-
(signature, _contract_eth) = deploy_contract(self.signer, self.client, trx, self.perm_accs, steps=1000)
400-
else:
401-
signature = call_signed(self.signer, self.client, trx, self.perm_accs, steps=250)
398+
signature = call_signed(self.signer, self.client, trx, self.perm_accs, steps=250)
402399

403400
logger.debug('Transaction signature: %s %s', signature, eth_signature)
404401

proxy/plugin/solana_rest_api_tools.py

Lines changed: 62 additions & 112 deletions
Original file line numberDiff line numberDiff line change
@@ -819,41 +819,33 @@ def create_account_list_by_emulate(signer, client, ethTrx):
819819
add_keys_05 = []
820820
trx = Transaction()
821821

822-
output_json = call_emulated(ethTrx.toAddress.hex(), sender_ether.hex(), ethTrx.callData.hex(), hex(ethTrx.value))
822+
if not ethTrx.toAddress:
823+
to_address_arg = "deploy"
824+
to_address = keccak_256(rlp.encode((bytes.fromhex(ethTrx.sender()), ethTrx.nonce))).digest()[-20:]
825+
else:
826+
to_address_arg = ethTrx.toAddress.hex()
827+
to_address = ethTrx.toAddress
828+
829+
output_json = call_emulated(to_address_arg, sender_ether.hex(), ethTrx.callData.hex(), hex(ethTrx.value))
823830
logger.debug("emulator returns: %s", json.dumps(output_json, indent=3))
824831
for acc_desc in output_json["accounts"]:
825832
address = bytes.fromhex(acc_desc["address"][2:])
826-
if address == ethTrx.toAddress:
827-
contract_sol = PublicKey(acc_desc["account"])
828-
if acc_desc["contract"] != None :
829-
code_sol = PublicKey(acc_desc["contract"])
830-
code_writable = acc_desc["writable"]
831-
else:
832-
code_sol = None
833-
code_writable = None
834-
835-
elif address == sender_ether:
836-
sender_sol = PublicKey(acc_desc["account"])
837-
else:
838-
add_keys_05.append(AccountMeta(pubkey=acc_desc["account"], is_signer=False, is_writable=(True if acc_desc["contract"] else acc_desc["writable"])))
839-
token_account = get_associated_token_address(PublicKey(acc_desc["account"]), ETH_TOKEN_MINT_ID)
840-
add_keys_05.append(AccountMeta(pubkey=token_account, is_signer=False, is_writable=True))
841-
if acc_desc["contract"]:
842-
add_keys_05.append(AccountMeta(pubkey=acc_desc["contract"], is_signer=False, is_writable=acc_desc["writable"]))
843833

834+
code_account = None
835+
code_account_writable = False
844836
if acc_desc["new"]:
845837
logger.debug("Create solana accounts for %s: %s %s", acc_desc["address"], acc_desc["account"], acc_desc["contract"])
846-
code_account = None
847838
if acc_desc["code_size"]:
848-
seed = b58encode(address)
839+
seed = b58encode(ACCOUNT_SEED_VERSION+address)
849840
code_account = accountWithSeed(signer.public_key(), seed, PublicKey(evm_loader_id))
850841
logger.debug(" with code account %s", code_account)
851842
code_size = acc_desc["code_size"]
852843
valids_size = (code_size // 8) + 1
853844
code_account_size = CODE_INFO_LAYOUT.sizeof() + code_size + valids_size + 2048
854845
code_account_balance = client.get_minimum_balance_for_rent_exemption(code_account_size)["result"]
855846
trx.add(createAccountWithSeedTrx(signer.public_key(), signer.public_key(), seed, code_account_balance, code_account_size, PublicKey(evm_loader_id)))
856-
add_keys_05.append(AccountMeta(pubkey=code_account, is_signer=False, is_writable=acc_desc["writable"]))
847+
# add_keys_05.append(AccountMeta(pubkey=code_account, is_signer=False, is_writable=acc_desc["writable"]))
848+
code_account_writable = acc_desc["writable"]
857849

858850
(create_trx, solana_address, token_address) = createEtherAccountTrx(client, address, evm_loader_id, signer, code_account)
859851
trx.add(create_trx)
@@ -873,6 +865,34 @@ def create_account_list_by_emulate(signer, client, ethTrx):
873865
acc_desc["address"],
874866
str(NEW_USER_AIRDROP_AMOUNT))
875867

868+
869+
if address == to_address:
870+
contract_sol = PublicKey(acc_desc["account"])
871+
if acc_desc["new"]:
872+
code_sol = code_account
873+
code_writable = code_account_writable
874+
else:
875+
if acc_desc["contract"] != None:
876+
code_sol = PublicKey(acc_desc["contract"])
877+
code_writable = acc_desc["writable"]
878+
else:
879+
code_sol = None
880+
code_writable = None
881+
882+
elif address == sender_ether:
883+
sender_sol = PublicKey(acc_desc["account"])
884+
else:
885+
add_keys_05.append(AccountMeta(pubkey=acc_desc["account"], is_signer=False, is_writable=(True if acc_desc["contract"] else acc_desc["writable"])))
886+
token_account = get_associated_token_address(PublicKey(acc_desc["account"]), ETH_TOKEN_MINT_ID)
887+
add_keys_05.append(AccountMeta(pubkey=token_account, is_signer=False, is_writable=True))
888+
if acc_desc["new"]:
889+
if code_account:
890+
add_keys_05.append(AccountMeta(pubkey=code_account, is_signer=False, is_writable=code_account_writable))
891+
else:
892+
if acc_desc["contract"]:
893+
add_keys_05.append(AccountMeta(pubkey=acc_desc["contract"], is_signer=False, is_writable=acc_desc["writable"]))
894+
895+
876896
for token_account in output_json["token_accounts"]:
877897
add_keys_05.append(AccountMeta(pubkey=PublicKey(token_account["key"]), is_signer=False, is_writable=True))
878898

@@ -898,24 +918,29 @@ def create_account_list_by_emulate(signer, client, ethTrx):
898918

899919

900920
def call_signed(signer, client, ethTrx, perm_accs, steps):
921+
901922
(trx_accs, sender_ether, create_acc_trx) = create_account_list_by_emulate(signer, client, ethTrx)
902-
msg = sender_ether + ethTrx.signature() + ethTrx.unsigned_msg()
903923

904-
call_from_holder = False
905-
call_iterative = False
906-
try:
907-
logger.debug("Try single trx call")
908-
return call_signed_noniterative(signer, client, ethTrx, perm_accs, trx_accs, msg, create_acc_trx)
909-
except Exception as err:
910-
logger.debug(str(err))
911-
if str(err).find("Program failed to complete") >= 0:
912-
logger.debug("Program exceeded instructions")
913-
call_iterative = True
914-
elif str(err).startswith("transaction too large:"):
915-
logger.debug("Transaction too large, call call_signed_with_holder_acc():")
916-
call_from_holder = True
917-
else:
918-
raise
924+
if not ethTrx.toAddress:
925+
call_from_holder = True
926+
else:
927+
call_from_holder = False
928+
call_iterative = False
929+
msg = sender_ether + ethTrx.signature() + ethTrx.unsigned_msg()
930+
931+
try:
932+
logger.debug("Try single trx call")
933+
return call_signed_noniterative(signer, client, ethTrx, perm_accs, trx_accs, msg, create_acc_trx)
934+
except Exception as err:
935+
logger.debug(str(err))
936+
if str(err).find("Program failed to complete") >= 0:
937+
logger.debug("Program exceeded instructions")
938+
call_iterative = True
939+
elif str(err).startswith("transaction too large:"):
940+
logger.debug("Transaction too large, call call_signed_with_holder_acc():")
941+
call_from_holder = True
942+
else:
943+
raise
919944

920945
if call_from_holder:
921946
return call_signed_with_holder_acc(signer, client, ethTrx, perm_accs, trx_accs, steps, create_acc_trx)
@@ -1085,81 +1110,6 @@ def write_trx_to_holder_account(signer, client, holder, ethTrx):
10851110
logger.debug("confirmed: %s", rcpt)
10861111

10871112

1088-
def deploy_contract(signer, client, ethTrx, perm_accs, steps):
1089-
sender_ether = bytes.fromhex(ethTrx.sender())
1090-
(sender_sol, _) = ether2program(sender_ether.hex(), evm_loader_id, signer.public_key())
1091-
logger.debug("Sender account solana: %s %s", sender_ether.hex(), sender_sol)
1092-
1093-
caller_token = get_associated_token_address(PublicKey(sender_sol), ETH_TOKEN_MINT_ID)
1094-
1095-
#info = _getAccountData(client, sender_sol, ACCOUNT_INFO_LAYOUT.sizeof())
1096-
#trx_count = int.from_bytes(AccountInfo.frombytes(info).trx_count, 'little')
1097-
#logger.debug("Sender solana trx_count: %s", trx_count)
1098-
1099-
# Create legacy contract address from (sender_eth, nonce)
1100-
#rlp = pack(sender_ether, ethTrx.nonce or None)
1101-
contract_eth = keccak_256(rlp.encode((sender_ether, ethTrx.nonce))).digest()[-20:]
1102-
(contract_sol, contract_nonce) = ether2program(contract_eth.hex(), evm_loader_id, signer.public_key())
1103-
1104-
# We need append ACCOUNT_SEED_VERSION to created CODE account (to avoid using previously created accounts to store the code)
1105-
# when calculate contract_sol variable ACCOUNT_SEED_VERSION already added in `neon-cli create-program-address`.
1106-
(code_sol, code_nonce, code_seed) = ether2seed(ACCOUNT_SEED_VERSION+contract_eth, evm_loader_id, signer.public_key())
1107-
1108-
logger.debug("Legacy contract address ether: %s", contract_eth.hex())
1109-
logger.debug("Legacy contract address solana: %s %s", contract_sol, contract_nonce)
1110-
logger.debug("Legacy code address solana: %s %s", code_sol, code_nonce)
1111-
1112-
write_trx_to_holder_account(signer, client, perm_accs.holder, ethTrx)
1113-
1114-
# Create contract account & execute deploy transaction
1115-
logger.debug(" # Create contract account & execute deploy transaction")
1116-
trx = Transaction()
1117-
sender_sol_info = client.get_account_info(sender_sol, commitment=Confirmed)
1118-
if sender_sol_info['result']['value'] is None:
1119-
trx.add(createEtherAccountTrx(client, sender_ether, evm_loader_id, signer)[0])
1120-
if NEW_USER_AIRDROP_AMOUNT > 0:
1121-
trx.add(transfer2(Transfer2Params(
1122-
source=getTokenAddr(signer.public_key()),
1123-
owner=signer.public_key(),
1124-
dest=caller_token,
1125-
amount=NEW_USER_AIRDROP_AMOUNT*1_000_000_000,
1126-
decimals=9,
1127-
mint=ETH_TOKEN_MINT_ID,
1128-
program_id=TOKEN_PROGRAM_ID,
1129-
)))
1130-
logger.debug("Token transfer to %s as ethereum 0x%s amount %s", caller_token, ethTrx.sender(), str(NEW_USER_AIRDROP_AMOUNT))
1131-
1132-
if client.get_balance(code_sol, commitment=Confirmed)['result']['value'] == 0:
1133-
msg_size = len(ethTrx.signature() + len(ethTrx.unsigned_msg()).to_bytes(8, byteorder="little") + ethTrx.unsigned_msg())
1134-
valids_size = (msg_size // 8) + 1
1135-
code_account_size = CODE_INFO_LAYOUT.sizeof() + msg_size + valids_size + 2048
1136-
code_account_balance = client.get_minimum_balance_for_rent_exemption(code_account_size)["result"]
1137-
trx.add(createAccountWithSeedTrx(signer.public_key(), signer.public_key(), code_seed, code_account_balance, code_account_size, PublicKey(evm_loader_id)))
1138-
if client.get_balance(contract_sol, commitment=Confirmed)['result']['value'] == 0:
1139-
trx.add(createEtherAccountTrx(client, contract_eth, evm_loader_id, signer, code_sol)[0])
1140-
if len(trx.instructions):
1141-
result = send_measured_transaction(client, trx, signer)
1142-
1143-
eth_accounts = [
1144-
AccountMeta(pubkey=contract_sol, is_signer=False, is_writable=True),
1145-
AccountMeta(pubkey=get_associated_token_address(PublicKey(contract_sol), ETH_TOKEN_MINT_ID), is_signer=False, is_writable=True),
1146-
AccountMeta(pubkey=code_sol, is_signer=False, is_writable=True),
1147-
AccountMeta(pubkey=sender_sol, is_signer=False, is_writable=True),
1148-
AccountMeta(pubkey=caller_token, is_signer=False, is_writable=True),
1149-
]
1150-
1151-
trx_accs = TransactionAccounts(caller_token, eth_accounts)
1152-
1153-
precall_txs = Transaction()
1154-
precall_txs.add(make_call_from_account_instruction(perm_accs, trx_accs))
1155-
1156-
# ExecuteTrxFromAccountDataIterative
1157-
logger.debug("ExecuteTrxFromAccountDataIterative:")
1158-
send_measured_transaction(client, precall_txs, signer)
1159-
1160-
return (call_continue(signer, client, perm_accs, trx_accs, steps), '0x'+contract_eth.hex())
1161-
1162-
11631113
def _getAccountData(client, account, expected_length, owner=None):
11641114
info = client.get_account_info(account, commitment=Confirmed)['result']['value']
11651115
if info is None:

0 commit comments

Comments
 (0)