Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

#492 use neon_instruction and solana_interactor in indexer #549

Merged
Merged
Changes from all commits
Commits
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
14 changes: 9 additions & 5 deletions proxy/common_neon/neon_instruction.py
Original file line number Diff line number Diff line change
@@ -267,7 +267,14 @@ def make_noniterative_call_transaction(self, length_before: int = 0) -> Transact
trx.add(self.make_05_call_instruction())
return trx

def make_cancel_transaction(self) -> Transaction:
def make_cancel_transaction(self, cancel_keys = None) -> Transaction:
append_keys = []
if cancel_keys:
append_keys = cancel_keys
else:
append_keys = self.eth_accounts
append_keys.append(AccountMeta(pubkey=SYSVAR_INSTRUCTION_PUBKEY, is_signer=False, is_writable=False))
append_keys += obligatory_accounts
return Transaction().add(TransactionInstruction(
program_id = EVM_LOADER_ID,
data = bytearray.fromhex("15") + self.eth_trx.nonce.to_bytes(8, 'little'),
@@ -279,10 +286,7 @@ def make_cancel_transaction(self) -> Transaction:
AccountMeta(pubkey=INCINERATOR_PUBKEY, is_signer=False, is_writable=True),
AccountMeta(pubkey=SYS_PROGRAM_ID, is_signer=False, is_writable=False),

] + self.eth_accounts + [

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

def make_partial_call_or_continue_instruction(self, steps=0) -> TransactionInstruction:
3 changes: 3 additions & 0 deletions proxy/common_neon/utils.py
Original file line number Diff line number Diff line change
@@ -159,6 +159,7 @@ def __setstate__(self, src):
self.__dict__ = src

def _set_defaults(self):
self.tx = None
self.addr = None
self.sign = None
self.nonce = None
@@ -174,6 +175,8 @@ def _set_defaults(self):
self.error = None

def init_from_eth_tx(self, tx: EthTx):
self.tx = tx

self.v = hex(tx.v)
self.r = hex(tx.r)
self.s = hex(tx.s)
73 changes: 73 additions & 0 deletions proxy/indexer/canceller.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@

import traceback

from logged_groups import logged_group
from solana.publickey import PublicKey
from solana.rpc.api import Client
from solana.system_program import SYS_PROGRAM_ID
from solana.sysvar import SYSVAR_CLOCK_PUBKEY, SYSVAR_RENT_PUBKEY
from solana.transaction import AccountMeta
from spl.token.constants import TOKEN_PROGRAM_ID
from spl.token.instructions import get_associated_token_address

from proxy.common_neon.constants import INCINERATOR_PUBKEY, KECCAK_PROGRAM, SYSVAR_INSTRUCTION_PUBKEY
from proxy.common_neon.neon_instruction import NeonInstruction
from proxy.common_neon.solana_interactor import SolanaInteractor
from proxy.common_neon.utils import get_from_dict
from proxy.environment import ETH_TOKEN_MINT_ID, EVM_LOADER_ID, SOLANA_URL, get_solana_accounts


@logged_group("neon.Indexer")
class Canceller:
readonly_accs = [
PublicKey(EVM_LOADER_ID),
PublicKey(ETH_TOKEN_MINT_ID),
PublicKey(TOKEN_PROGRAM_ID),
PublicKey(SYSVAR_CLOCK_PUBKEY),
PublicKey(SYSVAR_INSTRUCTION_PUBKEY),
PublicKey(KECCAK_PROGRAM),
PublicKey(SYSVAR_RENT_PUBKEY),
PublicKey(INCINERATOR_PUBKEY),
PublicKey(SYS_PROGRAM_ID),
]

def __init__(self):
# Initialize user account
self.signer = get_solana_accounts()[0]
self._operator = self.signer.public_key()
self._client = Client(SOLANA_URL)
self.operator_token = get_associated_token_address(PublicKey(self._operator), ETH_TOKEN_MINT_ID)

self.solana = SolanaInteractor(self._client)
self.builder = NeonInstruction(self._operator)


def unlock_accounts(self, blocked_storages):
for storage, tx_accounts in blocked_storages.items():
(neon_tx, blocked_accounts) = tx_accounts
if blocked_accounts is None:
self.error(f"Empty blocked accounts for the Neon tx {neon_tx}.")
else:
keys = []
for acc in blocked_accounts:
is_writable = False if PublicKey(acc) in self.readonly_accs else True
keys.append(AccountMeta(pubkey=acc, is_signer=False, is_writable=is_writable))

self.builder.init_eth_trx(neon_tx.tx, None, self.operator_token)
self.builder.init_iterative(storage, None, 0)

trx = self.builder.make_cancel_transaction(keys)

self.debug(f"Send Cancel: {trx}")
try:
cancel_result = self.solana.send_multiple_transactions(self.signer, [trx], neon_tx.tx, "CancelWithNonce")[0]
self.debug(f"cancel result: {cancel_result}")
result_error = get_from_dict(cancel_result, 'meta', 'err')
if result_error:
self.error(f'Error sending cancel transaction: {result_error}')
except Exception as err:
err_tb = "".join(traceback.format_tb(err.__traceback__))
self.error('Exception on submitting transaction. ' +
f'Type(err): {type(err)}, Error: {err}, Traceback: {err_tb}')
else:
self.debug(f"Canceled: {blocked_accounts}")
3 changes: 2 additions & 1 deletion proxy/indexer/indexer.py
Original file line number Diff line number Diff line change
@@ -7,8 +7,9 @@

from ..indexer.indexer_base import IndexerBase
from ..indexer.indexer_db import IndexerDB
from ..indexer.utils import SolanaIxSignInfo, Canceller
from ..indexer.utils import SolanaIxSignInfo
from ..indexer.utils import get_accounts_from_storage, check_error
from ..indexer.canceller import Canceller

from ..common_neon.utils import NeonTxResultInfo, NeonTxInfo, str_fmt_object

73 changes: 2 additions & 71 deletions proxy/indexer/utils.py
Original file line number Diff line number Diff line change
@@ -3,29 +3,20 @@
import base64
import multiprocessing
import psycopg2
import traceback

from typing import NamedTuple

from solana.publickey import PublicKey
from solana.rpc.api import Client
from solana.rpc.commitment import Confirmed
from solana.rpc.types import TxOpts
from solana.system_program import SYS_PROGRAM_ID
from solana.sysvar import SYSVAR_CLOCK_PUBKEY, SYSVAR_RENT_PUBKEY
from solana.transaction import AccountMeta, Transaction, TransactionInstruction
from spl.token.constants import TOKEN_PROGRAM_ID
from spl.token.instructions import get_associated_token_address
from logged_groups import logged_group

from ..common_neon.address import ether2program
from ..common_neon.constants import SYSVAR_INSTRUCTION_PUBKEY, INCINERATOR_PUBKEY, KECCAK_PROGRAM
from ..common_neon.layouts import STORAGE_ACCOUNT_INFO_LAYOUT, CODE_ACCOUNT_INFO_LAYOUT, ACCOUNT_INFO_LAYOUT
from ..common_neon.utils import get_from_dict
from ..environment import SOLANA_URL, EVM_LOADER_ID, ETH_TOKEN_MINT_ID, get_solana_accounts

from proxy.indexer.pg_common import POSTGRES_DB, POSTGRES_USER, POSTGRES_PASSWORD, POSTGRES_HOST
from proxy.indexer.pg_common import encode, decode
from .pg_common import POSTGRES_DB, POSTGRES_USER, POSTGRES_PASSWORD, POSTGRES_HOST
from .pg_common import encode, decode


def check_error(trx):
@@ -191,63 +182,3 @@ def decode_list(self, v):

def encode_list(self, v: []):
return None if (not v) or (len(v) == 0) else encode(v)


@logged_group("neon.Indexer")
class Canceller:
def __init__(self):
# Initialize user account
self.signer = get_solana_accounts()[0]

self.client = Client(SOLANA_URL)

self.operator = self.signer.public_key()
self.operator_token = get_associated_token_address(PublicKey(self.operator), ETH_TOKEN_MINT_ID)

def unlock_accounts(self, blocked_storages):
readonly_accs = [
PublicKey(EVM_LOADER_ID),
PublicKey(ETH_TOKEN_MINT_ID),
PublicKey(TOKEN_PROGRAM_ID),
PublicKey(SYSVAR_CLOCK_PUBKEY),
PublicKey(SYSVAR_INSTRUCTION_PUBKEY),
PublicKey(KECCAK_PROGRAM),
PublicKey(SYSVAR_RENT_PUBKEY),
PublicKey(INCINERATOR_PUBKEY),
PublicKey(SYS_PROGRAM_ID),
]
for storage, tx_accounts in blocked_storages.items():
(neon_tx, blocked_accounts) = tx_accounts
if blocked_accounts is None:
self.error(f"Emtpy blocked accounts for the Neon tx {neon_tx}.")

if blocked_accounts is not None:
keys = [
AccountMeta(pubkey=storage, is_signer=False, is_writable=True),
AccountMeta(pubkey=self.operator, is_signer=True, is_writable=True),
AccountMeta(pubkey=self.operator_token, is_signer=False, is_writable=True),
AccountMeta(pubkey=blocked_accounts[4], 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)
]
for acc in blocked_accounts:
is_writable = False if PublicKey(acc) in readonly_accs else True
keys.append(AccountMeta(pubkey=acc, is_signer=False, is_writable=is_writable))

trx = Transaction()
nonce = int(neon_tx.nonce, 16)
trx.add(TransactionInstruction(
program_id=EVM_LOADER_ID,
data=bytearray.fromhex("15") + nonce.to_bytes(8, 'little'),
keys=keys
))

self.debug("Send Cancel")
try:
self.client.send_transaction(trx, self.signer, opts=TxOpts(preflight_commitment=Confirmed))
except Exception as err:
err_tb = "".join(traceback.format_tb(err.__traceback__))
self.error('Exception on submitting transaction. ' +
f'Type(err): {type(err)}, Error: {err}, Traceback: {err_tb}')
else:
self.debug(f"Canceled: {blocked_accounts}")