Beispiel #1
0
    def sign(self, transaction: Any, use_tron: bool = True):
        """Safe method for signing your transaction

        Warnings:
            method: online_sign() - Use only in extreme cases.

        Args:
            transaction (Any): transaction details
            use_tron (bool): is Tron header

        """

        if is_string(transaction):
            if not is_hex(transaction):
                raise TronError('Expected hex message input')

            # Determine which header to attach to the message
            # before encrypting or decrypting
            header = TRX_MESSAGE_HEADER if use_tron else ETH_MESSAGE_HEADER
            header += str(len(transaction))

            message_hash = self.tron.sha3(text=header + transaction)
            signed_message = Account.sign_hash(message_hash,
                                               self.tron.private_key)

            return signed_message

        if 'signature' in transaction:
            raise TronError('Transaction is already signed')

        address = self.tron.address.from_private_key(
            self.tron.private_key).hex.lower()
        owner_address = transaction['raw_data']['contract'][0]['parameter'][
            'value']['owner_address']

        if address != owner_address:
            raise ValueError(
                'Private key does not match address in transaction')

        # This option deals with signing of transactions, and writing to the array
        signed_tx = Account.sign_hash(transaction['txID'],
                                      self.tron.private_key)
        transaction['signature'] = [signed_tx['signature'].hex()[2:]]
        return transaction
Beispiel #2
0
    def verify_message(self,
                       message,
                       signed_message=None,
                       address=None,
                       use_tron: bool = True):
        """ Get the address of the account that signed the message with the given hash.
        You must specify exactly one of: vrs or signature

        Args:
            message (str): The message in the format "hex"
            signed_message (AttributeDict): Signature
            address (str): is Address
            use_tron (bool): is Tron header

        """
        if address is None:
            address = self.tron.default_address.base58

        if not is_hex(message):
            raise TronError('Expected hex message input')

        # Determine which header to attach to the message
        # before encrypting or decrypting
        header = TRX_MESSAGE_HEADER if use_tron else ETH_MESSAGE_HEADER
        header += str(len(message))

        message_hash = self.tron.keccak(text=header + message)
        recovered = Account.recover_hash(self.tron.toHex(message_hash),
                                         signed_message.signature)

        tron_address = '41' + recovered[2:]
        base58address = self.tron.address.from_hex(tron_address).decode()

        if base58address == address:
            return True

        raise ValueError('Signature does not match')
Beispiel #3
0
    def create_smart_contract(self, **kwargs):
        """Deploy Contract

        Deploys a contract.
        Returns TransactionExtention, which contains an unsigned transaction.

        Example:
        .. code-block:: python
            >>> from tronapi import Tron
            >>>
            >>> tron = Tron()
            >>> tron.transaction_builder.create_smart_contract(
            >>>    fee_limit=10**9,
            >>>    call_value=0,
            >>>    consume_user_resource_percent=10
            >>> )

        Args:
            **kwargs: Transaction parameters for the deployment
            transaction as a dict

        """

        if 'bytecode' not in kwargs:
            raise ValueError(
                "Cannot deploy a contract that does not have 'bytecode' associated "
                "with it")

        # Maximum TRX consumption, measured in SUN (1 TRX = 1,000,000 SUN).
        fee_limit = kwargs.setdefault('fee_limit', 0)
        # The same as User Pay Ratio.
        # The percentage of resources specified for users who use this contract.
        # This field accepts integers between [0, 100].
        user_fee_percentage = kwargs.setdefault(
            'consume_user_resource_percent', 0)
        # Amount of TRX transferred with this transaction, measured in SUN (1TRX = 1,000,000 SUN)
        call_value = kwargs.setdefault('call_value', 0)
        # Contract owner address, converted to a hex string
        owner_address = kwargs.setdefault('owner_address',
                                          self.tron.default_address.hex)
        # The max energy which will be consumed by the owner
        # in the process of excution or creation of the contract,
        # is an integer which should be greater than 0.
        origin_energy_limit = kwargs.setdefault('origin_energy_limit',
                                                10000000)

        if not is_hex(kwargs.get('bytecode')):
            raise ValueError('Invalid bytecode provided')

        if not is_integer(fee_limit) or fee_limit <= 0 or \
                fee_limit > 1000000000:
            raise ValueError('Invalid fee limit provided')

        if not is_integer(call_value) or call_value < 0:
            raise ValueError('Invalid call value provided')

        if not is_integer(user_fee_percentage) or user_fee_percentage < 0 or \
                user_fee_percentage > 100:
            raise ValueError('Invalid user fee percentage provided')

        if not is_integer(origin_energy_limit) or origin_energy_limit < 0:
            return ValueError('Invalid origin_energy_limit provided')

        if not self.tron.isAddress(owner_address):
            raise InvalidAddress('Invalid issuer address provided')

        # We write all the results in one object
        transaction = dict(**kwargs)
        transaction.setdefault('owner_address',
                               self.tron.address.to_hex(owner_address))

        return self.tron.manager.request('/wallet/deploycontract', transaction)
Beispiel #4
0
    def to_hex(address):
        """Helper function that will convert a generic value to hex"""
        if is_hex(address):
            return address.lower().replace('0x', '41', 2)

        return base58.b58decode_check(address).hex().upper()
Beispiel #5
0
    def from_hex(address):
        """Helper function that will convert a generic value from hex"""
        if not is_hex(address):
            return address

        return base58.b58encode_check(bytes.fromhex(address))
Beispiel #6
0
    def recover_hash(message_hash, signature):
        if not is_hex(message_hash):
            raise ValueError('Invalid message_hash provided')

        return ETHAccount.recoverHash(message_hash, signature=signature)
Beispiel #7
0
    def sign_hash(message_hash, private_key):
        if not is_hex(message_hash):
            raise ValueError('Invalid message_hash provided')

        return ETHAccount.signHash(message_hash, private_key)
Beispiel #8
0
    def sign(self,
             transaction: Any,
             private_key=None,
             use_tron: bool = True,
             multisig: bool = False,
             is_message_hex=False):
        """Safe method for signing your transaction

        Warnings:
            method: online_sign() - Use only in extreme cases.

        Args:
            transaction (Any): transaction details
            use_tron (bool): is Tron header
            multisig (bool): multi sign

        """

        if is_string(transaction):
            if not is_hex(transaction):
                raise TronError('Expected hex message input')

            # Determine which header to attach to the message
            # before encrypting or decrypting
            header = TRX_MESSAGE_HEADER if use_tron else ETH_MESSAGE_HEADER
            header += str(len(transaction))

            if is_message_hex:
                from eth_hash.auto import keccak as keccak_256
                message_hash = keccak_256(
                    header.encode('utf-8') + bytes.fromhex(transaction))
            else:
                message_hash = self.tron.keccak(text=header + transaction)

            signed_message = Account.sign_hash(
                self.tron.toHex(message_hash), private_key
                or self.tron.private_key)
            return signed_message

        if not multisig and 'signature' in transaction:
            raise TronError('Transaction is already signed')

        try:
            if not multisig:
                address = self.tron.address.from_private_key(
                    private_key or self.tron.private_key).hex.lower()
                owner_address = transaction['raw_data']['contract'][0][
                    'parameter']['value']['owner_address']

                if address != owner_address:
                    raise ValueError(
                        'Private key does not match address in transaction')

            # This option deals with signing of transactions, and writing to the array
            signed_tx = Account.sign_hash(transaction['txID'], private_key
                                          or self.tron.private_key)
            signature = signed_tx['signature'].hex()[2:]

            # support multi sign
            if 'signature' in transaction and is_list(
                    transaction['signature']):
                if not transaction['signature'].index(signature):
                    transaction['signature'].append(signature)
            else:
                transaction['signature'] = [signature]

            return transaction
        except ValueError as err:
            raise InvalidTronError(err)
Beispiel #9
0
def is_hex_encoded_block_hash(value):
    if not is_string(value):
        return False
    return len(remove_0x_prefix(value)) == 64 and is_hex(value)