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

ci_test_block -> master v0.6.0-rc4 #603

Merged
merged 37 commits into from
Feb 25, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
e5e9649
#428 implement eth_getCode (#535)
otselnik Feb 3, 2022
e1f883e
VERSION = '0.6.0-dev' (#539)
vasiliy-zaznobin Feb 3, 2022
0c711b6
#517 suppress neon cli stderr (#541)
rozhkovdmitrii Feb 4, 2022
e027c80
#543 fix airdroper (#544)
otselnik Feb 4, 2022
7b9f2c9
#491 indexer as service (#540)
otselnik Feb 4, 2022
d5e1a62
#518 update logging format (#548)
rozhkovdmitrii Feb 4, 2022
dd45c94
#480 Do not create new read only accounts (#531)
anton-lisanin Feb 7, 2022
cd07241
542 memdb (#553)
afalaleev Feb 8, 2022
ca502e2
#492 use neon_instruction and solana_interactor in indexer (#549)
otselnik Feb 9, 2022
9fbf591
#520 add logging context to indexer (#558)
otselnik Feb 9, 2022
a25d293
Remove NEW_USER_AIRDROP_AMOUNT (320-change-new-user-airdrop) (#505)
vakond Feb 9, 2022
28844d5
560 gas_price must be represented in alan, not Galan (#561)
ivandzen Feb 9, 2022
797ddaf
Use faucet for local env (#563)
vasiliy-zaznobin Feb 9, 2022
f7ad45d
566 Update Pyth mapping account in GasPriceCalculator (#567)
ivandzen Feb 10, 2022
0dbfe37
568 Fix using of get_min_gas_price in solana_rest_api.py (#569)
ivandzen Feb 10, 2022
0a7c257
#357 log message on starting proxy (#564)
rozhkovdmitrii Feb 10, 2022
5e2d628
490 check operator SOLs (#557)
vasiliy-zaznobin Feb 11, 2022
c1faa04
neonlabsorg/Solana-EVM#355 Reduce logging on Indexer (#570)
otselnik Feb 15, 2022
52b3d2a
Check that the user's account balance is less than required and raise…
vasiliy-zaznobin Feb 15, 2022
5dff1ba
Last changes from devnet tests (#578)
afalaleev Feb 17, 2022
aa2d446
Use slot for block number. #580
afalaleev Feb 17, 2022
62c4368
All connections to Solana by SolanaInteractor
afalaleev Feb 19, 2022
d61b87c
Add installing of solcx to Dockerfile
afalaleev Feb 19, 2022
b89880d
Fix Neon EVM program version
afalaleev Feb 19, 2022
34d6675
Use SolTxSender for transaction sending.
afalaleev Feb 20, 2022
fea297d
Fix exeception on erasing not-exist key
afalaleev Feb 20, 2022
f799d94
Add reconnect on disconnect from Solana node
afalaleev Feb 20, 2022
cd67692
Use cache of existing blocks
afalaleev Feb 20, 2022
2d230a3
Fix Neon EVM version in docker-compose
afalaleev Feb 20, 2022
44162f6
Fix block order in cache
afalaleev Feb 20, 2022
1c35651
Change type of exception on connection problem
afalaleev Feb 20, 2022
263eb27
Create fake blocks for empty slots
afalaleev Feb 20, 2022
b0f0aaa
Call cancel on unknown errors for iterative transactions. #587
afalaleev Feb 21, 2022
2fc45c1
Show error message if history is disabled on the Solana node
afalaleev Feb 24, 2022
3ade5cb
Generate fake blocks for finalized history
afalaleev Feb 24, 2022
d9cd027
Merge remote-tracking branch 'origin/ci-test-block' into ci-test-bloc…
vasiliy-zaznobin Feb 25, 2022
324d005
EVM_LOADER_REVISION:=v0.6.0-rc3
vasiliy-zaznobin Feb 25, 2022
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
1 change: 1 addition & 0 deletions .buildkite/pipeline.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ steps:
- "evm_loader.log"
- "faucet.log"
- "airdropper.log"
- "indexer.log"

- wait

Expand Down
2 changes: 1 addition & 1 deletion .buildkite/steps/build-image.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ set -euo pipefail
REVISION=$(git rev-parse HEAD)

set ${SOLANA_REVISION:=v1.8.12-testnet}
set ${EVM_LOADER_REVISION:=stable}
set ${EVM_LOADER_REVISION:=v0.6.0-rc3}

# Refreshing neonlabsorg/solana:latest image is required to run .buildkite/steps/build-image.sh locally
docker pull neonlabsorg/solana:${SOLANA_REVISION}
Expand Down
8 changes: 6 additions & 2 deletions .buildkite/steps/deploy-test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ function cleanup_docker {
if docker logs evm_loader >evm_loader.log 2>&1; then echo "evm_loader logs saved"; fi
if docker logs faucet >faucet.log 2>&1; then echo "faucet logs saved"; fi
if docker logs airdropper >airdropper.log 2>&1; then echo "airdropper logs saved"; fi
if docker logs indexer >indexer.log 2>&1; then echo "indexer logs saved"; fi

echo "\nCleanup docker-compose..."
docker-compose -f proxy/docker-compose-test.yml down
Expand Down Expand Up @@ -73,17 +74,19 @@ echo "Wait proxy..." && wait-for-proxy "$PROXY_URL"

export EVM_LOADER=$(docker exec proxy bash -c "solana address -k /spl/bin/evm_loader-keypair.json")
export SOLANA_URL=$(docker exec solana bash -c 'echo "$SOLANA_URL"')
export FAUCET_URL=$(docker exec proxy bash -c 'echo "$FAUCET_URL"')

echo "EVM_LOADER" $EVM_LOADER
echo "SOLANA_URL" $SOLANA_URL
echo "FAUCET_URL" $FAUCET_URL

echo "Run proxy tests..."
docker run --rm -ti --network=container:proxy \
-e PROXY_URL \
-e EVM_LOADER \
-e SOLANA_URL \
-e FAUCET_URL \
-e EXTRA_GAS=100000 \
-e NEW_USER_AIRDROP_AMOUNT=100 \
-e POSTGRES_DB=neon-db \
-e POSTGRES_USER=neon-proxy \
-e POSTGRES_PASSWORD=neon-proxy-pass \
Expand All @@ -93,7 +96,8 @@ docker run --rm -ti --network=container:proxy \
$PROXY_IMAGE

echo "Run uniswap-v2-core tests..."
docker run --rm -ti --network=host \
docker run --rm -ti --network=container:proxy \
-e FAUCET_URL \
--entrypoint ./deploy-test.sh \
${EXTRA_ARGS:-} \
$UNISWAP_V2_CORE_IMAGE \
Expand Down
3 changes: 2 additions & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,9 @@ RUN apt update && \
pip3 install --upgrade pip && \
/bin/bash -c "source venv/bin/activate" && \
pip install -r requirements.txt && \
pip3 install py-solc-x && \
python3 -c "import solcx; solcx.install_solc(version='0.7.6')" && \
apt remove -y git && \
pip install py-solc-x && \
rm -rf /var/lib/apt/lists/*

COPY --from=cli /opt/solana/bin/solana \
Expand Down
4 changes: 2 additions & 2 deletions log_cfg.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,12 @@
},
"formatters": {
"standard": {
"format": "%(asctime)s.%(msecs)03d %(levelname)8s %(process)6d:%(threadName)-11s %(name)15s:%(class)-30s %(context)s %(message)s",
"format": "%(asctime)s.%(msecs)03d %(levelname)-.1s %(filename)s:%(lineno)d %(process)d %(name)s:%(class)s %(context)s %(message)s",
"style": "%",
"datefmt": "%Y-%m-%d %H:%M:%S"
},
"root": {
"format": "%(asctime)s.%(msecs)03d %(levelname)8s %(process)6d:%(threadName)-11s %(name)15s:Undefined %(context)s %(message)s",
"format": "%(asctime)s.%(msecs)03d %(levelname)-.1s %(filename)s:%(lineno)d %(process)d %(name)s:Undefined %(context)s %(message)s",
"style": "%",
"datefmt": "%Y-%m-%d %H:%M:%S"
}
Expand Down
4 changes: 2 additions & 2 deletions pretty_log_cfg.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,12 @@
},
"formatters": {
"standard": {
"format": "%(asctime)s.%(msecs)03d [%(levelname)-.1s] pid:%(process)d %(name)s:%(filename)s:%(lineno)d %(context)s %(message)s",
"format": "%(asctime)s.%(msecs)03d [%(levelname)-.1s] P:%(process)d %(name)s:%(class)s:%(funcName)s:%(lineno)d %(context)s %(message)s",
"style": "%",
"datefmt": "%Y-%m-%d %H:%M:%S"
},
"root": {
"format": "%(asctime)s.%(msecs)03d [%(levelname)-.1s] pid:%(process)d %(name)s:Undefined %(context)s %(message)s",
"format": "%(asctime)s.%(msecs)03d [%(levelname)-.1s] P:%(process)d %(name)s:%(lineno)d %(context)s %(message)s",
"style": "%",
"datefmt": "%Y-%m-%d %H:%M:%S"
}
Expand Down
4 changes: 0 additions & 4 deletions proxy/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
from .proxy import entry_point
from .proxy import main, start
from .proxy import Proxy
from .testing.test_case import TestCase

__all__ = [
# PyPi package entry_point. See
Expand All @@ -20,8 +19,5 @@
# Embed proxy.py. See
# https://github.com/abhinavsingh/proxy.py#embed-proxypy
'main', 'start',
# Unit testing with proxy.py. See
# https://github.com/abhinavsingh/proxy.py#unit-testing-with-proxypy
'TestCase',
'Proxy',
]
11 changes: 8 additions & 3 deletions proxy/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,14 @@
from .proxy import entry_point
import os
from .indexer.airdropper import run_airdropper
from solana.rpc.api import Client
from .indexer.indexer import run_indexer

if __name__ == '__main__':
airdropper_mode = os.environ.get('AIRDROPPER_MODE', 'False').lower() in [1, 'true', 'True']
indexer_mode = os.environ.get('INDEXER_MODE', 'False').lower() in [1, 'true', 'True']
if airdropper_mode:
print("Will run in airdropper mode")
solana_url = os.environ['SOLANA_URL']
evm_loader_id = os.environ['EVM_LOADER']
pyth_mapping_account = PublicKey(os.environ['PYTH_MAPPING_ACCOUNT'])
faucet_url = os.environ['FAUCET_URL']
wrapper_whitelist = os.environ['INDEXER_ERC20_WRAPPER_WHITELIST']
Expand All @@ -32,12 +32,17 @@
max_conf = float(os.environ.get('MAX_CONFIDENCE_INTERVAL', 0.02))

run_airdropper(solana_url,
evm_loader_id,
pyth_mapping_account,
faucet_url,
wrapper_whitelist,
neon_decimals,
pp_solana_url,
max_conf)
elif indexer_mode:
print("Will run in indexer mode")

solana_url = os.environ['SOLANA_URL']

run_indexer(solana_url)
else:
entry_point()
54 changes: 23 additions & 31 deletions proxy/common_neon/account_whitelist.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
import traceback
from datetime import datetime
import time
from proxy.environment import ELF_PARAMS, GET_WHITE_LIST_BALANCE_MAX_RETRIES, GET_WHITE_LIST_BALANCE_RETRY_INTERVAL_S
from proxy.environment import ELF_PARAMS
from proxy.common_neon.permission_token import PermissionToken
from solana.publickey import PublicKey
from solana.rpc.api import Client as SolanaClient
from solana.account import Account as SolanaAccount
from typing import Union
from proxy.common_neon.address import EthereumAddress
from logged_groups import logged_group
from ..common_neon.solana_interactor import SolanaInteractor

NEON_MINIMAL_CLIENT_ALLOWANCE_BALANCE = int(ELF_PARAMS.get("NEON_MINIMAL_CLIENT_ALLOWANCE_BALANCE", 0))
NEON_MINIMAL_CONTRACT_ALLOWANCE_BALANCE = int(ELF_PARAMS.get("NEON_MINIMAL_CONTRACT_ALLOWANCE_BALANCE", 0))
Expand All @@ -18,10 +17,7 @@

@logged_group("neon.AccountWhitelist")
class AccountWhitelist:
def __init__(self, solana: SolanaClient, payer: SolanaAccount, permission_update_int: int):
self.info(f'GET_WHITE_LIST_BALANCE_MAX_RETRIES={GET_WHITE_LIST_BALANCE_MAX_RETRIES}')
self.info(f'GET_WHITE_LIST_BALANCE_RETRY_INTERVAL_S={GET_WHITE_LIST_BALANCE_RETRY_INTERVAL_S} seconds')
self.info(f'permission_update_int={permission_update_int}')
def __init__(self, solana: SolanaInteractor, payer: SolanaAccount, permission_update_int: int):
self.solana = solana
self.account_cache = {}
self.permission_update_int = permission_update_int
Expand All @@ -43,9 +39,15 @@ def __init__(self, solana: SolanaClient, payer: SolanaAccount, permission_update
PublicKey(DENIAL_TOKEN_ADDR),
payer)

def read_balance_diff(self, ether_addr: Union[str, EthereumAddress]):
allowance_balance = self.allowance_token.get_balance(ether_addr)
denial_balance = self.denial_token.get_balance(ether_addr)
def read_balance_diff(self, ether_addr: Union[str, EthereumAddress]) -> int:
token_list = [
self.allowance_token.get_token_account_address(ether_addr),
self.denial_token.get_token_account_address(ether_addr)
]

balance_list = self.solana.get_token_account_balance_list(token_list)
allowance_balance = balance_list[0]
denial_balance = balance_list[1]
return allowance_balance - denial_balance

def grant_permissions(self, ether_addr: Union[str, EthereumAddress], min_balance: int):
Expand Down Expand Up @@ -106,27 +108,17 @@ def has_permission(self, ether_addr: Union[str, EthereumAddress], min_balance: i
if diff < self.permission_update_int:
return cached['diff'] >= min_balance

num_retries = GET_WHITE_LIST_BALANCE_MAX_RETRIES

while True:
try:
diff = self.read_balance_diff(ether_addr)
self.account_cache[ether_addr] = {
'last_update': current_time,
'diff': diff
}
return diff >= min_balance
except Exception as err:
err_tb = "".join(traceback.format_tb(err.__traceback__))
self.error(f'Failed to read permissions for {ether_addr}: ' +
f'Type(err): {type(err)}, Error: {err}, Traceback: {err_tb}')
num_retries -= 1
if num_retries == 0:
# This error should be forwarded to client
raise RuntimeError('Failed to read account permissions. Try to repeat later')

self.info(f'Will retry getting whitelist balance after {GET_WHITE_LIST_BALANCE_RETRY_INTERVAL_S} seconds')
time.sleep(GET_WHITE_LIST_BALANCE_RETRY_INTERVAL_S)
try:
diff = self.read_balance_diff(ether_addr)
self.account_cache[ether_addr] = {
'last_update': current_time,
'diff': diff
}
return diff >= min_balance
except Exception as err:
err_tb = "".join(traceback.format_tb(err.__traceback__))
self.error(f'Failed to read permissions for {ether_addr}: ' +
f'Type(err): {type(err)}, Error: {err}, Traceback: {err_tb}')

def has_client_permission(self, ether_addr: Union[str, EthereumAddress]):
return self.has_permission(ether_addr, NEON_MINIMAL_CLIENT_ALLOWANCE_BALANCE)
Expand Down
2 changes: 1 addition & 1 deletion proxy/common_neon/address.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,4 +65,4 @@ class AccountInfo(NamedTuple):
@staticmethod
def frombytes(data):
cont = ACCOUNT_INFO_LAYOUT.parse(data)
return AccountInfo(cont.ether, cont.trx_count, PublicKey(cont.code_account))
return AccountInfo(cont.ether, int.from_bytes(cont.trx_count, 'little'), PublicKey(cont.code_account))
2 changes: 1 addition & 1 deletion proxy/common_neon/costs.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import base58

from ..environment import EVM_LOADER_ID
from ..indexer.utils import BaseDB
from ..indexer.base_db import BaseDB


class SQLCost(BaseDB):
Expand Down
4 changes: 4 additions & 0 deletions proxy/common_neon/errors.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,7 @@ class SolanaAccountNotFoundError(Exception):
"""Provides special error processing"""
def __init__(self):
super().__init__(SolanaErrors.AccountNotFound.value)


class PendingTxError(Exception):
pass
58 changes: 47 additions & 11 deletions proxy/common_neon/eth_proto.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
from ecdsa import SigningKey, SECP256k1, VerifyingKey
from sha3 import keccak_256
import json
import rlp
from eth_keys import keys

Expand All @@ -21,6 +19,9 @@
'''


class InvalidTrx(Exception):
pass


class Trx(rlp.Serializable):
fields = (
Expand All @@ -35,6 +36,9 @@ class Trx(rlp.Serializable):
('s', rlp.codec.big_endian_int)
)

secpk1n = 115792089237316195423570985008687907852837564279074904382605163141518161494337
null_address = b'\xff' * 20

def __init__(self, *args, **kwargs):
rlp.Serializable.__init__(self, *args, **kwargs)
self._msg = None
Expand All @@ -44,29 +48,60 @@ def fromString(cls, s):
return rlp.decode(s, Trx)

def chainId(self):
# chainid*2 + 35 xxxxx0 + 100011 xxxx0 + 100010 +1
# chainid*2 + 36 xxxxx0 + 100100 xxxx0 + 100011 +1
return (self.v-1)//2 - 17
if self.v in (27, 28):
return None
elif self.v >= 37:
# chainid*2 + 35 xxxxx0 + 100011 xxxx0 + 100010 +1
# chainid*2 + 36 xxxxx0 + 100100 xxxx0 + 100011 +1
return ((self.v - 1) // 2) - 17
else:
raise InvalidTrx("Invalid V value")

def _unsigned_msg(self):
chain_id = self.chainId()
if chain_id is None:
return rlp.encode((self.nonce, self.gasPrice, self.gasLimit, self.toAddress, self.value, self.callData))
else:
return rlp.encode((self.nonce, self.gasPrice, self.gasLimit, self.toAddress, self.value, self.callData,
chain_id, 0, 0), Trx)

def unsigned_msg(self):
if self._msg is None:
self._msg = rlp.encode((self.nonce, self.gasPrice, self.gasLimit, self.toAddress, self.value, self.callData, self.chainId(), b"", b""))
self._msg = self._unsigned_msg()
return self._msg

def _signature(self):
return keys.Signature(vrs=[1 if self.v % 2 == 0 else 0, self.r, self.s])

def signature(self):
return keys.Signature(vrs=[1 if self.v % 2 == 0 else 0, self.r, self.s]).to_bytes()
return self._signature().to_bytes()

def _sender(self):
hash = keccak_256(self.unsigned_msg()).digest()
sig = keys.Signature(vrs=[1 if self.v % 2 == 0 else 0, self.r, self.s])
pub = sig.recover_public_key_from_msg_hash(hash)
if self.r == 0 and self.s == 0:
return self.null_address
elif self.v in (27, 28):
pass
elif self.v >= 37:
vee = self.v - self.chainId() * 2 - 8
assert vee in (27, 28)
else:
raise InvalidTrx("Invalid V value")

if self.r >= self.secpk1n or self.s >= self.secpk1n or self.r == 0 or self.s == 0:
raise InvalidTrx("Invalid signature values!")

sighash = keccak_256(self._unsigned_msg()).digest()
sig = self._signature()
pub = sig.recover_public_key_from_msg_hash(sighash)

return pub.to_canonical_address()

def sender(self):
return self._sender().hex()

def hash_signed(self):
return keccak_256(rlp.encode((self.nonce, self.gasPrice, self.gasLimit, self.toAddress, self.value, self.callData,
return keccak_256(rlp.encode((self.nonce, self.gasPrice, self.gasLimit,
self.toAddress, self.value, self.callData,
self.v, self.r, self.s))).digest()

def contract(self):
Expand All @@ -75,6 +110,7 @@ def contract(self):
contract_addr = rlp.encode((self._sender(), self.nonce))
return keccak_256(contract_addr).digest()[-20:].hex()


#class JsonEncoder(json.JSONEncoder):
# def default(self, obj):
# if isinstance(obj, bytes):
Expand Down
8 changes: 7 additions & 1 deletion proxy/common_neon/layouts.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@

from construct import Bytes, Int8ul, Int64ul
from construct import Bytes, Int8ul, Int32ul, Int64ul
from construct import Struct

STORAGE_ACCOUNT_INFO_LAYOUT = Struct(
Expand Down Expand Up @@ -30,6 +30,12 @@
"ro_blocked_cnt" / Int8ul,
)

CODE_ACCOUNT_INFO_LAYOUT = Struct(
"type" / Int8ul,
"owner" / Bytes(32),
"code_size" / Int32ul,
)


CREATE_ACCOUNT_LAYOUT = Struct(
"lamports" / Int64ul,
Expand Down
Loading