Ejemplo n.º 1
0
def _sign_edit_validator(transaction_dict, private_key):
    """
    Sign an edit validator transaction
    See sign_staking_transaction for details
    """
    # preliminary steps
    if transaction_dict['directive'] != Directive.EditValidator:
        raise TypeError('Only EditValidator is supported by _sign_create_or_edit_validator')
    # first common step
    account, sanitized_transaction = _get_account_and_transaction(transaction_dict, private_key)
    # encode the stakeMsg
    description = [
            sanitized_transaction.pop('name'),
            sanitized_transaction.pop('identity'),
            sanitized_transaction.pop('website'),
            sanitized_transaction.pop('security-contact'),
            sanitized_transaction.pop('details'),
        ]
    sanitized_transaction['stakeMsg'] = \
        apply_formatters_to_sequence( [
            hexstr_if_str(to_bytes),        # address
            identity,                       # description
            identity,                       # new rate (it's in a list so can't do hexstr_if_str)
            hexstr_if_str(to_int),          # min self delegation (in ONE), decimals are silently dropped
            hexstr_if_str(to_int),          # max total delegation (in ONE), decimals are silently dropped
            hexstr_if_str(to_bytes),        # key to remove
            hexstr_if_str(to_bytes),        # key to add
        ], [
            convert_one_to_hex(sanitized_transaction.pop('validatorAddress')),
            description,
            [ _convert_staking_percentage_to_number(sanitized_transaction.pop('rate')) ],
            math.floor(sanitized_transaction.pop('min-self-delegation')),       # Decimal floors it correctly
            math.floor(sanitized_transaction.pop('max-total-delegation')),
            sanitized_transaction.pop('bls-key-to-remove'),
            sanitized_transaction.pop('bls-key-to-add')
            ]
        )
    return _sign_transaction_generic(account, sanitized_transaction, EditValidator)
Ejemplo n.º 2
0
def _sign_collect_rewards(transaction_dict, private_key):
    """
    Sign a collect rewards transaction
    See sign_staking_transaction for details
    """
    # preliminary steps
    if transaction_dict['directive'] != Directive.CollectRewards:
        raise TypeError('Only CollectRewards is supported by _sign_collect_rewards')
    # first common step
    account, sanitized_transaction = _get_account_and_transaction(transaction_dict, private_key)
    # encode the stakeMsg
    sanitized_transaction['stakeMsg'] = \
        [hexstr_if_str(to_bytes)(convert_one_to_hex(sanitized_transaction.pop('delegatorAddress')))]
    return _sign_transaction_generic(account, sanitized_transaction, CollectRewards)
Ejemplo n.º 3
0
def _sign_delegate_or_undelegate(transaction_dict, private_key, delegate):
    """
    Sign a delegate or undelegate transaction
    See sign_staking_transaction for details
    """
    # preliminary steps
    if transaction_dict['directive'] not in [ Directive.Delegate, Directive.Undelegate ]:
        raise TypeError('Only Delegate or Undelegate are supported by _sign_delegate_or_undelegate')
    # first common step
    account, sanitized_transaction = _get_account_and_transaction(transaction_dict, private_key)
    # encode the stakeMsg
    sanitized_transaction['stakeMsg'] = \
        apply_formatters_to_sequence( [
            hexstr_if_str(to_bytes),
            hexstr_if_str(to_bytes),
            hexstr_if_str(to_int)
        ], [
            convert_one_to_hex(sanitized_transaction.pop('delegatorAddress')),
            convert_one_to_hex(sanitized_transaction.pop('validatorAddress')),
            sanitized_transaction.pop('amount'),
            ]
        )
    return _sign_transaction_generic(account, sanitized_transaction, DelegateOrUndelegate)
Ejemplo n.º 4
0
 def _recover_hash(self, message_hash, vrs=None, signature=None):
     hash_bytes = HexBytes(message_hash)
     if len(hash_bytes) != 32:
         raise ValueError("The message hash must be exactly 32-bytes")
     if vrs is not None:
         v, r, s = map(hexstr_if_str(to_int), vrs)
         v_standard = to_standard_v(v)
         signature_obj = self._keys.Signature(vrs=(v_standard, r, s))
     elif signature is not None:
         signature_bytes = HexBytes(signature)
         signature_bytes_standard = to_standard_signature_bytes(signature_bytes)
         signature_obj = self._keys.Signature(signature_bytes=signature_bytes_standard)
     else:
         raise TypeError("You must supply the vrs tuple or the signature bytes")
     pubkey = signature_obj.recover_public_key_from_msg_hash(hash_bytes)
     return pubkey.to_checksum_address()
Ejemplo n.º 5
0
 def from_dict(cls, dictionary: Dict[str, Any]):
     """Builds a TypedTransaction from a dictionary. Verifies the dictionary is well formed."""
     dictionary = set_transaction_type_if_needed(dictionary)
     if not ('type' in dictionary and is_int_or_prefixed_hexstr(dictionary['type'])):
         raise ValueError("missing or incorrect transaction type")
     # Switch on the transaction type to choose the correct constructor.
     transaction_type = pipe(dictionary['type'], hexstr_if_str(to_int))
     transaction: Any
     if transaction_type == AccessListTransaction.transaction_type:
         transaction = AccessListTransaction
     elif transaction_type == DynamicFeeTransaction.transaction_type:
         transaction = DynamicFeeTransaction
     else:
         raise TypeError("Unknown Transaction type: %s" % transaction_type)
     return cls(
         transaction_type=transaction_type,
         transaction=transaction.from_dict(dictionary),
     )
Ejemplo n.º 6
0
def _sign_create_validator(transaction_dict, private_key):
    """
    Sign a create validator transaction
    See sign_staking_transaction for details
    """
    # preliminary steps
    if transaction_dict['directive'] != Directive.CreateValidator:
        raise TypeError('Only CreateValidator is supported by _sign_create_or_edit_validator')
    # first common step
    account, sanitized_transaction = _get_account_and_transaction(transaction_dict, private_key)
    # encode the stakeMsg
    description = [
            sanitized_transaction.pop('name'),
            sanitized_transaction.pop('identity'),
            sanitized_transaction.pop('website'),
            sanitized_transaction.pop('security-contact'),
            sanitized_transaction.pop('details'),
        ]
    commission = apply_formatter_to_array( hexstr_if_str(to_int),       # formatter
        [
            _convert_staking_percentage_to_number(sanitized_transaction.pop('rate')),
            _convert_staking_percentage_to_number(sanitized_transaction.pop('max-rate')),
            _convert_staking_percentage_to_number(sanitized_transaction.pop('max-change-rate')),
        ]
    )
    commission = [ [element] for element in commission ]
    bls_keys = apply_formatter_to_array( hexstr_if_str(to_bytes),       # formatter
        sanitized_transaction.pop('bls-public-keys')
    )
    sanitized_transaction['stakeMsg'] = \
        apply_formatters_to_sequence( [
            hexstr_if_str(to_bytes),        # address
            identity,                       # description
            identity,                       # commission rates
            hexstr_if_str(to_int),          # min self delegation (in ONE), decimals are silently dropped
            hexstr_if_str(to_int),          # max total delegation (in ONE), decimals are silently dropped
            identity,                       # bls public keys
            hexstr_if_str(to_int),          # amount (the Hexlify in the SDK drops the decimals, which is what we will do too)
        ], [
            convert_one_to_hex(sanitized_transaction.pop('validatorAddress')),
            description,
            commission,
            math.floor(sanitized_transaction.pop('min-self-delegation')),       # Decimal floors it correctly
            math.floor(sanitized_transaction.pop('max-total-delegation')),
            bls_keys,
            math.floor(sanitized_transaction.pop('amount')),
            ]
        )
    return _sign_transaction_generic(account, sanitized_transaction, CreateValidator)
Ejemplo n.º 7
0
        return False


def is_none(val):
    return val is None


TRANSACTION_DEFAULTS = {
    'to': b'',
    'value': 0,
    'data': b'',
}

TRANSACTION_FORMATTERS = {
    'nonce':
    hexstr_if_str(to_int),
    'gasPrice':
    hexstr_if_str(to_int),
    'gas':
    hexstr_if_str(to_int),
    'to':
    apply_one_of_formatters((
        (is_string, hexstr_if_str(to_bytes)),
        (is_bytes, identity),
        (is_none, lambda val: b''),
    )),
    'value':
    hexstr_if_str(to_int),
    'data':
    hexstr_if_str(to_bytes),
    'v':
Ejemplo n.º 8
0
            return 0
        else:
            return int(value, 16)
    else:
        return int(value)


@functools.lru_cache(maxsize=128)
def normalize_to_address(value: AnyStr) -> Address:
    if value:
        return to_canonical_address(value)
    else:
        return CREATE_CONTRACT_ADDRESS


robust_decode_hex = hexstr_if_str(to_bytes)


#
# Containers
#
def dict_normalizer(formatters: Dict[Any, Callable[..., Any]],
                    required: Iterable[Any]=None,
                    optional: Iterable[Any]=None) -> Normalizer:

    all_keys = set(formatters.keys())

    if required is None and optional is None:
        required_set_form = all_keys
    elif required is not None and optional is not None:
        raise ValueError("Both required and optional keys specified")
Ejemplo n.º 9
0
def _mk_raw_params(**kwargs):
    return {
        'genesis': merge(PARAMS_DEFAULTS, valmap(hexstr_if_str(to_hex), kwargs)),
    }
Ejemplo n.º 10
0
from eth_account._utils.signing import (sign_transaction_hash)

from eth_account._utils.transactions import (
    Transaction as SignedEthereumTxData, UnsignedTransaction as
    UnsignedEthereumTxData, TRANSACTION_FORMATTERS as ETHEREUM_FORMATTERS,
    TRANSACTION_DEFAULTS, chain_id_to_v, UNSIGNED_TRANSACTION_FIELDS)

from cytoolz import (dissoc, pipe, merge, partial)

from eth_account.datastructures import (SignedTransaction)

from .util import (chain_id_to_int, convert_one_to_hex)

HARMONY_FORMATTERS = dict(
    ETHEREUM_FORMATTERS,
    shardID=hexstr_if_str(to_int),  # additional fields for Harmony transaction
    toShardID=hexstr_if_str(to_int),  # which may be cross shard
)


class UnsignedHarmonyTxData(HashableRLP):
    fields = (
        ('nonce', big_endian_int),
        ('gasPrice', big_endian_int),
        ('gas', big_endian_int),
        ('shardID', big_endian_int),
        ('toShardID', big_endian_int),
        ('to', Binary.fixed_length(20, allow_empty=True)),
        ('value', big_endian_int),
        ('data', binary),
    )
Ejemplo n.º 11
0
    def recoverHash(self, message_hash, vrs=None, signature=None):
        '''
        Get the address of the account that signed the message with the given hash.
        You must specify exactly one of: vrs or signature

        :param message_hash: the hash of the message that you want to verify
        :type message_hash: hex str or bytes or int
        :param vrs: the three pieces generated by an elliptic curve signature
        :type vrs: tuple(v, r, s), each element is hex str, bytes or int
        :param signature: signature bytes concatenated as r+s+v
        :type signature: hex str or bytes or int
        :returns: address of signer, hex-encoded & checksummed
        :rtype: str

        .. code-block:: python

            >>> msg = "I♥SF"
            >>> msghash = '0x1476abb745d423bf09273f1afd887d951181d25adc66c4834a70491911b7f750'
            >>> vrs = (
                  28,
                  '0xe6ca9bba58c88611fad66a6ce8f996908195593807c4b38bd528d2cff09d4eb3',
                  '0x3e5bfbbf4d3e39b1a2fd816a7680c19ebebaf3a141b239934ad43cb33fcec8ce')
            >>> Account.recoverHash(msghash, vrs=vrs)
            '0x5ce9454909639D2D17A3F753ce7d93fa0b9aB12E'

            # All of these recover calls are equivalent:

            # variations on msghash
            >>> msghash = b"\\x14v\\xab\\xb7E\\xd4#\\xbf\\t'?\\x1a\\xfd\\x88}\\x95\\x11\\x81\\xd2Z\\xdcf\\xc4\\x83JpI\\x19\\x11\\xb7\\xf7P"  # noqa: E501
            >>> Account.recoverHash(msghash, vrs=vrs)
            >>> msghash = 0x1476abb745d423bf09273f1afd887d951181d25adc66c4834a70491911b7f750
            >>> Account.recoverHash(msghash, vrs=vrs)

            # variations on vrs
            >>> vrs = (
                  '0x1c',
                  '0xe6ca9bba58c88611fad66a6ce8f996908195593807c4b38bd528d2cff09d4eb3',
                  '0x3e5bfbbf4d3e39b1a2fd816a7680c19ebebaf3a141b239934ad43cb33fcec8ce')
            >>> Account.recoverHash(msghash, vrs=vrs)
            >>> vrs = (
                  b'\\x1c',
                  b'\\xe6\\xca\\x9b\\xbaX\\xc8\\x86\\x11\\xfa\\xd6jl\\xe8\\xf9\\x96\\x90\\x81\\x95Y8\\x07\\xc4\\xb3\\x8b\\xd5(\\xd2\\xcf\\xf0\\x9dN\\xb3',  # noqa: E501
                  b'>[\\xfb\\xbfM>9\\xb1\\xa2\\xfd\\x81jv\\x80\\xc1\\x9e\\xbe\\xba\\xf3\\xa1A\\xb29\\x93J\\xd4<\\xb3?\\xce\\xc8\\xce')  # noqa: E501
            >>> Account.recoverHash(msghash, vrs=vrs)
            >>> vrs = (
                  0x1c,
                  0xe6ca9bba58c88611fad66a6ce8f996908195593807c4b38bd528d2cff09d4eb3,
                  0x3e5bfbbf4d3e39b1a2fd816a7680c19ebebaf3a141b239934ad43cb33fcec8ce)
            >>> Account.recoverHash(msghash, vrs=vrs)

            # variations on signature
            >>> signature = '0xe6ca9bba58c88611fad66a6ce8f996908195593807c4b38bd528d2cff09d4eb33e5bfbbf4d3e39b1a2fd816a7680c19ebebaf3a141b239934ad43cb33fcec8ce1c'  # noqa: E501
            >>> Account.recoverHash(msghash, signature=signature)
            >>> signature = b'\\xe6\\xca\\x9b\\xbaX\\xc8\\x86\\x11\\xfa\\xd6jl\\xe8\\xf9\\x96\\x90\\x81\\x95Y8\\x07\\xc4\\xb3\\x8b\\xd5(\\xd2\\xcf\\xf0\\x9dN\\xb3>[\\xfb\\xbfM>9\\xb1\\xa2\\xfd\\x81jv\\x80\\xc1\\x9e\\xbe\\xba\\xf3\\xa1A\\xb29\\x93J\\xd4<\\xb3?\\xce\\xc8\\xce\\x1c'  # noqa: E501
            >>> Account.recoverHash(msghash, signature=signature)
            >>> signature = 0xe6ca9bba58c88611fad66a6ce8f996908195593807c4b38bd528d2cff09d4eb33e5bfbbf4d3e39b1a2fd816a7680c19ebebaf3a141b239934ad43cb33fcec8ce1c  # noqa: E501
            >>> Account.recoverHash(msghash, signature=signature)
        '''
        hash_bytes = HexBytes(message_hash)
        if len(hash_bytes) != 32:
            raise ValueError("The message hash must be exactly 32-bytes")
        if vrs is not None:
            v, r, s = map(hexstr_if_str(to_int), vrs)
            v_standard = to_standard_v(v)
            signature_obj = self._keys.Signature(vrs=(v_standard, r, s))
        elif signature is not None:
            signature_bytes = HexBytes(signature)
            signature_bytes_standard = to_standard_signature_bytes(
                signature_bytes)
            signature_obj = self._keys.Signature(
                signature_bytes=signature_bytes_standard)
        else:
            raise TypeError(
                "You must supply the vrs tuple or the signature bytes")
        pubkey = signature_obj.recover_public_key_from_msg_hash(hash_bytes)
        return pubkey.to_checksum_address()
Ejemplo n.º 12
0
from .transaction_utils import (
    set_transaction_type_if_needed,
    transaction_rlp_to_rpc_structure,
    transaction_rpc_to_rlp_structure,
)
from .validation import (
    LEGACY_TRANSACTION_FORMATTERS,
    LEGACY_TRANSACTION_VALID_VALUES,
    is_int_or_prefixed_hexstr,
    is_rpc_structured_access_list,
)

TYPED_TRANSACTION_FORMATTERS = merge(
    LEGACY_TRANSACTION_FORMATTERS, {
        'chainId': hexstr_if_str(to_int),
        'type': hexstr_if_str(to_int),
        'accessList': apply_formatter_to_array(
            apply_formatters_to_dict(
                {
                    "address": apply_one_of_formatters((
                        (is_string, hexstr_if_str(to_bytes)),
                        (is_bytes, identity),
                    )),
                    "storageKeys": apply_formatter_to_array(hexstr_if_str(to_int))
                }
            ),
        ),
        'maxPriorityFeePerGas': hexstr_if_str(to_int),
        'maxFeePerGas': hexstr_if_str(to_int),
    },
Ejemplo n.º 13
0

def encode_transaction(unsigned_transaction, vrs):
    (v, r, s) = vrs
    chain_naive_transaction = dissoc(vars(unsigned_transaction), 'v', 'r', 's')
    signed_transaction = Transaction(v=v, r=r, s=s, **chain_naive_transaction)
    return rlp.encode(signed_transaction)


TRANSACTION_DEFAULTS = {
    'value': 0,
    'data': b'',
}

TRANSACTION_FORMATTERS = {
    'nonce': hexstr_if_str(to_int),
    'gasPrice': hexstr_if_str(to_int),
    'gas': hexstr_if_str(to_int),
    'to': hexstr_if_str(to_bytes),
    'value': hexstr_if_str(to_int),
    'data': hexstr_if_str(to_bytes),
    'v': hexstr_if_str(to_int),
    'r': hexstr_if_str(to_int),
    's': hexstr_if_str(to_int),
}


def chain_id_to_v(transaction_dict):
    # See EIP 155
    chain_id = transaction_dict.pop('chainId')
    if chain_id is None:
Ejemplo n.º 14
0
        return False


def is_none(val):
    return val is None


TRANSACTION_DEFAULTS = {
    'to': b'',
    'value': 0,
    'data': b'',
    'chainId': None,
}

TRANSACTION_FORMATTERS = {
    'nonce': hexstr_if_str(to_int),
    'gasPrice': hexstr_if_str(to_int),
    'gas': hexstr_if_str(to_int),
    'to': apply_one_of_formatters((
        (is_string, hexstr_if_str(to_bytes)),
        (is_bytes, identity),
        (is_none, lambda val: b''),
    )),
    'value': hexstr_if_str(to_int),
    'data': hexstr_if_str(to_bytes),
    'v': hexstr_if_str(to_int),
    'r': hexstr_if_str(to_int),
    's': hexstr_if_str(to_int),
}

TRANSACTION_VALID_VALUES = {
Ejemplo n.º 15
0
class Directive(
        Enum
):  # https://github.com/harmony-one/sdk/blob/99a827782fabcd5f91f025af0d8de228956d42b4/packages/harmony-staking/src/stakingTransaction.ts#L120
    def _generate_next_value_(name, start, count, last_values):
        return count

    CreateValidator = auto()
    EditValidator = auto()
    Delegate = auto()
    Undelegate = auto()
    CollectRewards = auto()


FORMATTERS = {
    'directive': hexstr_if_str(
        to_int),  # delegatorAddress is already formatted before the call
    'nonce': hexstr_if_str(to_int),
    'gasPrice': hexstr_if_str(to_int),
    'gasLimit': hexstr_if_str(to_int),
    'chainId': hexstr_if_str(to_int),
}


class CollectRewards:
    @staticmethod
    def UnsignedChainId():
        class UnsignedChainId(HashableRLP):
            fields = (
                ('directive', big_endian_int),
                ('stakeMsg',
                 CountableList(Binary.fixed_length(20, allow_empty=True))),
Ejemplo n.º 16
0
            return 0
        else:
            return int(value, 16)
    else:
        return int(value)


@functools.lru_cache(maxsize=128)
def normalize_to_address(value):
    if value:
        return to_canonical_address(value)
    else:
        return CREATE_CONTRACT_ADDRESS


robust_decode_hex = hexstr_if_str(to_bytes)


#
# Pytest fixture generation
#
def idfn(fixture_params):
    """
    Function for pytest to produce uniform names for fixtures.
    """
    return ":".join((str(item) for item in fixture_params))


def get_fixtures_file_hash(all_fixture_paths):
    """
    Returns the MD5 hash of the fixture files.  Used for cache busting.