Skip to content

Commit

Permalink
Small fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
tvorogme committed Oct 10, 2024
1 parent 48a7413 commit 56b4dc6
Show file tree
Hide file tree
Showing 13 changed files with 154 additions and 24 deletions.
2 changes: 1 addition & 1 deletion .idea/misc.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion .idea/tonpy.iml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ def finalize_options(self):

setup(
name="tonpy" if not IS_DEV else "tonpy-dev",
version="0.0.0.1.2b0" if not IS_DEV else "0.0.0.4.7b1",
version="0.0.0.1.2b0" if not IS_DEV else "0.0.0.4.7c1",
author="Disintar LLP",
author_email="[email protected]",
description="Types / API for TON blockchain",
Expand Down
17 changes: 12 additions & 5 deletions src/tonpy/blockscanner/blockscanner.py
Original file line number Diff line number Diff line change
Expand Up @@ -108,13 +108,19 @@ def process_subscriptions(data,
raise NotImplementedError("Emulation not supported yet")


def get_mega_libs(num_try=100):
def get_mega_libs(dton_key, num_try=100):
cur = 0

while cur < num_try:
try:
query = '''query{mega_libs_cell}'''
response = requests.post("https://dton.io/graphql", json={'query': query})

if dton_key is not None:
url = f"https://dton.io/{dton_key}/graphql"
else:
url = f"https://dton.io/graphql"

response = requests.post(url, json={'query': query})
return response.json()['data']['mega_libs_cell']
except Exception as e:
logger.error(f"Can't get dton.io/graphql: {e}, {tb.format_exc()}")
Expand Down Expand Up @@ -498,7 +504,8 @@ def __init__(self,
live_load_enable: bool = False,
load_chunks: typing.List[typing.Tuple[int, int]] = None,
allow_skip_mc_in_live: bool = True,
blocks_to_load: List[BlockIdExt] = None):
blocks_to_load: List[BlockIdExt] = None,
dton_key: str = None):
"""
:param lcparams: Params for LiteClient
Expand Down Expand Up @@ -583,7 +590,7 @@ def __init__(self,
self.account_subscriptions = account_subscriptions
self.emulate_before_output = emulate_before_output
self.known_key_blocks = {}
self.mega_libs = get_mega_libs()
self.mega_libs = get_mega_libs(dton_key)

self.process_raw = raw_process is not None
if self.process_raw:
Expand Down Expand Up @@ -901,7 +908,7 @@ def load_historical(self):
if self.loglevel > 1:
logger.debug(f"Start get mega libs: {time() - key_blocks_start_at}")

mega_libs = get_mega_libs()
mega_libs = self.mega_libs

for i in shards_data:
i['libs'] = mega_libs
Expand Down
5 changes: 4 additions & 1 deletion src/tonpy/tests/test_vmdict_large_keys.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@

import pytest

from tonpy import LiteClient
from tonpy.autogen.block import Account

path_root = Path(__file__).parents[2]
sys.path.append(str(path_root))

Expand Down Expand Up @@ -62,7 +65,7 @@ def test_set_get_large():
d.set_ref(CellBuilder().store_uint(1, 8).store_uint(2 ** 254, 256).end_cell().begin_parse(), v2)

d.set_builder(CellBuilder().store_uint(2, 8).store_uint(2 ** 254, 256).end_cell().begin_parse(),
CellBuilder().store_uint(0, 8))
CellBuilder().store_uint(0, 8))

value = d.lookup(CellBuilder().store_uint(0, 8).store_uint(2 ** 254, 256).end_cell().begin_parse())
assert value.get_hash() == v1.get_hash()
Expand Down
6 changes: 5 additions & 1 deletion src/tonpy/tvm/c7.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
from typing import Union, List

from tonpy.types import Cell, CellSlice, Stack, begin_cell, Address
from tonpy.types.cell import Cell
from tonpy.types.cellslice import CellSlice
from tonpy.types.cellbuilder import begin_cell
from tonpy.types.address import Address
from datetime import datetime
from tonpy.types.blockid import BlockIdExt
from tonpy.types.stack import Stack


class C7:
Expand Down
2 changes: 1 addition & 1 deletion src/tonpy/tvm/emulator.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

from tonpy.libs.python_ton import PyEmulator

from tonpy import Stack, StackEntry
from tonpy.types.stack import Stack, StackEntry
from tonpy.types import VmDict, Cell, CellSlice, begin_cell
from tonpy.types.blockid import BlockId
from typing import Union, Tuple, List
Expand Down
52 changes: 51 additions & 1 deletion src/tonpy/tvm/tvm.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,13 @@ def clear_stack(self) -> bool:
def fetch_detailed_step_info(self) -> None:
self.vm_steps_detailed = [StepInfo(i) for i in self.tvm.get_stacks()]
ops = self.tvm.get_ops()
assert len(ops) == len(self.vm_steps_detailed)
if len(ops) != len(self.vm_steps_detailed):
if len(self.vm_steps_detailed) - len(ops) == 1:
self.vm_steps_detailed = self.vm_steps_detailed[1:]
else:
logger.error(f"VM steps: {len(ops)} != {len(self.vm_steps_detailed)}")
return

for i, op in enumerate(ops):
self.vm_steps_detailed[i].next_op = op

Expand Down Expand Up @@ -113,6 +119,50 @@ def exit_code(self) -> int:
return ~self.tvm.exit_code
return self.tvm.exit_code

def exit_code_description(self):
exit_codes = {
0: {"Phase": "Compute Phase", "Description": "Standard successful execution exit code."},
1: {"Phase": "Compute Phase", "Description": "Alternative successful execution exit code."},
2: {"Phase": "Compute Phase",
"Description": "Stack underflow. Last op-code consumed more elements than there are on the stacks."},
3: {"Phase": "Compute Phase",
"Description": "Stack overflow. More values have been stored on a stack than allowed by this version of TVM."},
4: {"Phase": "Compute Phase",
"Description": "Integer overflow. Integer does not fit into −2^256 ≤ x < 2^256 or a division by zero has occurred."},
5: {"Phase": "Compute Phase", "Description": "Integer out of expected range."},
6: {"Phase": "Compute Phase",
"Description": "Invalid opcode. Instruction is unknown in the current TVM version."},
7: {"Phase": "Compute Phase",
"Description": "Type check error. An argument to a primitive is of an incorrect value type."},
8: {"Phase": "Compute Phase",
"Description": "Cell overflow. Writing to builder is not possible since after operation there would be more than 1023 bits or 4 references."},
9: {"Phase": "Compute Phase",
"Description": "Cell underflow. Read from slice primitive tried to read more bits or references than there are."},
10: {"Phase": "Compute Phase",
"Description": "Dictionary error. Error during manipulation with dictionary (hashmaps)."},
11: {"Phase": "Compute Phase",
"Description": "Most often caused by trying to call get-method whose id wasn't found in the code (missing method_id modifier or wrong get-method name specified when trying to call it)."},
12: {"Phase": "Compute Phase", "Description": "Thrown by TVM in situations deemed impossible."},
13: {"Phase": "Compute Phase",
"Description": "Out of gas error. Thrown by TVM when the remaining gas becomes negative."},
32: {"Phase": "Action Phase",
"Description": "Action list is invalid. Set during action phase if c5 register after execution contains unparsable object."},
33: {"Phase": "Action Phase", "Description": "Action list is too long."},
34: {"Phase": "Action Phase",
"Description": "Action is invalid or not supported. Set during action phase if current action cannot be applied."},
35: {"Phase": "Action Phase", "Description": "Invalid Source address in outbound message."},
36: {"Phase": "Action Phase", "Description": "Invalid Destination address in outbound message."},
37: {"Phase": "Action Phase",
"Description": "Not enough TON. Message sends too much TON (or there is not enough TON after deducting fees)."},
38: {"Phase": "Action Phase", "Description": "Not enough extra-currencies."},
40: {"Phase": "Action Phase",
"Description": "Not enough funds to process a message. This error is thrown when there is only enough gas to cover part of the message, but does not cover it completely."},
43: {"Phase": "Action Phase",
"Description": "The maximum number of cells in the library is exceeded or the maximum depth of the Merkle tree is exceeded."}
}

return exit_codes[self.exit_code]

@property
def vm_steps(self) -> int:
return self.tvm.vm_steps
Expand Down
6 changes: 1 addition & 5 deletions src/tonpy/types/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

from tonpy.types.cell import Cell
from tonpy.types.cellslice import CellSlice
from tonpy.types.cellbuilder import CellBuilder
from tonpy.types.cellbuilder import CellBuilder, begin_cell
from tonpy.types.vmdict import VmDict, TypedVmDict, TypedDataWithExtra, DataWithExtra, AugmentedData, TypedAugmentedData
from tonpy.types.tlb import TLB, RecordBase
from tonpy.types.tlb_types import RefT, NatWidth, TLBComplex, Int, UInt, Bits, NatLeq, NatLess
Expand All @@ -13,7 +13,3 @@
from tonpy.types.liteclient import *
from tonpy.types.address import *
from tonpy.types.vmdict_extra import *


def begin_cell():
return CellBuilder()
1 change: 1 addition & 0 deletions src/tonpy/types/address.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ def shard_prefix(self, size) -> int:
return self.my_address.shard_prefix(size)

def to_cs(self) -> CellSlice:
from tonpy.types.cellbuilder import CellBuilder
return CellBuilder().store_address(self).end_cell().begin_parse()

def __eq__(self, other):
Expand Down
4 changes: 4 additions & 0 deletions src/tonpy/types/cellbuilder.py
Original file line number Diff line number Diff line change
Expand Up @@ -418,3 +418,7 @@ def __repr__(self):
r = self.refs

return f"<CellBuilder [{b}] bits, [{r}] refs, [{self.get_hash()}] hash>"


def begin_cell():
return CellBuilder()
74 changes: 67 additions & 7 deletions src/tonpy/types/liteclient.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,12 @@
from tonpy.libs.python_ton import PyLiteClient, ipv4_int_to_str, globalSetVerbosity, BlockId as ton_BlockId, \
BlockIdExt as ton_BlockIdExt

from tonpy.types.lite_utils.constants import MASTER_SHARD
from tonpy.types.cellbuilder import CellBuilder
from tonpy.types.stack import Stack
from tonpy.types.cell import Cell
from tonpy.types.address import Address
from tonpy.tvm.tvm import TVM, method_name_to_id

from tonpy.types.keys import PublicKey
from base64 import b64decode
Expand Down Expand Up @@ -74,6 +78,23 @@ def __init__(self, ac):
self.gen_lt = ac.gen_lt
self.gen_utime = ac.gen_utime

def to_shard_state(self):
if not self.root.is_null():
return CellBuilder() \
.store_ref(self.root) \
.store_uint(int(self.last_trans_hash, 16), 256) \
.store_uint(self.last_trans_lt, 64).end_cell()
else:
return CellBuilder() \
.store_ref(CellBuilder().store_uint(0, 1).end_cell()) \
.store_uint(int(self.last_trans_hash, 16), 256) \
.store_uint(self.last_trans_lt, 64) \
.end_cell()

def get_parsed(self):
from tonpy.autogen.block import Account
return Account().cell_unpack(self.root, rec_unpack=True)


class BlockHdrInfo:
__slots__ = ['blk_id', 'proof', 'virt_blk_root', 'mode']
Expand Down Expand Up @@ -148,13 +169,6 @@ def __init__(self, servers: list,
logprefix: str = ''):
random.shuffle(servers)
self.servers = servers

# for s in servers:
# if self.check_server(s):
# self.servers.append(s)
# print(len(self.servers), len(servers))
# print(servers)

self.current = -1
self.client: Optional[LiteClient] = None
self.timeout = timeout
Expand Down Expand Up @@ -549,6 +563,52 @@ def wait_connected(self, timeout: int):
"""Wait until connected with timeout, throw error if not connected"""
return self.client.wait_connected(datetime.datetime.now().timestamp() + timeout)

def run_get_method(self, account: Address,
method: str,
stack: Union[Stack, List] = None,
mc_seqno: int = None,
block: BlockIdExt = None,
c7=None,
allow_non_success=False,
gas_limit=5000000,
gas_max=5000000):
from tonpy.tvm.c7 import C7

if stack is None:
stack = []

if mc_seqno is not None:
if block:
raise ValueError(f"Can't run get_method with block {block} because block {mc_seqno} is provided")
block = BlockId(workchain=-1, shard=MASTER_SHARD, seqno=mc_seqno)

if block is None:
block = self.get_masterchain_info_ext().last

account_state = self.get_account_state(account, block).get_parsed()

code = account_state.storage.state.x.code.value
data = account_state.storage.state.x.data.value

tvm = TVM(data=data, code=code, allow_debug=True)
tvm.set_gas_limit(gas_limit, gas_max)

if c7 is None:
config = self.get_config_all(block)

# Todo: last_mc_blocks, prev_key_block, income_extra
tvm.set_c7(C7(
time=datetime.datetime.now(),
balance_grams=account_state.storage.balance.grams.amount.value,
address=account,
my_code=code,
global_config=config[1].get_cell()
))

tvm.set_stack([*stack, method_name_to_id(method)])

return tvm.run(allow_non_success=True)

@staticmethod
def get_one(timeout: int = 1, threads: int = 1) -> "LiteClient":
server = random.choice(servers)
Expand Down
4 changes: 4 additions & 0 deletions src/tonpy/types/stack.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

from tonpy.libs.python_ton import PyStackEntry, PyStack, make_tuple, deserialize_stack_entry, deserialize_stack, \
PyContinuation

from tonpy.types.address import Address
from tonpy.types import Cell, CellSlice, CellBuilder
from typing import Union, Iterable, List
from enum import Enum
Expand Down Expand Up @@ -60,6 +62,8 @@ def __init__(self, value: "None | Cell | CellSlice | int | CellBuilder | list |
self.entry = StackEntry.create_tuple(value).entry
elif isinstance(value, Continuation):
self.entry = PyStackEntry(continuation=value)
elif isinstance(value, Address):
self.entry = PyStackEntry(cell_slice=value.to_cs().cell_slice)
else:
raise ValueError(f"Type {type(value)} is not supported")

Expand Down

0 comments on commit 56b4dc6

Please sign in to comment.