Skip to content

Commit

Permalink
Merge pull request #99 from graphsense/feature/tron
Browse files Browse the repository at this point in the history
Merge Tron Changes to develop
  • Loading branch information
soad003 authored Dec 7, 2023
2 parents fb94619 + c8d8711 commit 342bf07
Show file tree
Hide file tree
Showing 19 changed files with 420 additions and 97 deletions.
211 changes: 132 additions & 79 deletions gsrest/db/cassandra.py

Large diffs are not rendered by default.

7 changes: 4 additions & 3 deletions gsrest/db/tagstore.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import aiopg
import hashlib
from gsrest.util import is_eth_like


class Result:
Expand Down Expand Up @@ -240,7 +241,7 @@ def list_tags_by_address(self,
"""

address = address.strip()
if currency == 'eth':
if is_eth_like(currency):
address = address.lower()

return self.execute(query,
Expand Down Expand Up @@ -302,7 +303,7 @@ async def count_address_tags_by_entity(self,
return await self.execute(query, [currency.upper(), entity])

async def get_best_entity_tag(self, currency, entity, show_private=False):
if currency == 'eth':
if is_eth_like(currency):
# in case of eth we want to propagate the best address tag
# regardless of if the tagpack is a defines it as cluster definer
# since cluster == entity in eth
Expand Down Expand Up @@ -361,7 +362,7 @@ async def list_labels_for_addresses(self,
raise TypeError('x')
return Result(), None

if currency == 'eth':
if is_eth_like(currency):
addresses = tuple(addr.lower().strip() for addr in addresses)
else:
addresses = tuple(addr.strip() for addr in addresses)
Expand Down
16 changes: 14 additions & 2 deletions gsrest/service/addresses_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from gsrest.service.rates_service import get_rates
import gsrest.service.common_service as common
from gsrest.errors import NotFoundException
from gsrest.util.address import cannonicalize_address
from openapi_server.models.neighbor_addresses import NeighborAddresses
from openapi_server.models.neighbor_address import NeighborAddress
import asyncio
Expand All @@ -17,6 +18,7 @@ async def list_tags_by_address(request,
address,
page=None,
pagesize=None):
address = cannonicalize_address(currency, address)
return await common.list_tags_by_address(request,
currency,
address,
Expand All @@ -33,10 +35,12 @@ async def list_address_txs(request,
token_currency=None,
page=None,
pagesize=None):
address = cannonicalize_address(currency, address)
db = request.app['db']
results, paging_state = \
await db.list_address_txs(currency, address, direction, min_height,
max_height, token_currency, page, pagesize)

address_txs = await common.txs_from_rows(
request, currency, results, db.get_token_configuration(currency))
return AddressTxs(next_page=paging_state, address_txs=address_txs)
Expand All @@ -50,9 +54,13 @@ async def list_address_neighbors(request,
include_labels=False,
page=None,
pagesize=None):
address = cannonicalize_address(currency, address)
db = request.app['db']
if isinstance(only_ids, list):
aws = [db.get_address_id(currency, id) for id in only_ids]
aws = [
db.get_address_id(currency, cannonicalize_address(currency, id))
for id in only_ids
]
only_ids = await asyncio.gather(*aws)
only_ids = [id for id in only_ids if id is not None]

Expand All @@ -67,7 +75,8 @@ async def list_address_neighbors(request,
if results is None:
return NeighborAddresses()
aws = [
get_address(request, currency, row[dst + '_address'])
get_address(request, currency,
cannonicalize_address(currency, row[dst + '_address']))
for row in results
]

Expand All @@ -90,6 +99,7 @@ async def list_address_links(request,
neighbor,
page=None,
pagesize=None):
address = cannonicalize_address(currency, address)
db = request.app['db']
result = await db.list_address_links(currency,
address,
Expand All @@ -102,6 +112,7 @@ async def list_address_links(request,

async def try_get_delta_update_entity_dummy(request, currency, address,
notfound):
address = cannonicalize_address(currency, address)
db = request.app['db']
try:
aws = [get_rates(request, currency), db.new_entity(currency, address)]
Expand All @@ -115,6 +126,7 @@ async def try_get_delta_update_entity_dummy(request, currency, address,


async def get_address_entity(request, currency, address):
address = cannonicalize_address(currency, address)
db = request.app['db']

notfound = NotFoundException(
Expand Down
3 changes: 2 additions & 1 deletion gsrest/service/blocks_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@
from gsrest.service.rates_service import get_rates
from gsrest.service.txs_service import from_row
from gsrest.errors import NotFoundException
from gsrest.util import is_eth_like


def block_from_row(currency, row):
if currency == 'eth':
if is_eth_like(currency):
return Block(currency=currency,
height=row['block_id'],
block_hash=row['block_hash'].hex(),
Expand Down
7 changes: 5 additions & 2 deletions gsrest/service/common_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
from gsrest.util import get_first_key_present
from gsrest.errors import NotFoundException, BadUserInputException
from psycopg2.errors import InvalidTextRepresentation
from gsrest.util.address import cannonicalize_address
from gsrest.util import is_eth_like


def address_from_row(currency, row, rates, token_config, actors):
Expand Down Expand Up @@ -50,7 +52,7 @@ async def txs_from_rows(request, currency, rows, token_config):
timestamp_keys = ["timestamp", "block_timestamp"]
heights = [get_first_key_present(row, height_keys) for row in rows]
rates = await list_rates(request, currency, heights)
if currency == 'eth':
if is_eth_like(currency):
return [
TxAccount(
currency=currency
Expand Down Expand Up @@ -84,6 +86,7 @@ async def txs_from_rows(request, currency, rows, token_config):


async def get_address(request, currency, address):
address = cannonicalize_address(currency, address)
db = request.app['db']
result = await db.get_address(currency, address)

Expand Down Expand Up @@ -198,7 +201,7 @@ async def add_labels(request, currency, node_type, that, nodes):
async def links_response(request, currency, result):

links, next_page = result
if currency == 'eth':
if is_eth_like(currency):
db = request.app['db']
token_config = db.get_token_configuration(currency)
heights = [row['block_id'] for row in links]
Expand Down
6 changes: 3 additions & 3 deletions gsrest/service/tokens_service.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
from openapi_server.models.token_config import TokenConfig
from openapi_server.models.token_configs import TokenConfigs

from gsrest.util import is_eth_like

async def list_supported_tokens(request, currency):
db = request.app['db']
if currency == "eth":
if is_eth_like(currency):
return TokenConfigs([
TokenConfig(ticker=k.lower(),
decimals=v["decimals"],
peg_currency=v["peg_currency"].lower())
for k, v in db.get_token_configuration("eth").items()
for k, v in db.get_token_configuration(currency).items()
])
else:
return TokenConfigs([])
7 changes: 4 additions & 3 deletions gsrest/service/txs_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,11 @@
from gsrest.service.rates_service import get_rates
from gsrest.util.values import convert_value, convert_token_value
from gsrest.errors import NotFoundException
from gsrest.util import is_eth_like


def from_row(currency, row, rates, token_config, include_io=False):
if currency == 'eth':
if is_eth_like(currency):
return TxAccount(
currency=currency
if "token_tx_id" not in row else row["currency"].lower(),
Expand Down Expand Up @@ -106,7 +107,7 @@ async def get_tx(request,
db = request.app['db']

if token_tx_id is not None:
if currency == 'eth':
if is_eth_like(currency):
results = await list_token_txs(request,
currency,
tx_hash,
Expand Down Expand Up @@ -137,7 +138,7 @@ async def get_tx(request,


async def get_tx_io(request, currency, tx_hash, io):
if currency == 'eth':
if is_eth_like(currency):
raise NotFoundException('get_tx_io not implemented for ETH')
result = await get_tx(request, currency, tx_hash, include_io=True)
return getattr(result, io)
Expand Down
1 change: 0 additions & 1 deletion gsrest/test/entities_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -407,7 +407,6 @@ async def list_entity_neighbors(test_case):
entity=entityWithTags.entity,
include_labels=True,
direction='out')
print(yaml.dump(result))
test_case.assertEqual(ewton, result)

result = await test_case.request(path,
Expand Down
4 changes: 4 additions & 0 deletions gsrest/util/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,7 @@ def get_first_key_present(target_dict, keylist):
if k in target_dict:
return target_dict[k]
raise KeyError(f"Non of the keys {keylist} is present in {target_dict}.")


def is_eth_like(network: str) -> bool:
return network == 'eth' or network == 'trx'
42 changes: 42 additions & 0 deletions gsrest/util/address.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
from gsrest.util.tron import tron_address_to_evm_string, evm_to_tron_address_string, partial_tron_to_partial_evm
from gsrest.util.bch import try_bch_address_to_legacy
from gsrest.util.evm import eth_address_to_hex, is_hex_string


def cannonicalize_address(currency, address, partial=False) -> str:
try:
if currency == "trx":
if partial:
return partial_tron_to_partial_evm(address)
else:
return tron_address_to_evm_string(address, validate=False)
elif currency == "bch":
return try_bch_address_to_legacy(address)
elif isinstance(address, str):
return address
else:
raise Exception(
f"Don't know how to encode address, {address} {currency}")
except ValueError:
return address


def address_to_user_format(currency, db_address) -> str:
if currency == "eth":
if isinstance(db_address, bytes):
return eth_address_to_hex(db_address)
else:
return db_address
elif currency == "trx":
if isinstance(db_address, bytes):
return evm_to_tron_address_string(eth_address_to_hex(db_address))
else:
if is_hex_string(db_address):
return evm_to_tron_address_string(db_address)
else:
return db_address
elif isinstance(db_address, str):
return db_address
else:
raise Exception(
f"Don't know how to decode db address, {db_address} {currency}")
19 changes: 19 additions & 0 deletions gsrest/util/bch.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
from cashaddress.convert import Address, to_legacy_address, InvalidAddress

# Patch P2SH32 legacy address support
# https://bch.info/en/upgrade
if ("P2SH32", 5, False) not in Address.VERSION_MAP["legacy"]:
Address.VERSION_MAP["legacy"].append(("P2SH32", 5, False))
if ("P2SH32", 11, False) not in Address.VERSION_MAP["cash"]:
Address.VERSION_MAP["cash"].append(("P2SH32", 11, False))


def bch_address_to_legacy(address):
return to_legacy_address(address)


def try_bch_address_to_legacy(address):
try:
return bch_address_to_legacy(address)
except InvalidAddress:
return address
26 changes: 26 additions & 0 deletions gsrest/util/evm.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
from typing import Optional

from gsrest.util.string_edit import remove_prefix


def eth_address_to_hex(address):
if not isinstance(address, bytes):
return address
return '0x' + bytes_to_hex(address)


def is_hex_string(string: Optional[str]) -> bool:
return string is not None and string.startswith("0x") and len(string) >= 2


def bytes_to_hex(b: bytes) -> Optional[str]:
r = bytes(b).hex()
return r if len(r) > 0 else None


def hex_str_to_bytes(hex_str: str) -> bytes:
return bytes.fromhex(hex_str)


def strip_0x(string: Optional[str]) -> Optional[str]:
return remove_prefix(string, "0x") if is_hex_string(string) else string
7 changes: 7 additions & 0 deletions gsrest/util/string_edit.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,10 @@

def alphanumeric_lower(expression):
return pattern.sub("", expression).lower()


def remove_prefix(s: str, prefix: str) -> str:
if s.startswith(prefix):
return s[len(prefix):]
else:
return s
Loading

0 comments on commit 342bf07

Please sign in to comment.