Skip to content

Commit 3faddaa

Browse files
author
rozhkovdmitrii
committed
Merge branch 'develop' into 191-create-and-airdrop-eth-account
# Conflicts: # proxy/plugin/solana_rest_api.py # proxy/plugin/solana_rest_api_tools.py
2 parents 0b0046e + cf6b250 commit 3faddaa

15 files changed

+737
-219
lines changed

Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ COPY --from=cli /opt/solana/bin/solana \
3232

3333
COPY --from=spl /opt/solana/bin/solana /cli/bin/
3434
COPY --from=spl /opt/evm_loader.so /opt/evm_loader-keypair.json \
35-
/opt/neon-cli /spl/bin/
35+
/opt/neon-cli /opt/faucet /spl/bin/
3636
COPY --from=spl /opt/spl-token /opt/test_token_keypair /opt/test_token_owner /spl/bin/
3737
COPY --from=spl /opt/collateral_pool_generator.py \
3838
/opt/solana_utils.py \

proxy/deploy-test.sh

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,10 @@ set -xeuo pipefail
33

44
echo "Deploy test..."
55

6+
solana config set -u $SOLANA_URL
67
solana address || solana-keygen new --no-passphrase
7-
export $(/spl/bin/neon-cli --evm_loader JxujFZpNBPADbfw2MnPPgnnFGruzp2ELSFWPQgrjz5D neon-elf-params /spl/bin/evm_loader.so | grep NEON_REVISION | xargs)
8+
solana program dump "$EVM_LOADER" ./evm_loader.dump
9+
export $(/spl/bin/neon-cli --evm_loader "$EVM_LOADER" neon-elf-params ./evm_loader.dump)
810

911
curl -v --header "Content-Type: application/json" --data '{"method":"eth_blockNumber","id":1,"jsonrpc":"2.0","params":[]}' $PROXY_URL
1012

proxy/docker-compose-test.yml

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ services:
55
container_name: solana
66
image: neonlabsorg/solana:${SOLANA_REVISION:-v1.7.9-resources}
77
environment:
8-
- SOLANA_URL=http://solana:8899
9-
- RUST_LOG=solana_runtime::system_instruction_processor=trace,solana_runtime::message_processor=debug,solana_bpf_loader=debug,solana_rbpf=debug
8+
SOLANA_URL: http://solana:8899
9+
RUST_LOG: solana_runtime::system_instruction_processor=trace,solana_runtime::message_processor=debug,solana_bpf_loader=debug,solana_rbpf=debug
1010
hostname: solana
1111
expose:
1212
- "8899"
@@ -17,11 +17,28 @@ services:
1717
networks:
1818
- net
1919

20+
postgres:
21+
container_name: postgres
22+
image: postgres:14.0
23+
command: postgres -c 'max_connections=1000'
24+
environment:
25+
POSTGRES_DB: neon-db
26+
POSTGRES_USER: neon-proxy
27+
POSTGRES_PASSWORD: neon-proxy-pass
28+
hostname: postgres
29+
expose:
30+
- "5432"
31+
networks:
32+
- net
33+
2034
proxy:
2135
container_name: proxy
2236
image: neonlabsorg/proxy:${REVISION}
2337
environment:
24-
- CONFIG=ci
38+
POSTGRES_DB: neon-db
39+
POSTGRES_USER: neon-proxy
40+
POSTGRES_PASSWORD: neon-proxy-pass
41+
CONFIG: ci
2542
hostname: proxy
2643
ports:
2744
- 127.0.0.1:9090:9090

proxy/environment.py

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
import os
2+
import subprocess
3+
import logging
4+
from solana.publickey import PublicKey
5+
6+
logger = logging.getLogger(__name__)
7+
logger.setLevel(logging.DEBUG)
8+
9+
solana_url = os.environ.get("SOLANA_URL", "http://localhost:8899")
10+
evm_loader_id = os.environ.get("EVM_LOADER")
11+
neon_cli_timeout = float(os.environ.get("NEON_CLI_TIMEOUT", "0.1"))
12+
13+
class solana_cli:
14+
def call(self, *args):
15+
try:
16+
cmd = ["solana",
17+
"--url", solana_url,
18+
] + list(args)
19+
print(cmd)
20+
return subprocess.check_output(cmd, universal_newlines=True)
21+
except subprocess.CalledProcessError as err:
22+
import sys
23+
logger.debug("ERR: solana error {}".format(err))
24+
raise
25+
26+
27+
class neon_cli:
28+
def call(self, *args):
29+
try:
30+
cmd = ["neon-cli",
31+
"--commitment=recent",
32+
"--url", solana_url,
33+
"--evm_loader={}".format(evm_loader_id),
34+
] + list(args)
35+
print(cmd)
36+
return subprocess.check_output(cmd, timeout=neon_cli_timeout, universal_newlines=True)
37+
except subprocess.CalledProcessError as err:
38+
import sys
39+
logger.debug("ERR: neon-cli error {}".format(err))
40+
raise
41+
42+
def read_elf_params(out_dict):
43+
logger.debug('load for solana_url={} and evm_loader_id={}'.format(solana_url, evm_loader_id))
44+
res = solana_cli().call('program', 'dump', evm_loader_id, './evm_loader.dump')
45+
substr = "Wrote program to "
46+
path = ""
47+
for line in res.splitlines():
48+
if line.startswith(substr):
49+
path = line[len(substr):].strip()
50+
if path == "":
51+
raise Exception("cannot program dump for ", evm_loader_id)
52+
for param in neon_cli().call("neon-elf-params", path).splitlines():
53+
if param.startswith('NEON_') and '=' in param:
54+
v = param.split('=')
55+
out_dict[v[0]] = v[1]
56+
57+
ELF_PARAMS = {}
58+
read_elf_params(ELF_PARAMS)
59+
COLLATERAL_POOL_BASE = ELF_PARAMS.get("NEON_POOL_BASE")
60+
ETH_TOKEN_MINT_ID: PublicKey = PublicKey(ELF_PARAMS.get("NEON_TOKEN_MINT"))

proxy/indexer/solana_receipts_update.py

Lines changed: 54 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -6,20 +6,20 @@
66
import logging
77
from solana.rpc.api import Client
88
from multiprocessing.dummy import Pool as ThreadPool
9-
from sqlitedict import SqliteDict
109
from typing import Dict, Union
10+
from proxy.environment import solana_url, evm_loader_id
1111

1212

1313
try:
1414
from utils import check_error, get_trx_results, get_trx_receipts, LogDB, Canceller
15+
from sql_dict import SQLDict
1516
except ImportError:
1617
from .utils import check_error, get_trx_results, get_trx_receipts, LogDB, Canceller
18+
from .sql_dict import SQLDict
1719

1820

19-
solana_url = os.environ.get("SOLANA_URL", "https://api.devnet.solana.com")
20-
evm_loader_id = os.environ.get("EVM_LOADER", "eeLSJgWzzxrqKv1UxtRVVH8FX3qCQWUs9QuAjJpETGU")
2121
PARALLEL_REQUESTS = int(os.environ.get("PARALLEL_REQUESTS", "2"))
22-
22+
CANCEL_TIMEOUT = int(os.environ.get("CANCEL_TIMEOUT", "60"))
2323

2424
logger = logging.getLogger(__name__)
2525
logger.setLevel(logging.DEBUG)
@@ -45,7 +45,7 @@ def __init__(self, signature, results, accounts = None):
4545

4646

4747
class TransactionStruct:
48-
def __init__(self, eth_trx, eth_signature, from_address, got_result, signatures, storage, blocked_accounts):
48+
def __init__(self, eth_trx, eth_signature, from_address, got_result, signatures, storage, blocked_accounts, slot):
4949
# logger.debug(eth_signature)
5050
self.eth_trx = eth_trx
5151
self.eth_signature = eth_signature
@@ -54,19 +54,20 @@ def __init__(self, eth_trx, eth_signature, from_address, got_result, signatures,
5454
self.signatures = signatures
5555
self.storage = storage
5656
self.blocked_accounts = blocked_accounts
57+
self.slot = slot
5758

5859

5960
class Indexer:
6061
def __init__(self):
6162
self.client = Client(solana_url)
6263
self.canceller = Canceller()
63-
self.logs_db = LogDB(filename="local.db")
64-
self.blocks_by_hash = SqliteDict(filename="local.db", tablename="solana_blocks_by_hash", autocommit=True)
65-
self.transaction_receipts = SqliteDict(filename="local.db", tablename="known_transactions", autocommit=True, encode=json.dumps, decode=json.loads)
66-
self.ethereum_trx = SqliteDict(filename="local.db", tablename="ethereum_transactions", autocommit=True, encode=json.dumps, decode=json.loads)
67-
self.eth_sol_trx = SqliteDict(filename="local.db", tablename="ethereum_solana_transactions", autocommit=True, encode=json.dumps, decode=json.loads)
68-
self.sol_eth_trx = SqliteDict(filename="local.db", tablename="solana_ethereum_transactions", autocommit=True, encode=json.dumps, decode=json.loads)
69-
self.constants = SqliteDict(filename="local.db", tablename="constants", autocommit=True)
64+
self.logs_db = LogDB()
65+
self.blocks_by_hash = SQLDict(tablename="solana_blocks_by_hash")
66+
self.transaction_receipts = SQLDict(tablename="known_transactions")
67+
self.ethereum_trx = SQLDict(tablename="ethereum_transactions")
68+
self.eth_sol_trx = SQLDict(tablename="ethereum_solana_transactions")
69+
self.sol_eth_trx = SQLDict(tablename="solana_ethereum_transactions")
70+
self.constants = SQLDict(tablename="constants")
7071
self.last_slot = 0
7172
self.current_slot = 0
7273
self.transaction_order = []
@@ -271,6 +272,7 @@ def process_receipts(self):
271272
continue_result.signatures,
272273
storage_account,
273274
continue_result.accounts,
275+
slot
274276
)
275277

276278
del continue_table[storage_account]
@@ -327,7 +329,16 @@ def process_receipts(self):
327329
got_result = get_trx_results(trx)
328330
if got_result is not None:
329331
# self.submit_transaction(eth_trx, eth_signature, from_address, got_result, [signature])
330-
trx_table[eth_signature] = TransactionStruct(eth_trx, eth_signature, from_address, got_result, [signature], None, None)
332+
trx_table[eth_signature] = TransactionStruct(
333+
eth_trx,
334+
eth_signature,
335+
from_address,
336+
got_result,
337+
[signature],
338+
None,
339+
None,
340+
slot
341+
)
331342
else:
332343
logger.error("RESULT NOT FOUND IN 05\n{}".format(json.dumps(trx, indent=4, sort_keys=True)))
333344

@@ -357,7 +368,8 @@ def process_receipts(self):
357368
None,
358369
[signature],
359370
storage_account,
360-
blocked_accounts
371+
blocked_accounts,
372+
slot
361373
)
362374

363375
if storage_account in continue_table:
@@ -369,11 +381,15 @@ def process_receipts(self):
369381
trx_table[eth_signature].signatures = continue_result.signatures
370382
del continue_table[storage_account]
371383

372-
elif instruction_data[0] == 0x0a: # Continue
373-
# logger.debug("{:>10} {:>6} Continue 0x{}".format(slot, counter, instruction_data.hex()))
384+
elif instruction_data[0] == 0x0a or instruction_data[0] == 0x14: # Continue or ContinueV02
374385

375386
storage_account = trx['transaction']['message']['accountKeys'][instruction['accounts'][0]]
376-
blocked_accounts = [trx['transaction']['message']['accountKeys'][acc_idx] for acc_idx in instruction['accounts'][5:]]
387+
if instruction_data[0] == 0x0a:
388+
# logger.debug("{:>10} {:>6} Continue 0x{}".format(slot, counter, instruction_data.hex()))
389+
blocked_accounts = [trx['transaction']['message']['accountKeys'][acc_idx] for acc_idx in instruction['accounts'][5:]]
390+
if instruction_data[0] == 0x14:
391+
# logger.debug("{:>10} {:>6} ContinueV02 0x{}".format(slot, counter, instruction_data.hex()))
392+
blocked_accounts = [trx['transaction']['message']['accountKeys'][acc_idx] for acc_idx in instruction['accounts'][5:]]
377393
got_result = get_trx_results(trx)
378394

379395
if storage_account in continue_table:
@@ -406,13 +422,14 @@ def process_receipts(self):
406422
continue_table[storage_account].signatures.append(signature)
407423

408424
if holder_account in holder_table:
409-
holder_table[holder_account] = HolderStruct(storage_account)
425+
if holder_table[holder_account].storage_account != storage_account:
426+
logger.error("Strange behavior. Pay attention. STORAGE_ACCOUNT != STORAGE_ACCOUNT")
427+
holder_table[holder_account] = HolderStruct(storage_account)
410428
else:
411429
holder_table[holder_account] = HolderStruct(storage_account)
412430
else:
413431
continue_table[storage_account] = ContinueStruct(signature, None, blocked_accounts)
414432
holder_table[holder_account] = HolderStruct(storage_account)
415-
# self.add_hunged_storage(trx, storage_account)
416433

417434

418435
elif instruction_data[0] == 0x0c or instruction_data[0] == 0x15: # Cancel
@@ -440,7 +457,16 @@ def process_receipts(self):
440457
if eth_signature in trx_table:
441458
trx_table[eth_signature].signatures.append(signature)
442459
else:
443-
trx_table[eth_signature] = TransactionStruct(eth_trx, eth_signature, from_address, got_result, [signature], storage_account, blocked_accounts)
460+
trx_table[eth_signature] = TransactionStruct(
461+
eth_trx,
462+
eth_signature,
463+
from_address,
464+
got_result,
465+
[signature],
466+
storage_account,
467+
blocked_accounts,
468+
slot
469+
)
444470

445471
elif instruction_data[0] == 0x0e:
446472
# logger.debug("{:>10} {:>6} ExecuteTrxFromAccountDataIterativeOrContinue 0x{}".format(slot, counter, instruction_data.hex()))
@@ -454,9 +480,11 @@ def process_receipts(self):
454480
continue_table[storage_account].signatures.append(signature)
455481

456482
if holder_account in holder_table:
457-
logger.error("Strange behavior. Pay attention. HOLDER ACCOUNT FOUND")
458-
holder_table[holder_account] = HolderStruct(storage_account)
483+
if holder_table[holder_account].storage_account != storage_account:
484+
logger.error("Strange behavior. Pay attention. STORAGE_ACCOUNT != STORAGE_ACCOUNT")
485+
holder_table[holder_account] = HolderStruct(storage_account)
459486
else:
487+
logger.error("Strange behavior. Pay attention. HOLDER ACCOUNT NOT FOUND")
460488
holder_table[holder_account] = HolderStruct(storage_account)
461489

462490
if got_result:
@@ -467,67 +495,8 @@ def process_receipts(self):
467495

468496
continue_table[storage_account].results = got_result
469497
else:
470-
got_result = get_trx_results(trx)
471-
if got_result is not None:
472-
continue_table[storage_account] = ContinueStruct(signature, got_result, blocked_accounts)
473-
holder_table[holder_account] = HolderStruct(storage_account)
474-
else:
475-
self.add_hunged_storage(trx, storage_account)
476-
477-
elif instruction_data[0] == 0x13: # PartialCallFromRawEthereumTXv02
478-
# logger.debug("{:>10} {:>6} PartialCallFromRawEthereumTXv02 0x{}".format(slot, counter, instruction_data.hex()))
479-
480-
storage_account = trx['transaction']['message']['accountKeys'][instruction['accounts'][0]]
481-
482-
if storage_account in continue_table:
483-
# collateral_pool_buf = instruction_data[1:5]
484-
# step_count = instruction_data[5:13]
485-
# from_addr = instruction_data[13:33]
486-
487-
sign = instruction_data[33:98]
488-
unsigned_msg = instruction_data[98:]
489-
490-
(eth_trx, eth_signature, from_address) = get_trx_receipts(unsigned_msg, sign)
491-
492-
continue_result = continue_table[storage_account]
493-
494-
self.submit_transaction(eth_trx, eth_signature, from_address, continue_result.results, continue_result.signatures)
495-
496-
del continue_table[storage_account]
497-
else:
498-
self.add_hunged_storage(trx, storage_account)
499-
500-
elif instruction_data[0] == 0x14: # ContinueV02
501-
# logger.debug("{:>10} {:>6} ContinueV02 0x{}".format(slot, counter, instruction_data.hex()))
502-
503-
storage_account = trx['transaction']['message']['accountKeys'][instruction['accounts'][0]]
504-
505-
if storage_account in continue_table:
506-
continue_table[storage_account].signatures.append(signature)
507-
else:
508-
got_result = get_trx_results(trx)
509-
if got_result is not None:
510-
continue_table[storage_account] = ContinueStruct(signature, got_result)
511-
else:
512-
self.add_hunged_storage(trx, storage_account)
513-
514-
elif instruction_data[0] == 0x16: # ExecuteTrxFromAccountDataIterativeV02
515-
# logger.debug("{:>10} {:>6} ExecuteTrxFromAccountDataIterativeV02 0x{}".format(slot, counter, instruction_data.hex()))
516-
517-
holder_account = trx['transaction']['message']['accountKeys'][instruction['accounts'][0]]
518-
storage_account = trx['transaction']['message']['accountKeys'][instruction['accounts'][1]]
519-
520-
if storage_account in continue_table:
521-
continue_table[storage_account].signatures.append(signature)
522-
523-
if holder_account in holder_table:
524-
# logger.debug("holder_account found")
525-
# logger.debug("Strange behavior. Pay attention.")
526-
holder_table[holder_account] = HolderStruct(storage_account)
527-
else:
528-
holder_table[holder_account] = HolderStruct(storage_account)
529-
else:
530-
self.add_hunged_storage(trx, storage_account)
498+
continue_table[storage_account] = ContinueStruct(signature, got_result, blocked_accounts)
499+
holder_table[holder_account] = HolderStruct(storage_account)
531500

532501
if instruction_data[0] > 0x16:
533502
logger.debug("{:>10} {:>6} Unknown 0x{}".format(slot, counter, instruction_data.hex()))
@@ -538,12 +507,12 @@ def process_receipts(self):
538507
if trx_struct.got_result:
539508
self.submit_transaction(trx_struct)
540509
elif trx_struct.storage:
541-
self.blocked_storages[trx_struct.storage] = (trx_struct.eth_trx, trx_struct.blocked_accounts)
510+
if abs(trx_struct.slot - self.current_slot) > CANCEL_TIMEOUT:
511+
self.blocked_storages[trx_struct.storage] = (trx_struct.eth_trx, trx_struct.blocked_accounts)
542512
else:
543513
logger.error(trx_struct)
544514

545515

546-
547516
def submit_transaction(self, trx_struct):
548517
(logs, status, gas_used, return_value, slot) = trx_struct.got_result
549518
(_slot, block_hash) = self.get_block(slot)
@@ -605,11 +574,6 @@ def get_block(self, slot):
605574
return (slot, block_hash)
606575

607576

608-
def add_hunged_storage(self, trx, storage):
609-
if abs(trx['slot'] - self.current_slot) > 16:
610-
self.blocked_storages.add(storage)
611-
612-
613577
def run_indexer():
614578
logging.basicConfig(format='%(asctime)s - pid:%(process)d [%(levelname)-.1s] %(funcName)s:%(lineno)d - %(message)s')
615579
logger.setLevel(logging.DEBUG)

0 commit comments

Comments
 (0)