Skip to content

Commit

Permalink
Merge branch 'development' into script_container
Browse files Browse the repository at this point in the history
  • Loading branch information
ixje authored Aug 24, 2024
2 parents 37bfa8b + f304688 commit 7263874
Show file tree
Hide file tree
Showing 1,691 changed files with 10,035 additions and 3,373 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,4 @@ jobs:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
OPENAI_API_MODEL: "gpt-4" # Optional: defaults to "gpt-4"
exclude: "**/*.json, **/*.md" # Optional: exclude patterns separated by commas
exclude: "**/*.json, **/*.md" # Optional: exclude patterns separated by commas
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0


### Deprecated
- Deprecated @metadata decorator to identify metadata function.


### Removed
- Dropped support to Python 3.10


### Fixed
Expand Down
2 changes: 2 additions & 0 deletions boa3/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,5 @@

logging.basicConfig(format='%(levelname)s: %(message)s', level=logging.DEBUG)
__version__ = '1.2.1'

__boa3_builtin_deprecate_version__ = '1.3.0'
255 changes: 7 additions & 248 deletions boa3/builtin/compile_time/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,12 @@
'NeoMetadata',
]

from typing import Any

from boa3.builtin.type import Event
from boa3.internal.deprecation import deprecated
from boa3.sc.compiletime import NeoMetadata


@deprecated(details='This module is deprecated. Use :mod:`boa3.sc.utils` instead')
def CreateNewEvent(arguments: list[tuple[str, type]] = [], event_name: str = '') -> Event:
"""
Creates a new Event.
Expand All @@ -31,11 +32,12 @@ def CreateNewEvent(arguments: list[tuple[str, type]] = [], event_name: str = '')
:param event_name: custom name of the event. It's filled with the variable name if not specified
:type event_name: str
:return: the new event
:rtype: Event
:rtype: boa3.builtin.type.Event
"""
pass


@deprecated(details='This module is deprecated. Use :mod:`boa3.sc.compiletime` instead')
def public(name: str = None, safe: bool = False, *args, **kwargs):
"""
This decorator identifies which methods should be included in the abi file. Adding this decorator to a function
Expand Down Expand Up @@ -85,6 +87,7 @@ def decorator_wrapper(*args, **kwargs):
return decorator_wrapper


@deprecated(details='This module is deprecated. Use :mod:`boa3.sc.compiletime` instead')
def contract(script_hash: str | bytes):
"""
This decorator identifies a class that should be interpreted as an interface to an existing contract.
Expand Down Expand Up @@ -125,6 +128,7 @@ def decorator_wrapper(cls, *args, **kwargs):
return decorator_wrapper


@deprecated(details='This module is deprecated. Use :mod:`boa3.sc.compiletime` instead')
def display_name(name: str):
"""
This decorator identifies which methods from a contract interface should have a different identifier from the one
Expand All @@ -146,248 +150,3 @@ def display_name(name: str):
def decorator_wrapper(*args, **kwargs):
pass
return decorator_wrapper


class NeoMetadata:
"""
This class stores the smart contract manifest information.
Check out `Neo's Documentation <https://developers.neo.org/docs/n3/develop/write/manifest>`__ to learn more about
the Manifest.
>>> def neo_metadata() -> NeoMetadata:
... meta = NeoMetadata()
... meta.name = 'NewContractName'
... meta.add_permission(methods=['onNEP17Payment'])
... meta.add_trusted_source("0x1234567890123456789012345678901234567890")
... meta.date = "2023/05/30" # this property will end up inside the extra property
... return meta
:ivar name: the smart contract name. Will be the name of the file by default;
:vartype type name: str
:ivar supported_standards: Neo standards supported by this smart contract. Empty by default;
:vartype supported_standards: list[str]
:ivar permissions: a list of contracts and methods that this smart contract permits to invoke and call. All
contracts and methods permitted by default;
:vartype permissions: list[str]
:ivar trusts: a list of contracts that this smart contract trust. Empty by default;
:vartype trusts: list[str]
:ivar author: the smart contract author. None by default;
:vartype author: str or None
:ivar email: the smart contract author email. None by default;
:vartype email: str or None
:ivar description: the smart contract description. None by default;
:vartype description: str or None
"""
from boa3.internal.constants import IMPORT_WILDCARD

def __init__(self):
self.name: str = ''
self.source: str | None = None
self.supported_standards: list[str] = []
self._trusts: list[str] = []
self._permissions: list[dict] = []
self._groups: list[dict] = []

@property
def extras(self) -> dict[str, Any]:
"""
Gets the metadata extra information.
:return: a dictionary that maps each extra value with its name. Empty by default
"""
# list the variables names that are part of the manifest
specific_field_names = ['name',
'source',
'supported_standards',
]
extra = {}

for var_name, var_value in vars(self).items():
if var_name in specific_field_names:
continue

if var_value is not None and not var_name.startswith('_'):
extra_field = var_name.title().replace('_', '')
extra[extra_field] = var_value

return extra

@property
def trusts(self) -> list[str]:
from boa3.internal.constants import IMPORT_WILDCARD
if self._trusts == [IMPORT_WILDCARD]:
return IMPORT_WILDCARD
return self._trusts.copy()

@property
def permissions(self) -> list[dict]:
return self._permissions.copy()

@property
def groups(self) -> list[dict]:
return self._groups.copy()

def add_trusted_source(self, hash_or_address: str):
"""
Adds a valid contract hash, valid group public key, or the '*' wildcard to trusts.
>>> self.add_trusted_source("0x1234567890123456789012345678901234abcdef")
>>> self.add_trusted_source("035a928f201639204e06b4368b1a93365462a8ebbff0b8818151b74faab3a2b61a")
>>> self.add_trusted_source("*")
:param hash_or_address: a contract hash, group public key or '*'
:type hash_or_address: str
"""
if not isinstance(hash_or_address, str):
return

from boa3.internal.constants import IMPORT_WILDCARD
if self._trusts == [IMPORT_WILDCARD]:
return

if hash_or_address == IMPORT_WILDCARD:
self._trusts = [IMPORT_WILDCARD]

# verifies if it's a valid contract hash
elif self._verify_is_valid_contract_hash(hash_or_address):
if hash_or_address not in self._trusts:
self._trusts.append(hash_or_address.lower())

# verifies if it's a valid public key
elif self._verify_is_valid_public_key(hash_or_address):
if hash_or_address not in self._trusts:
self._trusts.append(hash_or_address.lower())

def add_group(self, pub_key: str, signature: str):
"""
Adds a pair of public key and signature to the groups in the manifest.
>>> self.add_group("031f64da8a38e6c1e5423a72ddd6d4fc4a777abe537e5cb5aa0425685cda8e063b",
... "fhsOJNF3N5Pm3oV1b7wYTx0QVelYNu7whwXMi8GsNGFKUnu3ZG8z7oWLfzzEz9pbnzwQe8WFCALEiZhLD1jG/w==")
:param pub_key: public key of the group
:type pub_key: str
:param signature: signature of the contract hash encoded in Base64
:type signature: str
"""

if not isinstance(pub_key, str) or not isinstance(signature, str):
return

# verifies if pub_key is a valid value
if not self._verify_is_valid_public_key(pub_key):
return

new_group = {
'pubkey': pub_key.lower(),
'signature': signature,
}

if new_group not in self._permissions:
self._groups.append(new_group)

def add_permission(self, *, contract: str = IMPORT_WILDCARD,
methods: list[str] | str | tuple[str, ...] = IMPORT_WILDCARD):
"""
Adds a valid contract and a valid methods to the permissions in the manifest.
>>> self.add_permission(methods=['onNEP17Payment'])
>>> self.add_permission(contract='0x3846a4aa420d9831044396dd3a56011514cd10e3', methods=['get_object'])
>>> self.add_permission(contract='0333b24ee50a488caa5deec7e021ff515f57b7993b93b45d7df901e23ee3004916')
:param contract: a contract hash, group public key or '*'
:type contract: str
:param methods: a list of methods or '*'
:type methods: list[str] or str
"""

if isinstance(contract, bytes):
try:
from boa3.internal.neo3.core.types import UInt160
contract = str(UInt160(contract))
except BaseException:
pass

if not isinstance(contract, str):
return

if not isinstance(methods, (str, list, tuple)):
return

from boa3.internal.constants import IMPORT_WILDCARD
# verifies if contract is a valid value
if (not self._verify_is_valid_contract_hash(contract) and
not self._verify_is_valid_public_key(contract) and
contract != IMPORT_WILDCARD):
return

# verifies if methods is a valid value
elif isinstance(methods, (tuple, list)) and (any(not isinstance(method, str) for method in methods) or len(methods) == 0):
return

from boa3.internal import constants
wildcard_permission = {
'contract': constants.IMPORT_WILDCARD,
'methods': constants.IMPORT_WILDCARD,
}

# verifies if method contains wildcard
if isinstance(methods, (tuple, list)):
# if any of the elements in the tuple is the wildcard
if constants.IMPORT_WILDCARD in methods:
methods = constants.IMPORT_WILDCARD
else:
methods = list(methods)
# if it's a single str and not wildcard, add to a list
elif isinstance(methods, str) and methods != constants.IMPORT_WILDCARD:
methods = [methods]

if wildcard_permission not in self._permissions:
new_permission = {
'contract': contract.lower(),
'methods': methods,
}

if contract == constants.IMPORT_WILDCARD and methods == constants.IMPORT_WILDCARD:
self._permissions.clear()
self._permissions.append(wildcard_permission)
elif new_permission not in self._permissions:
self._permissions.append(new_permission)

@staticmethod
def _verify_is_valid_public_key(public_key: str) -> bool:
"""
Verifies if a given compressed public key is valid.
:return: whether the given public key is valid or not
"""
if public_key.startswith('03') or public_key.startswith('02'):
try:
from boa3.internal import constants
if len(bytes.fromhex(public_key)) == constants.SIZE_OF_ECPOINT:
return True
except ValueError:
pass
return False

@staticmethod
def _verify_is_valid_contract_hash(contract_hash: str) -> bool:
"""
Verifies if a given contract hash is valid.
:return: whether the given contract hash is valid or not
"""
if contract_hash.startswith('0x'):
try:
from boa3.internal.neo3.core.types import UInt160
# if contract_hash is not a valid UInt160, it will raise a ValueError
UInt160.from_string(contract_hash[2:])
return True
except ValueError:
pass
return False
2 changes: 2 additions & 0 deletions boa3/builtin/contract/Nep17Contract.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@

from boa3.builtin.interop.contract import Contract
from boa3.builtin.type import UInt160
from boa3.internal.deprecation import deprecated


@deprecated(details='This module is deprecated. Use :mod:`boa3.sc.types` instead')
class Nep17Contract(Contract):
def symbol(self) -> str:
pass
Expand Down
7 changes: 6 additions & 1 deletion boa3/builtin/contract/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
from boa3.builtin.compile_time import CreateNewEvent
from boa3.builtin.contract.Nep17Contract import Nep17Contract
from boa3.builtin.type import ECPoint, UInt160, Event
from boa3.internal.deprecation import deprecated

Nep11TransferEvent: Event = CreateNewEvent(
[
Expand Down Expand Up @@ -78,6 +79,7 @@
"""


@deprecated(details='This module is deprecated. Use :mod:`boa3.sc.utils` instead')
def abort(msg: str | None = None):
"""
Aborts the execution of a smart contract. Using this will cancel the changes made on the blockchain by the
Expand All @@ -93,6 +95,7 @@ def abort(msg: str | None = None):
pass


@deprecated(details='This module is deprecated. Use :mod:`boa3.sc.types` instead')
class NeoAccountState:
"""
Represents the account state of NEO token in the NEO system.
Expand All @@ -102,7 +105,7 @@ class NeoAccountState:
:ivar height: the height of the block where the balance changed last time
:vartype height: int
:ivar vote_to: the voting target of the account
:vartype vote_to: ECPoint
:vartype vote_to: boa3.builtin.type.ECPoint
"""

def __init__(self):
Expand All @@ -113,6 +116,7 @@ def __init__(self):
self.last_gas_per_vote: int = 0


@deprecated(details='This module is deprecated. Use :mod:`boa3.sc.utils` instead')
def to_script_hash(data_bytes: Any) -> bytes:
"""
Converts a data to a script hash.
Expand All @@ -131,6 +135,7 @@ def to_script_hash(data_bytes: Any) -> bytes:
pass


@deprecated(details='This module is deprecated. Use :mod:`boa3.sc.utils` instead')
def to_hex_str(data: bytes) -> str:
"""
Converts bytes into its string hex representation.
Expand Down
Loading

0 comments on commit 7263874

Please sign in to comment.