示例#1
0
    def sign(self, private_key):
        """
        Sign check
        Args:
            private_key (str)
        """

        if not self.passphrase:
            raise ValueError('Passphrase should be not empty string')

        # Prepare structure
        # It contains nonce, chain_id, due_block, coin, value, lock, v, r, s
        # lock, v, r, s appended later in code
        structure = [
            int(binascii.hexlify(str(self.nonce).encode()), 16),
            self.chain_id,
            self.due_block,
            MinterConvertor.encode_coin_name(self.coin),
            MinterConvertor.convert_value(value=self.value, to='pip')
        ]

        # Create msg hash
        msg_hash = self.__hash(structure)

        # SHA256 from passphrase
        sha = hashlib.sha256()
        sha.update(self.passphrase.encode())
        passphrase = sha.hexdigest()

        # Create lock from signature
        self.lock = self.__lockfromsignature(
            signature=ECDSA.sign(message=msg_hash, private_key=passphrase)
        )

        # Re-create msg hash with adding lock to structure
        structure.append(self.lock)
        msg_hash = self.__hash(structure)

        # Re-create signature, add it to check attrs and to structure
        signature = ECDSA.sign(message=msg_hash, private_key=private_key)
        self.signature = {
            'v': signature[0],
            'r': format(signature[1], 'x'),
            's': format(signature[2], 'x')
        }
        structure += signature

        # Get RLP, which will be the check
        check = binascii.hexlify(rlp.encode(structure))

        return MinterPrefix.CHECK + check.decode()
示例#2
0
    def get_sender_address(cls, tx):
        """
        Get sender address from tx.
        Recover public key from tx and then get address from public key, if tx has single signature type, or get
        decoded sender address, if tx has multi signature type.
        Args:
            tx (dict): transaction dict
        Returns:
            Minter address (string)
        """

        # Remember signature data and remove it from tx
        signature_data = tx.pop('signature_data')

        # If there is sender address in signature data (multi signature tx), return it
        if signature_data.get('from_mx'):
            return signature_data['from_mx']

        # Otherwise (single signature tx), recover public key and get address from public key
        # Unhexlify (convert to bin (ascii)) all non-numeric dict values
        tx = MinterHelper.hex2bin_recursive(tx)

        # Encode tx data to RLP
        tx['data'] = rlp.encode(list(tx['data'].values()))

        # Message
        tx_rlp = rlp.encode(list(tx.values()))
        _keccak = MinterHelper.keccak_hash(tx_rlp)

        # Recover public key
        public_key = MinterPrefix.PUBLIC_KEY + ECDSA.recover(_keccak, tuple(signature_data.values()))

        return MinterWallet.get_address_from_public_key(public_key)
示例#3
0
    def proof(cls, address, passphrase):
        """
        Create proof
        Args:
            address (str)
            passphrase (str)
        Returns:
            str
        """

        # Get address hash
        address = MinterPrefix.remove_prefix(
            string=address,
            prefix=MinterPrefix.ADDRESS
        )
        address = MinterHelper.hex2bin(address)
        address_hash = cls.__hash(data=[address])

        # Create SHA256 from passphrase
        sha = hashlib.sha256()
        sha.update(passphrase.encode())
        passphrase = sha.hexdigest()

        # Get signature
        signature = ECDSA.sign(message=address_hash, private_key=passphrase)

        return binascii.hexlify(cls.__lockfromsignature(signature)).decode()
示例#4
0
    def sign(self, private_key):
        """
        Sign transaction.
        This method can be called only from instances of inherited classes.
        Args:
            private_key (string): private key
        Return:
            string
        """

        # Get structure populated with instance data
        tx = self._structure_from_instance()
        # Remove sgnature data, it's not needed before getting Keccak
        tx.pop('signature_data')

        # Encode tx data to RLP
        tx['data'] = rlp.encode(list(tx['data'].values()))

        # Encode all tx to RLP and create Keccak hash
        tx_rlp = rlp.encode(list(tx.values()))
        _keccak = MinterHelper.keccak_hash(tx_rlp)

        # Signature data
        tx['signature_data'] = rlp.encode(ECDSA.sign(_keccak, private_key))

        tx_rlp = rlp.encode(list(tx.values()))
        self.signed_tx = binascii.hexlify(tx_rlp).decode()
示例#5
0
    def recover_public_key(cls, tx):
        """
        Recover public key from tx.
        Args:
            tx (dict): transaction dict
        Returns:
            public_key (string)
        """

        # Remember signature data and remove it from tx
        signature_data = tx.pop('signature_data')

        # Unhexlify (convert to bin (ascii)) all non-numeric dict values
        tx = MinterHelper.hex2bin_recursive(tx)

        # Encode tx data to RLP
        tx['data'] = rlp.encode(list(tx['data'].values()))

        # Message
        tx_rlp = rlp.encode(list(tx.values()))
        _keccak = MinterHelper.keccak_hash(tx_rlp)

        # Recover public key
        public_key = ECDSA.recover(_keccak, tuple(signature_data.values()))

        return MinterPrefix.PUBLIC_KEY + public_key
示例#6
0
    def sign(self, private_key):
        """
        Sign check
        Args:
            private_key (str)
        """
        # Prepare structure
        # It contains nonce, chain_id, due_block, coin, value, gas_coin,
        # lock, v, r, s.
        # lock, v, r, s appended later in code
        structure = [
            int(str(self.nonce).encode().hex(), 16), self.chain_id,
            self.due_block,
            MinterHelper.encode_coin_name(self.coin),
            MinterHelper.to_pip(self.value),
            MinterHelper.encode_coin_name(self.gas_coin)
        ]

        # Create msg hash
        msg_hash = self.__hash(structure)

        # SHA256 from passphrase
        sha = hashlib.sha256()
        sha.update(self.passphrase.encode())
        passphrase = sha.hexdigest()

        # Create lock from signature
        self.lock = self.__lockfromsignature(
            signature=ECDSA.sign(message=msg_hash, private_key=passphrase))

        # Re-create msg hash with adding lock to structure
        structure.append(self.lock)
        msg_hash = self.__hash(structure)

        # Re-create signature, add it to check attrs and to structure
        signature = ECDSA.sign(message=msg_hash, private_key=private_key)
        self.signature = {
            'v': signature[0],
            'r': format(signature[1], 'x'),
            's': format(signature[2], 'x')
        }
        structure += signature

        # Get RLP, which will be the check
        check = rlp.encode(structure).hex()

        return MinterHelper.prefix_add(check, PREFIX_CHECK)
示例#7
0
    def from_raw(cls, rawcheck):
        """
        Create check instance from raw check
        Args:
            rawcheck (str)
        Returns:
            MinterCheck
        """

        # Remove check prefix and RLP decode it
        rawcheck = MinterPrefix.remove_prefix(
            string=rawcheck,
            prefix=MinterPrefix.CHECK
        )
        rawcheck = binascii.unhexlify(rawcheck)
        decoded = rlp.decode(rawcheck)

        # Create MinterCheck instance
        kwargs = {
            'nonce': int(decoded[0].decode()),
            'chain_id': MinterHelper.bin2int(decoded[1]),
            'due_block': MinterHelper.bin2int(decoded[2]),
            'coin': MinterConvertor.decode_coin_name(decoded[3]),
            'value': MinterConvertor.convert_value(
                value=MinterHelper.bin2int(decoded[4]),
                to='bip'
            ),
            'lock': binascii.hexlify(decoded[5]).decode(),
            'signature': {
                'v': MinterHelper.bin2int(decoded[6]),
                'r': MinterHelper.bin2hex(decoded[7]),
                's': MinterHelper.bin2hex(decoded[8])
            }
        }
        check = MinterCheck(**kwargs)

        # Recover owner address
        msg_hash = cls.__hash(data=[
            int(binascii.hexlify(str(check.nonce).encode()), 16),
            check.chain_id,
            check.due_block,
            MinterConvertor.encode_coin_name(check.coin),
            MinterConvertor.convert_value(value=check.value, to='pip'),
            MinterHelper.hex2bin(check.lock)
        ])
        public_key = ECDSA.recover(msg_hash, list(check.signature.values()))
        public_key = MinterPrefix.PUBLIC_KEY + public_key

        check.owner = MinterWallet.get_address_from_public_key(public_key)

        return check
示例#8
0
    def from_raw(cls, rawcheck):
        """
        Create check instance from raw check
        Args:
            rawcheck (str)
        Returns:
            MinterCheck
        """

        # Remove check prefix and RLP decode it
        rawcheck = MinterHelper.prefix_remove(rawcheck)
        rawcheck = bytes.fromhex(rawcheck)
        decoded = rlp.decode(rawcheck)

        # Create MinterCheck instance
        kwargs = {
            'nonce': int(decoded[0].decode()),
            'chain_id': int.from_bytes(decoded[1], 'big'),
            'due_block': int.from_bytes(decoded[2], 'big'),
            'coin': MinterHelper.decode_coin_name(decoded[3]),
            'value': MinterHelper.to_bip(int.from_bytes(decoded[4], 'big')),
            'gas_coin': MinterHelper.decode_coin_name(decoded[5]),
            'lock': decoded[6].hex(),
            'signature': {
                'v': int.from_bytes(decoded[7], 'big'),
                'r': decoded[8].hex(),
                's': decoded[9].hex()
            }
        }
        check = MinterCheck(**kwargs)

        # Recover owner address
        msg_hash = cls.__hash(data=[
            int(str(check.nonce).encode().hex(), 16), check.chain_id,
            check.due_block,
            MinterHelper.encode_coin_name(check.coin),
            MinterHelper.to_pip(check.value),
            MinterHelper.encode_coin_name(check.gas_coin),
            bytes.fromhex(check.lock)
        ])
        public_key = ECDSA.recover(msg_hash, tuple(check.signature.values()))
        public_key = MinterHelper.prefix_add(public_key, PREFIX_PUBKEY)

        check.owner = MinterWallet.get_address_from_public_key(public_key)

        return check
示例#9
0
    def generate_signature(self, private_key):
        """
        Create signature for transaction
        Args:
            private_key (str): private key to sign with
        Returns:
            hex_signature (str)
        """
        # Get structure populated with instance data and rlp encoded
        tx_struct = self.generate_tx_rlp()

        # Create keccak hash
        tx_rlp = rlp.encode(list(tx_struct.values()))
        keccak = MinterHelper.keccak_hash(tx_rlp)

        # Create signature
        signature = ECDSA.sign(keccak, private_key)
        signature = binascii.hexlify(rlp.encode(signature)).decode()

        return signature
示例#10
0
    def proof(cls, address, passphrase=''):
        """
        Create proof
        Args:
            address (str)
            passphrase (str)
        Returns:
            str
        """

        # Get address hash
        address = MinterHelper.prefix_remove(address)
        address = bytes.fromhex(address)
        address_hash = cls.__hash(data=[address])

        # Create SHA256 from passphrase
        sha = hashlib.sha256()
        sha.update(passphrase.encode())
        passphrase = sha.hexdigest()

        # Get signature
        signature = ECDSA.sign(message=address_hash, private_key=passphrase)

        return cls.__lockfromsignature(signature).hex()