Exemple #1
0
def sign(data: bytes,
         private_key_seed_ascii: str,
         hash_function=bitcoin.bin_sha256):
    """Sign data using Ethereum private key.

    :param private_key_seed_ascii: Private key seed as ASCII string
    """

    msghash = hash_function(data)

    priv = utils.sha3(private_key_seed_ascii)
    pub = bitcoin.privtopub(priv)

    # Based on ethereum/tesrt_contracts.py test_ecrecover
    pk = PrivateKey(priv, raw=True)

    signature = pk.ecdsa_recoverable_serialize(
        pk.ecdsa_sign_recoverable(msghash, raw=True))
    signature = signature[0] + utils.bytearray_to_bytestr([signature[1]])

    # Enforce non-tightly-packed arguments for signing
    # (0x00 left pad)
    # https://github.com/ethereum/web3.py/issues/466
    v = utils.safe_ord(signature[64]) + 27
    r_bytes = signature[0:32]
    r_bytes = pad_left(r_bytes, 32, b"\0")
    r = big_endian_to_int(r_bytes)
    s_bytes = signature[32:64]
    s_bytes = pad_left(s_bytes, 32, b"\0")
    s = big_endian_to_int(s_bytes)

    # Make sure we use bytes data and zero padding stays
    # good across different systems
    r_hex = binascii.hexlify(r_bytes).decode("ascii")
    s_hex = binascii.hexlify(s_bytes).decode("ascii")

    # Convert to Etheruem address format
    addr = utils.big_endian_to_int(
        utils.sha3(bitcoin.encode_pubkey(pub, 'bin')[1:])[12:])

    # Return various bits about signing so it's easier to debug
    return {
        "signature": signature,
        "v": v,
        "r": r,
        "s": s,
        "r_bytes": r_bytes,
        "s_bytes": s_bytes,
        "r_hex": "0x" + r_hex,
        "s_hex": "0x" + s_hex,
        "address_bitcoin": addr,
        "address_ethereum": get_ethereum_address_from_private_key(priv),
        "public_key": pub,
        "hash": msghash,
        "payload":
        binascii.hexlify(bytes([v] + list(r_bytes) + list(s_bytes, )))
    }
Exemple #2
0
    def sender(self):
        if not self._sender:
            if not is_bitcoin_available() or not is_secp256k1_available():
                raise ImportError(
                    "In order to derive the sender for transactions the "
                    "`bitcoin` and `secp256k1` packages must be installed."
                )
            from bitcoin import N
            from secp256k1 import PublicKey, ALL_FLAGS

            # Determine sender
            if self.v:
                has_invalid_signature_values = (
                    self.r >= N or
                    self.s >= N or
                    self.v < 27 or
                    self.v > 28 or
                    self.r == 0 or
                    self.s == 0
                )
                if has_invalid_signature_values:
                    raise ValueError("Invalid signature values!")
                rlpdata = rlp.encode(self, UnsignedTransaction)
                rawhash = keccak(rlpdata)

                pk = PublicKey(flags=ALL_FLAGS)
                try:
                    pk.public_key = pk.ecdsa_recover(
                        rawhash,
                        pk.ecdsa_recoverable_deserialize(
                            pad_left(
                                int_to_big_endian(self.r),
                                32,
                                b'\x00',
                            ) + pad_left(
                                int_to_big_endian(self.s),
                                32,
                                b'\x00',
                            ),
                            self.v - 27
                        ),
                        raw=True
                    )
                    pub = pk.serialize(compressed=False)
                except Exception:
                    raise ValueError("Invalid signature values (x^3+7 is non-residue)")

                if pub[1:] == b"\x00" * (len(pub) - 1):
                    raise ValueError("Invalid signature (zero privkey cannot sign)")

                self._sender = to_normalized_address(keccak(pub[1:])[-20:])
                assert self.sender == self._sender
            else:
                self._sender = 0
        return self._sender
Exemple #3
0
    def sender(self):
        if not self._sender:
            if not is_bitcoin_available() or not is_secp256k1_available():
                raise ImportError(
                    "In order to derive the sender for transactions the "
                    "`bitcoin` and `secp256k1` packages must be installed.")
            from bitcoin import N
            from secp256k1 import PublicKey, ALL_FLAGS

            # Determine sender
            if self.v:
                has_invalid_signature_values = (self.r >= N or self.s >= N
                                                or self.v < 27 or self.v > 28
                                                or self.r == 0 or self.s == 0)
                if has_invalid_signature_values:
                    raise ValueError("Invalid signature values!")
                rlpdata = rlp.encode(self, UnsignedTransaction)
                rawhash = keccak(rlpdata)

                pk = PublicKey(flags=ALL_FLAGS)
                try:
                    pk.public_key = pk.ecdsa_recover(
                        rawhash,
                        pk.ecdsa_recoverable_deserialize(
                            pad_left(
                                int_to_big_endian(self.r),
                                32,
                                b'\x00',
                            ) + pad_left(
                                int_to_big_endian(self.s),
                                32,
                                b'\x00',
                            ), self.v - 27),
                        raw=True)
                    pub = pk.serialize(compressed=False)
                except Exception:
                    raise ValueError(
                        "Invalid signature values (x^3+7 is non-residue)")

                if pub[1:] == b"\x00" * (len(pub) - 1):
                    raise ValueError(
                        "Invalid signature (zero privkey cannot sign)")

                self._sender = to_normalized_address(keccak(pub[1:])[-20:])
                assert self.sender == self._sender
            else:
                self._sender = 0
        return self._sender
Exemple #4
0
def get_default_account_keys():
    keys = KeyAPI()

    for i in range(1, 11):
        pk_bytes = pad_left(int_to_big_endian(i), 32, b'\x00')
        private_key = keys.PrivateKey(pk_bytes)
        yield private_key
def main(**kwargs):
    project = Project()

    chain_name = kwargs['chain']
    owner = kwargs['owner']
    challenge_period = kwargs['challenge_period']
    supply = kwargs['supply']
    token_name = kwargs['token_name']
    token_decimals = kwargs['token_decimals']
    token_symbol = kwargs['token_symbol']
    token_address = kwargs['token_address']
    supply *= 10**(token_decimals)
    txn_wait = 250

    assert challenge_period >= 500, 'Challenge period should be >= 500 blocks'

    if chain_name == 'rinkeby':
        txn_wait = 500

    print(
        '''Make sure {} chain is running, you can connect to it and it is synced,
          or you'll get timeout'''.format(chain_name))

    with project.get_chain(chain_name) as chain:
        web3 = chain.web3
        print('Web3 provider is', web3.currentProvider)

        owner = owner or web3.eth.accounts[0]
        assert owner
        assert web3.eth.getBalance(
            owner) > 0, 'Account with insuficient funds.'
        print('Owner is', owner)

        token = chain.provider.get_contract_factory('CustomToken')

        if not token_address:
            txhash = token.deploy(
                args=[supply, token_name, token_symbol, token_decimals],
                transaction={'from': owner})
            receipt = check_succesful_tx(chain.web3, txhash, txn_wait)
            token_address = receipt['contractAddress']
            print(token_name, 'address is', token_address)

        microraiden_contract = chain.provider.get_contract_factory(
            'RaidenMicroTransferChannels')
        txhash = microraiden_contract.deploy(
            args=[token_address, challenge_period])
        receipt = check_succesful_tx(chain.web3, txhash, txn_wait)
        microraiden_address = receipt['contractAddress']

        print('RaidenMicroTransferChannels address is', microraiden_address)

        abi_encoded_args = encode_hex(
            pad_left(pack(remove_0x_prefix(token_address), challenge_period),
                     128, '0'))

        print('RaidenMicroTransferChannels arguments', token_address,
              challenge_period)
        print('RaidenMicroTransferChannels abi encoded constructor arguments:',
              abi_encoded_args)
Exemple #6
0
def robust_decode_hex(value):
    unprefixed_value = remove_0x_prefix(value)
    if len(unprefixed_value) % 2:
        return decode_hex(
            pad_left(unprefixed_value,
                     len(unprefixed_value) + 1, b'0'))
    else:
        return decode_hex(unprefixed_value)
Exemple #7
0
def getTokens(**kwargs):
    project = Project()

    # print(kwargs)
    chain_name = kwargs['chain']
    owner = kwargs['owner']
    challenge_period = kwargs['challenge_period']
    supply = kwargs['supply']
    senders = kwargs['senders']
    sender_addresses = kwargs['sender_addresses'].split(',')
    token_name = kwargs['token_name']
    token_decimals = kwargs['token_decimals']
    token_symbol = kwargs['token_symbol']
    token_address = kwargs['token_address']

    supply *= 10**(token_decimals)
    token_assign = int(supply / (len(sender_addresses) + senders))

    txn_wait = 250
    event_wait = 50
    if chain_name == 'rinkeby':
        txn_wait = 500
        event_wait = 500

    print(
        "Make sure {} chain is running, you can connect to it and it is synced, or you'll get timeout"
        .format(chain_name))

    with project.get_chain(chain_name) as chain:
        web3 = chain.web3
        owner = owner or web3.eth.accounts[0]
        print('Web3 provider is', web3.currentProvider)

        if not token_address:
            token = chain.provider.get_contract_factory('ERC223Token')
            txhash = token.deploy(
                args=[supply, token_name, token_decimals, token_symbol],
                transaction={'from': owner})
            receipt = check_succesful_tx(chain.web3, txhash, txn_wait)
            token_address = receipt['contractAddress']
            print(token_name, ' address is', token_address)

        channel_factory = chain.provider.get_contract_factory(
            'RaidenMicroTransferChannels')
        txhash = channel_factory.deploy(args=[token_address, challenge_period])

        print('RaidenMicroTransferChannels arguments', token_address,
              challenge_period)
        padded_token_address = pad_left(remove_0x_prefix(token_address), 64,
                                        '0')
        print('RaidenMicroTransferChannels abi encoded arguments:',
              encode_hex(pack(padded_token_address, challenge_period)))
        receipt = check_succesful_tx(chain.web3, txhash, txn_wait)
        cf_address = receipt['contractAddress']
        print('RaidenMicroTransferChannels address is', cf_address)

        priv_keys = []
        addresses = []
        # we cannot retrieve private keys from configured chains
        # therefore: create 5 wallets (sample addresses with private keys)
        # store in separate arrays
        for i in range(senders - 1):
            priv_key, address = createWallet()
            priv_keys.append(priv_key)
            addresses.append('0x' + address)

        # send tokens to each new wallet
        for sender in addresses:
            token(token_address).transact({
                'from': owner
            }).transfer(sender, token_assign)
        # also send tokens to sender addresses
        for sender in sender_addresses:
            token(token_address).transact({
                'from': owner
            }).transfer(sender, token_assign)

        print('Senders have each been issued', token_assign, ' tokens')

        # check if it works:
        # 1. get message balance hash for address[0]
        balance_msg = "Receiver: " + addresses[
            0] + ", Balance: 10000, Channel ID: 100"

        # 2. sign the hash with private key corresponding to address[0]
        balance_msg_sig, addr = sign.check(balance_msg,
                                           binascii.unhexlify(priv_keys[0]))
        # 3. check if ECVerify and ec_recovered address are equal
        ec_recovered_addr = channel_factory(
            cf_address).call().verifyBalanceProof(addresses[0], 100, 10000,
                                                  balance_msg_sig)
        print('EC_RECOVERED_ADDR:', ec_recovered_addr)
        print('FIRST WALLET ADDR:', addresses[0])
        assert ec_recovered_addr == addresses[0]

        print('Wait for confirmation...')

        transfer_filter = token.on('Transfer')
        wait(transfer_filter, event_wait)

        print('BALANCE:', token(token_address).call().balanceOf(addresses[0]))
        assert token(token_address).call().balanceOf(addresses[0]) > 0

    # return arrays with generated wallets (private keys first, then addresses, so that priv_key[0] <-> address[0]
    return (priv_keys, addresses, token(token_address))
Exemple #8
0
def pad_left_hex(value, num_bytes):
    return pad_left(value, num_bytes * 2, '0')
Exemple #9
0
def _pad32(value):
    return pad_left(value, 32, b'\x00')
Exemple #10
0
def pad_left_hex(value, num_bytes):
    return pad_left(value, num_bytes * 2, '0')
Exemple #11
0
def random_private_key(bound):
    """Randomly gnerate a private key smaller than a certain bound."""
    n = random.randint(1, bound)
    private_key = encode_hex(pad_left(int_to_big_endian(n), 32, '\0'))
    return private_key
Exemple #12
0
def msg_hash(nextkey, gas, addr, value, data):
    msg  = b''.join([pad_left(nextkey, 32, b'\x00'), pad_left(gas, 32, b'\x00'), pad_left(addr, 20, b'\x00'), pad_left(value, 32, b'\x00')])+data
    #print('Expected: ',"0x"+msg.hex(), len("0x"+msg.hex()))
    return eth_utils.keccak(msg)