Skip to content
This repository has been archived by the owner on Aug 12, 2024. It is now read-only.

Commit

Permalink
feat: update compatiblity range to LIMA series (#355)
Browse files Browse the repository at this point in the history
* update compatiblity range to LIMA series
* remove obsolete tests
* remove legacy checks
* restore previously skipped test

BREAKING CHANGE:
- remove suport for node v < v5.0.0
- remove support for compiler v <  v4.0.0
  • Loading branch information
noandrea authored Jan 30, 2020
1 parent 1f21bcb commit 154cde7
Show file tree
Hide file tree
Showing 11 changed files with 123 additions and 294 deletions.
4 changes: 2 additions & 2 deletions aeternity/__init__.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import pkg_resources
import logging

__node_compatibility__ = (">=3.0.1", "<=6.0.0")
__compiler_compatibility__ = (">=3.2.0", "<5.0.0")
__node_compatibility__ = (">=5.0.0", "<=6.0.0")
__compiler_compatibility__ = (">=4.1.0", "<5.0.0")

# initialize logging
logging.basicConfig(level=logging.ERROR)
Expand Down
4 changes: 1 addition & 3 deletions aeternity/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

from aeternity.node import NodeClient, Config
from aeternity.transactions import TxSigner, TxBuilder, TxObject
from aeternity.identifiers import NETWORK_ID_MAINNET, PROTOCOL_LIMA # TODO: remove after HF
from aeternity.identifiers import NETWORK_ID_MAINNET
from . import utils, signing, aens, defaults, exceptions
from aeternity.compiler import CompilerClient
from aeternity.openapi import OpenAPIClientException
Expand Down Expand Up @@ -548,8 +548,6 @@ def name_bid(keystore_name, domain, name_fee, ttl, fee, nonce, password, force,
try:
set_global_options(json_, force, wait)
account, _ = _account(keystore_name, password=password)
if _node_cli().get_consensus_protocol_version() < PROTOCOL_LIMA:
raise TypeError(f"Name auctions are not supported in protocol before LIMA ({PROTOCOL_LIMA})")
name = _node_cli().AEName(domain)
name.update_status()
if name.status != aens.AEName.Status.AVAILABLE:
Expand Down
15 changes: 5 additions & 10 deletions aeternity/aens.py
Original file line number Diff line number Diff line change
Expand Up @@ -240,8 +240,6 @@ def claim(self, preclaim_tx_hash, account, name_salt,
self.preclaimed_block_height = pre_claim_tx.block_height
except OpenAPIClientException:
raise MissingPreclaim(f"Pre-claim transaction {preclaim_tx_hash} not found")
# first get the protocol version
protocol = self.client.get_consensus_protocol_version()
# if the commitment_id mismatch
pre_claim_commitment_id = pre_claim_tx.tx.commitment_id
commitment_id, _ = hashing.commitment_id(self.domain, salt=name_salt)
Expand All @@ -261,14 +259,11 @@ def claim(self, preclaim_tx_hash, account, name_salt,
nonce, ttl = self.client._get_nonce_ttl(account.get_address(), tx_ttl)
# create transaction
# check the protocol version
if protocol < identifiers.PROTOCOL_LIMA:
tx = txb.tx_name_claim(account.get_address(), self.domain, self.preclaim_salt, fee, ttl, nonce)
else:
min_name_fee = AEName.get_minimum_name_fee(self.domain)
if name_fee != defaults.NAME_FEE and name_fee < min_name_fee:
raise TypeError(f"the provided fee {name_fee} is not enough to execute the claim, required: {min_name_fee}")
name_fee = max(min_name_fee, name_fee)
tx = txb.tx_name_claim_v2(account.get_address(), self.domain, self.preclaim_salt, name_fee, fee, ttl, nonce)
min_name_fee = AEName.get_minimum_name_fee(self.domain)
if name_fee != defaults.NAME_FEE and name_fee < min_name_fee:
raise TypeError(f"the provided fee {name_fee} is not enough to execute the claim, required: {min_name_fee}")
name_fee = max(min_name_fee, name_fee)
tx = txb.tx_name_claim_v2(account.get_address(), self.domain, self.preclaim_salt, name_fee, fee, ttl, nonce)
# sign the transaction
tx_signed = self.client.sign_transaction(account, tx)
# post the transaction to the chain
Expand Down
9 changes: 3 additions & 6 deletions aeternity/compiler.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,19 +15,16 @@ class CompilerError(exceptions.AException):

class CompilerClient(object):
"""
The compiler client Fate version is the client for the aesophia_http compiler v4.x.x series,
that is compatible with LIMA protocol (v4)
The compiler client to interact with the aeternity http compiler
"""

def __init__(self, compiler_url='http://localhost:3080', **kwargs):
self.compiler_url = compiler_url
self.compiler_cli = openapi.OpenAPICli(compiler_url, compatibility_version_range=__compiler_compatibility__)
# chec the compatibiity node protocol
self.target_protocol = identifiers.PROTOCOL_LIMA if semver.match(self.compiler_cli.version().version, ">3.9.9") else identifiers.PROTOCOL_FORTUNA
# default backend set to FATE
self.compiler_options = {
"backend": kwargs.get("backend", identifiers.COMPILER_OPTIONS_BACKEND_FATE)
}
if self.target_protocol >= identifiers.PROTOCOL_LIMA:
self.set_option("backend", kwargs.get("backend", identifiers.COMPILER_OPTIONS_BACKEND_FATE))

def set_option(self, name, value):
self.compiler_options[name] = value
Expand Down
134 changes: 81 additions & 53 deletions aeternity/hashing.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
import rlp
import secrets
import math
from deprecated import deprecated

from nacl.hash import blake2b
from nacl.encoding import RawEncoder
Expand Down Expand Up @@ -105,7 +104,7 @@ def decode(data: str) -> bytes:

def encode_rlp(prefix: str, data: list) -> str:
"""
Encode a data
Encode input data into rlp + the encoding defined for the prefix
Args:
prefix(str): the prefix to use when encoding the rlp to string
Expand All @@ -121,60 +120,57 @@ def encode_rlp(prefix: str, data: list) -> str:
return encode(prefix, payload)


def decode_rlp(data):
def decode_rlp(data: str) -> list:
"""
Decode an rlp/b2b message to a list
:param data: the encoded string to decode
Args:
the encoded prefixed sting
Returns:
the raw data contained in the rlp message
"""
rlp_enc = decode(data)
return rlp.decode(rlp_enc)


def hash(data):
"""run the default hashing algorithm"""
return _blake2b_digest(data)

def hash(data: bytes) -> bytes:
"""
Compute the hash of the input data using the default algorithm
def hash_encode(prefix, data):
"""run the default hashing + digest algorithms"""
return encode(prefix, hash(data))
Args:
data(bytes): the data to hash
Returns:
the hash of the input data
"""
return _blake2b_digest(data)


@deprecated(version="5.0.0", reason="changes in the protocol from lima release. use name_id(name: str) instead.")
def namehash(name: str):
if isinstance(name, str):
name = name.lower().encode('ascii')
# see:
# https://github.com/aeternity/protocol/blob/master/AENS.md#hashing
# and also:
# https://github.com/ethereum/EIPs/blob/master/EIPS/eip-137.md#namehash-algorithm
labels = name.split(b'.')
hashed = b'\x00' * 32
while labels:
hashed = hash(hashed + hash(labels[0]))
labels = labels[1:]
return hashed
def hash_encode(prefix: str, data: bytes) -> str:
"""
Compute the hash of the input data and encode the
result with the encoding mapped for the prefix
Args:
prefix(str): the prefix for the data
data(bytes): the bytes for the input data
Returns:
a string composed by the prefix and the encoded hash
@deprecated(version="5.0.0", reason="will not be necessary from lima release")
def namehash_encode(prefix, name):
"""
Encode the namehash to
"""
return encode(prefix, namehash(name))
return encode(prefix, hash(data))


def commitment_id(domain: str, salt: int = None) -> tuple:
"""
Compute the commitment id, the computed id will be different for .test (pre lima) and .chain domains
:param domain: the domain for which the commitment_id has to be generated
:param salt: the salt to use, if not provided it is randomly generated
Compute the commitment id used in AENS pre-claim transactions
Args:
domain(str): the domain for which the commitment_id has to be generated
salt(int): the salt to use, if not provided it is randomly generated
Returns:
a tuple containing the commitment_id and the salt used to generate the commitment_id
"""
name_salt = randint() if salt is None else salt
if domain.endswith(".chain"):
commitment_id = hash_encode(identifiers.COMMITMENT_ID, domain.lower().encode('ascii') + _int(name_salt, 32))
else:
commitment_id = hash_encode(identifiers.COMMITMENT_ID, namehash(domain) + _int(name_salt, 32))
commitment_id = hash_encode(identifiers.COMMITMENT_ID, domain.lower().encode('utf8') + _int(name_salt, 32))
return commitment_id, name_salt


Expand Down Expand Up @@ -255,46 +251,78 @@ def _id_decode(data):
return encode(prefix, data[1:])


def name_id(name: str):
def name_id(name: str) -> str:
"""
Encode a domain name
:param name: the domain name to encode
Args:
name(str): the domain name to encode
Returns:
the encoded and prefixed name hash
"""
if name.endswith('.chain'):
return encode(identifiers.NAME_ID, hash(name.lower().encode('ascii')))
return encode(identifiers.NAME_ID, namehash(name))
return encode(identifiers.NAME_ID, hash(name.lower().encode('utf8')))


def contract_id(owner_id, nonce):
def contract_id(owner_id: str, nonce: int) -> str:
"""
Compute the contract id of a contract
:param owner_id: the account creating the contract
:param nonce: the nonce of the contract creation transaction
Args:
owner_id(str): the account creating the contract
nonce(int): the nonce of the contract creation transaction
Returns:
the computed contract_id
"""
return hash_encode(identifiers.CONTRACT_ID, decode(owner_id) + _int(nonce))


def oracle_id(account_id):
def oracle_id(account_id: str) -> str:
"""
Compute the oracle id of a oracle registration
:parm account_id: the account registering the oracle
Args:
account_id(str): the account registering the oracle
Returns:
the computed oracle_id
"""
return f"{identifiers.ORACLE_ID}_{account_id[3:]}"


def oracle_query_id(sender_id, nonce, oracle_id):
def oracle_query_id(sender_id: str, nonce: int, oracle_id: str) -> str:
"""
Compute the query id for a sender and an oracle
:param sender_id: the account making the query
:param nonce: the nonce of the query transaction
:param oracle_id: the oracle id
Args:
sender_id(str): the account making the query
nonce(int): the nonce of the query transaction
oracle_id(str): the oracle id
Returns:
the computed oracle_query_id
"""
return hash_encode(identifiers.ORACLE_QUERY_ID, decode(sender_id) + _int(nonce, byte_length=32) + decode(oracle_id))


def randint(upper_bound=2**64):
def randint(upper_bound: int = 2**64):
"""
Generate a cryptographically secure random int between 0 and `upper_bound`
It uses the nacl library to do so
Args:
upper_bound(int): the upper bound of the generated number (default 2**64)
Returns:
a random number
"""
return secrets.randbelow(upper_bound)


def randbytes(size=32):
def randbytes(size: int = 32) -> bytes:
"""
Generate a cryptographically secure random byte sequence of the requested size
It uses the nacl library to do so.
Args:
size(int): the size of the generated byte sequence (default 32)
Returns:
a random byte sequence
"""
return secrets.token_bytes(size)
20 changes: 8 additions & 12 deletions tests/test_aens.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
from aeternity.aens import AEName
from aeternity.identifiers import PROTOCOL_LIMA
from tests.conftest import random_domain
from aeternity.signing import Account

Expand All @@ -19,13 +18,13 @@ def test_name_validation_succeeds(chain_fixture):


def test_name_is_available(chain_fixture):
domain = random_domain(tld='chain' if chain_fixture.NODE_CLI.get_consensus_protocol_version() >= PROTOCOL_LIMA else 'test')
domain = random_domain()
name = chain_fixture.NODE_CLI.AEName(domain)
assert name.is_available()


def test_name_status_available(chain_fixture):
domain = random_domain(length=13 ,tld='chain' if chain_fixture.NODE_CLI.get_consensus_protocol_version() >= PROTOCOL_LIMA else 'test')
domain = random_domain(length=13)
name = chain_fixture.NODE_CLI.AEName(domain)
assert name.status == AEName.Status.UNKNOWN
name.update_status()
Expand All @@ -35,7 +34,7 @@ def test_name_status_available(chain_fixture):
def test_name_claim_lifecycle(chain_fixture):
try:
# avoid auctions
domain = random_domain(length=13 ,tld='chain' if chain_fixture.NODE_CLI.get_consensus_protocol_version() >= PROTOCOL_LIMA else 'test')
domain = random_domain(length=13)
node_cli = chain_fixture.NODE_CLI
name = node_cli.AEName(domain)
assert name.status == AEName.Status.UNKNOWN
Expand All @@ -51,9 +50,6 @@ def test_name_claim_lifecycle(chain_fixture):
assert e is None

def test_name_auction(chain_fixture):
if chain_fixture.NODE_CLI.get_consensus_protocol_version() < PROTOCOL_LIMA:
skip("name auction is only supported after Lima HF")
return
try:
domain = random_domain(length=12)
node_cli = chain_fixture.NODE_CLI
Expand Down Expand Up @@ -86,7 +82,7 @@ def test_name_auction(chain_fixture):

def test_name_status_unavailable(chain_fixture):
# avoid auctions
domain = random_domain(length=13 ,tld='chain' if chain_fixture.NODE_CLI.get_consensus_protocol_version() >= PROTOCOL_LIMA else 'test')
domain = random_domain(length=13)
print(f"domain is {domain}")
occupy_name = chain_fixture.NODE_CLI.AEName(domain)
occupy_name.full_claim_blocking(chain_fixture.ALICE)
Expand All @@ -97,7 +93,7 @@ def test_name_status_unavailable(chain_fixture):

def test_name_update(chain_fixture):
# avoid auctions
domain = random_domain(length=13 ,tld='chain' if chain_fixture.NODE_CLI.get_consensus_protocol_version() >= PROTOCOL_LIMA else 'test')
domain = random_domain(length=13)
print(f"domain is {domain}")
name = chain_fixture.NODE_CLI.AEName(domain)
print("Claim name ", domain)
Expand All @@ -122,7 +118,7 @@ def test_name_update(chain_fixture):

def test_spend_by_name(chain_fixture):
# claim a domain
domain = random_domain(tld='chain' if chain_fixture.NODE_CLI.get_consensus_protocol_version() >= PROTOCOL_LIMA else 'test', length=20)
domain = random_domain(length=20)
print(f"domain is {domain}")
name = chain_fixture.NODE_CLI.AEName(domain)
print("Claim name ", domain)
Expand All @@ -146,7 +142,7 @@ def test_spend_by_name(chain_fixture):

def test_name_transfer_ownership(chain_fixture):
# avoid auctions
domain = random_domain(length=13 ,tld='chain' if chain_fixture.NODE_CLI.get_consensus_protocol_version() >= PROTOCOL_LIMA else 'test')
domain = random_domain(length=13)
name = chain_fixture.NODE_CLI.AEName(domain)
name.full_claim_blocking(chain_fixture.ALICE)
assert name.status == AEName.Status.CLAIMED
Expand All @@ -167,7 +163,7 @@ def test_name_transfer_ownership(chain_fixture):

def test_name_revocation(chain_fixture):
# avoid auctions
domain = random_domain(length=13 ,tld='chain' if chain_fixture.NODE_CLI.get_consensus_protocol_version() >= PROTOCOL_LIMA else 'test')
domain = random_domain(length=13)
name = chain_fixture.NODE_CLI.AEName(domain)
name.full_claim_blocking(chain_fixture.ALICE)
name.revoke(chain_fixture.ALICE)
Expand Down
Loading

0 comments on commit 154cde7

Please sign in to comment.