예제 #1
0
    def _get_setting(self, key, default_value=None, value_type=str):
        """Get the setting stored at the given key.

        Args:
            key (str): the setting key
            default_value (str, optional): The default value, if none is
                found. Defaults to None.
            value_type (function, optional): The type of a setting value.
                Defaults to `str`.

        Returns:
            str: The value of the setting if found, default_value
            otherwise.
        """
        try:
            state_entry = self._state_view.get(
                SettingsView.setting_address(key))
        except KeyError:
            return default_value

        if state_entry is not None:
            setting = Setting()
            setting.ParseFromString(state_entry)
            for setting_entry in setting.entries:
                if setting_entry.key == key:
                    return value_type(setting_entry.value)

        return default_value
예제 #2
0
def test_atomic_swap_init_swap_no_account_in_state():
    """
    Case: initialize swap of bot's Remme node tokens to Alice's ERC20 Remme tokens from non-existent bot address.
    Expect: invalid transaction error is raised with not enough balance error message.
    """
    atomic_swap_init_payload = AtomicSwapInitPayload(
        receiver_address=ALICE_ADDRESS,
        sender_address_non_local=BOT_ETHEREUM_ADDRESS,
        amount=TOKENS_AMOUNT_TO_SWAP,
        swap_id=SWAP_ID,
        secret_lock_by_solicitor=BOT_IT_IS_INITIATOR_MARK,
        email_address_encrypted_by_initiator=ALICE_EMAIL_ADDRESS_ENCRYPTED_BY_INITIATOR,
        created_at=CURRENT_TIMESTAMP,
    )

    transaction_payload = TransactionPayload()
    transaction_payload.method = AtomicSwapMethod.INIT
    transaction_payload.data = atomic_swap_init_payload.SerializeToString()

    serialized_transaction_payload = transaction_payload.SerializeToString()

    transaction_header = TransactionHeader(
        signer_public_key=BOT_PUBLIC_KEY,
        family_name=TRANSACTION_REQUEST_ACCOUNT_HANDLER_PARAMS.get('family_name'),
        family_version=TRANSACTION_REQUEST_ACCOUNT_HANDLER_PARAMS.get('family_version'),
        inputs=INPUTS,
        outputs=OUTPUTS,
        dependencies=[],
        payload_sha512=hash512(data=serialized_transaction_payload),
        batcher_public_key=RANDOM_NODE_PUBLIC_KEY,
        nonce=time.time().hex().encode(),
    )

    serialized_header = transaction_header.SerializeToString()

    transaction_request = TpProcessRequest(
        header=transaction_header,
        payload=serialized_transaction_payload,
        signature=create_signer(private_key=BOT_PRIVATE_KEY).sign(serialized_header),
    )

    swap_commission_setting = Setting()
    swap_commission_setting.entries.add(key=SETTINGS_SWAP_COMMISSION, value=str(SWAP_COMMISSION_AMOUNT))
    serialized_swap_commission_setting = swap_commission_setting.SerializeToString()

    mock_context = StubContext(inputs=INPUTS, outputs=OUTPUTS, initial_state={
        BLOCK_INFO_CONFIG_ADDRESS: SERIALIZED_BLOCK_INFO_CONFIG,
        BLOCK_INFO_ADDRESS: SERIALIZED_BLOCK_INFO,
        ADDRESS_TO_GET_SWAP_COMMISSION_AMOUNT_BY: serialized_swap_commission_setting,
    })

    with pytest.raises(InvalidTransaction) as error:
        AtomicSwapHandler().apply(transaction=transaction_request, context=mock_context)

    total_amount = TOKENS_AMOUNT_TO_SWAP + SWAP_COMMISSION_AMOUNT

    assert f'Not enough balance to perform the transaction in the amount (with a commission) {total_amount}.' \
           == str(error.value)
예제 #3
0
    def create_get_response_report_key_pem(self, pem=None):
        setting = Setting()
        if pem is not None:
            entry = Setting.Entry(key='sawtooth.poet.report_public_key_pem',
                                  value=pem)
            setting.entries.extend([entry])

        data = setting.SerializeToString()
        return self._factory.create_get_response(
            {'000000a87cb5eafdcca6a87ccc804f5546a'
             'b8e97a7d614626e4500e3b0c44298fc1c14': data})
예제 #4
0
    def create_get_response_enclave_basenames(self, basenames=None):
        setting = Setting()
        if basenames is not None:
            entry = Setting.Entry(key='sawtooth.poet.'
                                      'valid_enclave_basenames',
                                  value=basenames)
            setting.entries.extend([entry])

        data = setting.SerializeToString()
        return self._factory.create_get_response(
            {'000000a87cb5eafdcca6a87ccc804f5546a'
             'b8ebec3b47bc008b27de3b0c44298fc1c14': data})
예제 #5
0
    def create_get_response_enclave_measurements(self, measurements=None):
        setting = Setting()
        if measurements is not None:
            entry = Setting.Entry(key='sawtooth.poet.'
                                      'valid_enclave_measurements',
                                  value=measurements)
            setting.entries.extend([entry])

        data = setting.SerializeToString()
        return self._factory.create_get_response(
            {'000000a87cb5eafdcca6a87ccc804f5546a'
             'b8e39ccaeec28506829e3b0c44298fc1c14': data})
예제 #6
0
def _get_setting_entry(context, address):
    setting = Setting()

    try:
        entries_list = context.get_state([address], timeout=STATE_TIMEOUT_SEC)
    except FutureTimeoutError:
        LOGGER.warning('Timeout occured on context.get_state([%s])', address)
        raise InternalError('Unable to get {}'.format(address))

    if entries_list:
        setting.ParseFromString(entries_list[0].data)

    return setting
예제 #7
0
def _get_setting_entry(context, address):
    from remme.tp.basic import get_data  # noqa

    try:
        entry = get_data(context, Setting, address)
    except FutureTimeoutError:
        LOGGER.warning('Timeout occured on context.get_state([%s])', address)
        raise InternalError('Unable to get {}'.format(address))

    return entry if entry else Setting()
예제 #8
0
def _check_allowed_minter(minting_key, context):
    entries_list = _get_data(ALLOWED_SIGNER_ADDRESS, context)
    if not entries_list:
        raise InvalidTransaction(
            "The transaction signer is not authorized to submit transactions: "
            "{}".format(minting_key))

    setting = Setting()
    setting.ParseFromString(entries_list[0].data)
    for entry in setting.entries:
        if entry.key == "sawtooth.stake.allowed_keys":
            allowed_signer = entry.value.split(",")
            LOGGER.info('minting key: {}'.format(allowed_signer))
            if minting_key == allowed_signer[0]:
                return

    raise InvalidTransaction(
        "The transction signer is not authorized mint stake tokens: "
        "{}".format(minting_key))
예제 #9
0
def _check_allowed_transactor(transaction, context):
    header = transaction.header

    entries_list = _get_data(ALLOWED_SIGNER_ADDRESS, context)
    if not entries_list:
        raise InvalidTransaction(
            "The transaction signer is not authorized to submit transactions: "
            "{}".format(header.signer_public_key))

    setting = Setting()
    setting.ParseFromString(entries_list[0].data)
    for entry in setting.entries:
        if entry.key == "sawtooth.identity.allowed_keys":
            allowed_signer = entry.value.split(",")
            if header.signer_public_key in allowed_signer:
                return

    raise InvalidTransaction(
        "The transction signer is not authorized to submit transactions: "
        "{}".format(header.signer_public_key))
    async def get_initial_stake(self):
        """
        Get initial stake of node.

        To use:
            .. code-block:: python

                initial_stake = await remme.node_management.get_initial_stake()
        """
        data = await self._remme_api.send_request(
            method=RemmeMethods.FETCH_STATE,
            params={
                'address': self._stake_settings_address,
            },
        )

        setting = Setting()
        setting.ParseFromString(base64.b64decode(data.get('data')))

        value = setting.entries[0].value

        return int(value, 10)
예제 #11
0
 def get_setting_value(self, key):
     setting = Setting()
     value = self.get_value(_make_settings_key(key))
     setting.ParseFromString(value)
     return setting.entries[0].value
예제 #12
0
 def get_pub_key_encryption(self):
     setting = Setting()
     setting.ParseFromString(self.get_value(_make_settings_key(SETTINGS_PUB_KEY_ENCRYPTION)))
     return setting.entries[0].value
예제 #13
0
 async def get_pub_key_encryption(self):
     setting = Setting()
     pub_key_enc = _make_settings_key(SETTINGS_PUB_KEY_ENCRYPTION)
     raw_pub_key = await self.get_value(pub_key_enc)
     setting.ParseFromString(raw_pub_key)
     return setting.entries[0].value
예제 #14
0
class RpcApiTestCase(AioHTTPTestCase, HelperTestCase):
    @staticmethod
    def create_raw_transaction_send_token_payload(pub_key_to, amount=1):
        client = AccountClient()
        signer = client._signer
        address = client.make_address_from_data(pub_key_to)
        node_address = client.get_user_address()

        transfer = TransferPayload()
        transfer.address_to = address
        transfer.value = amount

        tr = TransactionPayload()
        tr.method = AccountMethod.TRANSFER
        tr.data = transfer.SerializeToString()

        payload = tr.SerializeToString()

        header = TransactionHeader(
            signer_public_key=signer.get_public_key().as_hex(),
            family_name=client._family_handler.family_name,
            family_version=client._family_handler.family_versions[-1],
            inputs=[node_address, address],
            outputs=[node_address, address],
            dependencies=[],
            payload_sha512=hash512(payload),
            batcher_public_key=signer.get_public_key().as_hex(),
            nonce=time.time().hex().encode()).SerializeToString()

        signature = signer.sign(header)

        transaction = Transaction(header=header,
                                  payload=payload,
                                  header_signature=signature)
        return transaction

    async def get_application(self):
        app = web.Application()
        rpc = JsonRpc(loop=self.loop, max_workers=1)
        rpc.add_methods(
            ('', get_node_config),
            ('', send_raw_transaction),
            ('', get_balance),
            ('', get_batch_status),
        )
        app.router.add_route('POST', '/', rpc)
        return app

    async def create_rpc_request(self, method, params=None):
        if params is None:
            params = {}
        data = encode_request(method, id=int(time.time()), params=params)
        LOGGER.info(f'JSON RPC request payload: {data}')
        return await self.client.request(
            'POST',
            '/',
            data=data,
            headers={'Content-Type': 'application/json'})

    @mock.patch(
        'remme.clients.basic.BasicClient.fetch_state',
        return_value={
            'data':
            base64.b64encode(
                Setting(entries=[
                    Setting.Entry(
                        key=_make_settings_key(SETTINGS_STORAGE_PUB_KEY),
                        value=
                        '03823c7a9e285246985089824f3aaa51fb8675d08d84b151833ca5febce37ad61e'
                    )
                ]).SerializeToString())
        })
    @mock.patch('remme.clients.basic.BasicClient._head_to_root',
                return_value=(None, 'some_root'))
    @unittest_run_loop
    @test
    async def test_node_key_retrieve_info_and_it_ok(self, root_mock,
                                                    fetch_state_mock):
        resp = await self.create_rpc_request('get_node_config')
        self.assertEqual(resp.status, 200)
        data = await resp.json()

        pub_key = PubKeyClient().get_public_key()
        self.assertEqual(data['result']['node_public_key'], pub_key)

    @mock.patch(
        'remme.clients.basic.BasicClient.submit_batches',
        return_value={
            'data':
            'c6bcb01255c1870a5d42fe2dde5e91fb0c5992ec0b49932cdab901539bf977f75bb7699c053cea16668ba732a7d597dd0c2b80f157f1a2514932078bb761de4b'
        })
    @unittest_run_loop
    @test
    async def test_valid_raw_transaction_send_to_the_node(self, req_mock):
        payload = self.create_raw_transaction_send_token_payload(
            '03823c7a9e285246985089824f3aaa51fb8675d08d84b151833ca5febce37ad61e',
            1)
        resp = await self.create_rpc_request('send_raw_transaction', {
            'data':
            base64.b64encode(payload.SerializeToString()).decode('utf-8')
        })
        self.assertEqual(resp.status, 200)
        data = await resp.json()
        self.assertEqual(
            data['result'],
            'c6bcb01255c1870a5d42fe2dde5e91fb0c5992ec0b49932cdab901539bf977f75bb7699c053cea16668ba732a7d597dd0c2b80f157f1a2514932078bb761de4b'
        )

    @mock.patch('remme.clients.basic.BasicClient.fetch_state',
                return_value={
                    'data':
                    base64.b64encode(Account(balance=100).SerializeToString())
                })
    @mock.patch('remme.clients.basic.BasicClient._head_to_root',
                return_value=(None, 'some_root'))
    @unittest_run_loop
    @test
    async def test_get_token_balance(self, root_mock, fetch_state_mock):
        address = AccountClient().make_address_from_data(
            '03823c7a9e285246985089824f3aaa51fb8675d08d84b151833ca5febce37ad61a'
        )
        resp = await self.create_rpc_request('get_balance',
                                             {'public_key_address': address})
        self.assertEqual(resp.status, 200)
        data = await resp.json()
        self.assertEqual(data['result'], 100)

    @mock.patch('remme.clients.basic.BasicClient.list_statuses',
                return_value={'data': [{
                    'status': 'COMMITTED'
                }]})
    @unittest_run_loop
    @test
    async def test_check_batch_status(self, batch_status_mock):
        resp = await self.create_rpc_request(
            'get_batch_status', {
                'id':
                '3936f0fa13d008c2b00d04013dfa5e5359fccc117e4c47b1416ee24e115ac08b08707be3b3ce6956ca3d789d245ff0dddf7a39bc2b2f4210ffe81ebd0244c014'
            })
        self.assertEqual(resp.status, 200)
        data = await resp.json()
        self.assertEqual(data['result'], 'COMMITTED')
예제 #15
0
def test_store_public_key_for_other_economy_is_not_enabled():
    """
    Case: send transaction request, to store certificate public key for other, when economy isn't enabled.
    Expect: public key information is stored to blockchain linked to owner address. Owner hasn't paid for storing.
    """
    new_public_key_payload = generate_rsa_payload(key=CERTIFICATE_PUBLIC_KEY)
    serialized_new_public_key_payload = new_public_key_payload.SerializeToString()

    private_key = Secp256k1PrivateKey.from_hex(OWNER_PRIVATE_KEY)
    signature_by_owner = Secp256k1Context().sign(serialized_new_public_key_payload, private_key)

    new_public_key_store_and_pay_payload = NewPubKeyStoreAndPayPayload(
        pub_key_payload=new_public_key_payload,
        owner_public_key=bytes.fromhex(OWNER_PUBLIC_KEY),
        signature_by_owner=bytes.fromhex(signature_by_owner),
    )

    transaction_payload = TransactionPayload()
    transaction_payload.method = PubKeyMethod.STORE_AND_PAY
    transaction_payload.data = new_public_key_store_and_pay_payload.SerializeToString()

    serialized_transaction_payload = transaction_payload.SerializeToString()

    transaction_header = generate_header(
        serialized_transaction_payload, INPUTS, OUTPUTS, signer_public_key=PAYER_PUBLIC_KEY,
    )

    serialized_header = transaction_header.SerializeToString()

    transaction_request = TpProcessRequest(
        header=transaction_header,
        payload=serialized_transaction_payload,
        signature=create_signer(private_key=PAYER_PRIVATE_KEY).sign(serialized_header),
    )

    payer_account = Account()
    payer_account.balance = PAYER_INITIAL_BALANCE
    serialized_payer_account = payer_account.SerializeToString()

    owner_account = Account()
    owner_account.pub_keys.append(RANDOM_ALREADY_STORED_OWNER_PUBLIC_KEY_ADDRESS)
    serialized_owner_account = owner_account.SerializeToString()

    zero_account = Account()
    zero_account.balance = 0
    serialized_zero_account = zero_account.SerializeToString()

    is_economy_enabled_setting = Setting()
    is_economy_enabled_setting.entries.add(key='remme.economy_enabled', value='false')
    serialized_is_economy_enabled_setting = is_economy_enabled_setting.SerializeToString()

    mock_context = StubContext(inputs=INPUTS, outputs=OUTPUTS, initial_state={
        OWNER_ADDRESS: serialized_owner_account,
        PAYER_ADDRESS: serialized_payer_account,
        ZERO_ADDRESS: serialized_zero_account,
        IS_NODE_ECONOMY_ENABLED_ADDRESS: serialized_is_economy_enabled_setting,
    })

    expected_public_key_storage = PubKeyStorage()
    expected_public_key_storage.owner = OWNER_PUBLIC_KEY
    expected_public_key_storage.payload.CopyFrom(new_public_key_payload)
    expected_public_key_storage.is_revoked = False
    expected_serialized_public_key_storage = expected_public_key_storage.SerializeToString()

    expected_payer_account = Account()
    expected_payer_account.balance = PAYER_INITIAL_BALANCE
    serialized_expected_payer_account = expected_payer_account.SerializeToString()

    expected_owner_account = Account()
    expected_owner_account.pub_keys.append(RANDOM_ALREADY_STORED_OWNER_PUBLIC_KEY_ADDRESS)
    expected_owner_account.pub_keys.append(ADDRESS_FROM_CERTIFICATE_PUBLIC_KEY)
    serialized_expected_owner_account = expected_owner_account.SerializeToString()

    expected_zero_account = Account()
    expected_zero_account.balance = 0
    expected_serialized_zero_account = expected_zero_account.SerializeToString()

    expected_state = {
        OWNER_ADDRESS: serialized_expected_owner_account,
        PAYER_ADDRESS: serialized_expected_payer_account,
        ADDRESS_FROM_CERTIFICATE_PUBLIC_KEY: expected_serialized_public_key_storage,
        ZERO_ADDRESS: expected_serialized_zero_account,
    }

    PubKeyHandler().apply(transaction=transaction_request, context=mock_context)

    state_as_list = mock_context.get_state(addresses=[
        OWNER_ADDRESS, PAYER_ADDRESS, ADDRESS_FROM_CERTIFICATE_PUBLIC_KEY, ZERO_ADDRESS,
    ])

    state_as_dict = {entry.address: entry.data for entry in state_as_list}

    assert expected_state == state_as_dict
예제 #16
0
def test_public_key_handler_store_sender_is_node():
    """
    Case: send transaction request, to store certificate public key, when sender is node (same addresses).
    Expect: public key information is stored to blockchain linked to owner address. Owner hasn't paid for storing.
    """
    new_public_key_payload = generate_rsa_payload()

    transaction_payload = TransactionPayload()
    transaction_payload.method = PubKeyMethod.STORE
    transaction_payload.data = new_public_key_payload.SerializeToString()

    serialized_transaction_payload = transaction_payload.SerializeToString()

    transaction_header = generate_header(serialized_transaction_payload,
                                         INPUTS, OUTPUTS)

    serialized_header = transaction_header.SerializeToString()

    transaction_request = TpProcessRequest(
        header=transaction_header,
        payload=serialized_transaction_payload,
        signature=create_signer(
            private_key=SENDER_PRIVATE_KEY).sign(serialized_header),
    )

    sender_account = Account()
    sender_account.pub_keys.append(RANDOM_ALREADY_STORED_SENDER_PUBLIC_KEY)
    serialized_sender_account = sender_account.SerializeToString()

    zero_account = Account()
    serialized_zero_account = zero_account.SerializeToString()

    is_economy_enabled_setting = Setting()
    is_economy_enabled_setting.entries.add(key='remme.economy_enabled',
                                           value='false')
    serialized_is_economy_enabled_setting = is_economy_enabled_setting.SerializeToString(
    )

    mock_context = StubContext(inputs=INPUTS,
                               outputs=OUTPUTS,
                               initial_state={
                                   SENDER_ADDRESS: serialized_sender_account,
                                   IS_NODE_ECONOMY_ENABLED_ADDRESS:
                                   serialized_is_economy_enabled_setting,
                                   ZERO_ADDRESS: serialized_zero_account,
                               })

    expected_public_key_storage = PubKeyStorage()
    expected_public_key_storage.owner = SENDER_PUBLIC_KEY
    expected_public_key_storage.payload.CopyFrom(new_public_key_payload)
    expected_public_key_storage.is_revoked = False
    expected_serialized_public_key_storage = expected_public_key_storage.SerializeToString(
    )

    expected_sender_account = Account()
    expected_sender_account.pub_keys.append(
        RANDOM_ALREADY_STORED_SENDER_PUBLIC_KEY)
    expected_sender_account.pub_keys.append(
        ADDRESS_FROM_CERTIFICATE_PUBLIC_KEY)
    expected_serialized_sender_account = expected_sender_account.SerializeToString(
    )

    expected_zero_account = Account()
    expected_serialized_zero_account = expected_zero_account.SerializeToString(
    )

    expected_state = {
        SENDER_ADDRESS: expected_serialized_sender_account,
        ADDRESS_FROM_CERTIFICATE_PUBLIC_KEY:
        expected_serialized_public_key_storage,
        ZERO_ADDRESS: expected_serialized_zero_account,
    }

    PubKeyHandler().apply(transaction=transaction_request,
                          context=mock_context)

    state_as_list = mock_context.get_state(addresses=[
        SENDER_ADDRESS,
        ADDRESS_FROM_CERTIFICATE_PUBLIC_KEY,
        ZERO_ADDRESS,
    ])

    state_as_dict = {entry.address: entry.data for entry in state_as_list}

    assert expected_state == state_as_dict
예제 #17
0
def get_setting_from_key_value(key, value):
    setting = Setting()
    setting.entries.add(key=key, value=str(value).encode())

    return setting
예제 #18
0
def test_close_atomic_swap():
    """
    Case: close atomic swap.
    Expect: increase Alice account address by swap amount.
    """
    atomic_swap_close_payload = AtomicSwapClosePayload(
        swap_id=SWAP_ID,
        secret_key=SECRET_KEY,
    )

    transaction_payload = TransactionPayload()
    transaction_payload.method = AtomicSwapMethod.CLOSE
    transaction_payload.data = atomic_swap_close_payload.SerializeToString()

    serialized_transaction_payload = transaction_payload.SerializeToString()

    transaction_header = TransactionHeader(
        signer_public_key=BOT_PUBLIC_KEY,
        family_name=TRANSACTION_REQUEST_ACCOUNT_HANDLER_PARAMS.get(
            'family_name'),
        family_version=TRANSACTION_REQUEST_ACCOUNT_HANDLER_PARAMS.get(
            'family_version'),
        inputs=INPUTS,
        outputs=OUTPUTS,
        dependencies=[],
        payload_sha512=hash512(data=serialized_transaction_payload),
        batcher_public_key=RANDOM_NODE_PUBLIC_KEY,
        nonce=time.time().hex().encode(),
    )

    serialized_header = transaction_header.SerializeToString()

    transaction_request = TpProcessRequest(
        header=transaction_header,
        payload=serialized_transaction_payload,
        signature=create_signer(
            private_key=BOT_PRIVATE_KEY).sign(serialized_header),
    )

    alice_account = Account()
    alice_account.balance = 0
    serialized_alice_account = alice_account.SerializeToString()

    existing_swap_info_to_close = AtomicSwapInfo()
    existing_swap_info_to_close.swap_id = SWAP_ID
    existing_swap_info_to_close.amount = 200
    existing_swap_info_to_close.state = AtomicSwapInfo.APPROVED
    existing_swap_info_to_close.secret_lock = SECRET_LOCK
    existing_swap_info_to_close.is_initiator = True
    existing_swap_info_to_close.sender_address = BOT_ADDRESS
    existing_swap_info_to_close.receiver_address = ALICE_ADDRESS
    serialized_existing_swap_info_to_lock = existing_swap_info_to_close.SerializeToString(
    )

    genesis_members_setting = Setting()
    genesis_members_setting.entries.add(key=SETTINGS_KEY_ZERO_ADDRESS_OWNERS,
                                        value=f'{BOT_PUBLIC_KEY},')
    serialized_genesis_members_setting = genesis_members_setting.SerializeToString(
    )

    mock_context = StubContext(inputs=INPUTS,
                               outputs=OUTPUTS,
                               initial_state={
                                   ADDRESS_TO_GET_GENESIS_MEMBERS_AS_STRING_BY:
                                   serialized_genesis_members_setting,
                                   ADDRESS_TO_STORE_SWAP_INFO_BY:
                                   serialized_existing_swap_info_to_lock,
                                   ALICE_ADDRESS: serialized_alice_account,
                               })

    expected_alice_account = Account()
    expected_alice_account.balance = TOKENS_AMOUNT_TO_SWAP
    serialized_expected_alice_account = expected_alice_account.SerializeToString(
    )

    expected_closed_swap_info = AtomicSwapInfo()
    expected_closed_swap_info.swap_id = SWAP_ID
    expected_closed_swap_info.amount = 200
    expected_closed_swap_info.state = AtomicSwapInfo.CLOSED
    expected_closed_swap_info.secret_lock = SECRET_LOCK
    expected_closed_swap_info.secret_key = SECRET_KEY
    expected_closed_swap_info.is_initiator = True
    expected_closed_swap_info.sender_address = BOT_ADDRESS
    expected_closed_swap_info.receiver_address = ALICE_ADDRESS
    serialized_expected_closed_swap_info = expected_closed_swap_info.SerializeToString(
    )

    expected_state = {
        ADDRESS_TO_STORE_SWAP_INFO_BY: serialized_expected_closed_swap_info,
        ALICE_ADDRESS: serialized_expected_alice_account,
    }

    AtomicSwapHandler().apply(transaction=transaction_request,
                              context=mock_context)

    state_as_list = mock_context.get_state(
        addresses=[ADDRESS_TO_STORE_SWAP_INFO_BY, ALICE_ADDRESS])
    state_as_dict = {entry.address: entry.data for entry in state_as_list}

    assert expected_state == state_as_dict
예제 #19
0
def test_expire_atomic_swap():
    """
    Case: to expire atomic swap.
    Expect: increase bot address balance by swap amount. Leave commission on zero address.
    """
    atomic_swap_expire_payload = AtomicSwapExpirePayload(swap_id=SWAP_ID, )

    transaction_payload = TransactionPayload()
    transaction_payload.method = AtomicSwapMethod.EXPIRE
    transaction_payload.data = atomic_swap_expire_payload.SerializeToString()

    serialized_transaction_payload = transaction_payload.SerializeToString()

    transaction_header = TransactionHeader(
        signer_public_key=BOT_PUBLIC_KEY,
        family_name=TRANSACTION_REQUEST_ACCOUNT_HANDLER_PARAMS.get(
            'family_name'),
        family_version=TRANSACTION_REQUEST_ACCOUNT_HANDLER_PARAMS.get(
            'family_version'),
        inputs=INPUTS,
        outputs=OUTPUTS,
        dependencies=[],
        payload_sha512=hash512(data=serialized_transaction_payload),
        batcher_public_key=RANDOM_NODE_PUBLIC_KEY,
        nonce=time.time().hex().encode(),
    )

    serialized_header = transaction_header.SerializeToString()

    transaction_request = TpProcessRequest(
        header=transaction_header,
        payload=serialized_transaction_payload,
        signature=create_signer(
            private_key=BOT_PRIVATE_KEY).sign(serialized_header),
    )

    bot_account = Account()
    bot_account.balance = 4700
    serialized_bot_account = bot_account.SerializeToString()

    genesis_members_setting = Setting()
    genesis_members_setting.entries.add(key=SETTINGS_KEY_ZERO_ADDRESS_OWNERS,
                                        value=f'{BOT_PUBLIC_KEY},')
    serialized_genesis_members_setting = genesis_members_setting.SerializeToString(
    )

    existing_swap_info = AtomicSwapInfo()
    existing_swap_info.swap_id = SWAP_ID
    existing_swap_info.state = AtomicSwapInfo.OPENED
    existing_swap_info.amount = TOKENS_AMOUNT_TO_SWAP
    existing_swap_info.created_at = CURRENT_TIMESTAMP // 2
    existing_swap_info.sender_address = BOT_ADDRESS
    existing_swap_info.receiver_address = ALICE_ADDRESS
    existing_swap_info.is_initiator = True
    serialized_existing_swap_info = existing_swap_info.SerializeToString()

    mock_context = StubContext(inputs=INPUTS,
                               outputs=OUTPUTS,
                               initial_state={
                                   BLOCK_INFO_CONFIG_ADDRESS:
                                   SERIALIZED_BLOCK_INFO_CONFIG,
                                   BLOCK_INFO_ADDRESS:
                                   SERIALIZED_BLOCK_INFO,
                                   BOT_ADDRESS:
                                   serialized_bot_account,
                                   ADDRESS_TO_STORE_SWAP_INFO_BY:
                                   serialized_existing_swap_info,
                                   ADDRESS_TO_GET_GENESIS_MEMBERS_AS_STRING_BY:
                                   serialized_genesis_members_setting,
                               })

    expected_bot_account = Account()
    expected_bot_account.balance = 4700 + TOKENS_AMOUNT_TO_SWAP
    serialized_expected_bot_account = expected_bot_account.SerializeToString()

    expected_swap_info = AtomicSwapInfo()
    expected_swap_info.swap_id = SWAP_ID
    expected_swap_info.state = AtomicSwapInfo.EXPIRED
    expected_swap_info.amount = TOKENS_AMOUNT_TO_SWAP
    expected_swap_info.created_at = CURRENT_TIMESTAMP // 2
    expected_swap_info.sender_address = BOT_ADDRESS
    expected_swap_info.receiver_address = ALICE_ADDRESS
    expected_swap_info.is_initiator = True
    serialized_expected_swap_info = expected_swap_info.SerializeToString()

    expected_state = {
        BOT_ADDRESS: serialized_expected_bot_account,
        ADDRESS_TO_STORE_SWAP_INFO_BY: serialized_expected_swap_info,
    }

    AtomicSwapHandler().apply(transaction=transaction_request,
                              context=mock_context)

    state_as_list = mock_context.get_state(addresses=[
        ADDRESS_TO_STORE_SWAP_INFO_BY,
        BOT_ADDRESS,
    ])
    state_as_dict = {entry.address: entry.data for entry in state_as_list}

    assert expected_state == state_as_dict
예제 #20
0
def test_atomic_swap_init():
    """
    Case: initialize swap of bot's Remme node tokens to Alice's ERC20 Remme tokens.
    Expect: bot sends commission to the zero account address, swap amount is decreased from bot account.
    """

    atomic_swap_init_payload = AtomicSwapInitPayload(
        receiver_address=ALICE_ADDRESS,
        sender_address_non_local=BOT_ETHEREUM_ADDRESS,
        amount=TOKENS_AMOUNT_TO_SWAP,
        swap_id=SWAP_ID,
        secret_lock_by_solicitor=BOT_IT_IS_INITIATOR_MARK,
        email_address_encrypted_by_initiator=ALICE_EMAIL_ADDRESS_ENCRYPTED_BY_INITIATOR,
        created_at=CURRENT_TIMESTAMP,
    )

    transaction_payload = TransactionPayload()
    transaction_payload.method = AtomicSwapMethod.INIT
    transaction_payload.data = atomic_swap_init_payload.SerializeToString()

    serialized_transaction_payload = transaction_payload.SerializeToString()

    transaction_header = TransactionHeader(
        signer_public_key=BOT_PUBLIC_KEY,
        family_name=TRANSACTION_REQUEST_ACCOUNT_HANDLER_PARAMS.get('family_name'),
        family_version=TRANSACTION_REQUEST_ACCOUNT_HANDLER_PARAMS.get('family_version'),
        inputs=INPUTS,
        outputs=OUTPUTS,
        dependencies=[],
        payload_sha512=hash512(data=serialized_transaction_payload),
        batcher_public_key=RANDOM_NODE_PUBLIC_KEY,
        nonce=time.time().hex().encode(),
    )

    serialized_header = transaction_header.SerializeToString()

    transaction_request = TpProcessRequest(
        header=transaction_header,
        payload=serialized_transaction_payload,
        signature=create_signer(private_key=BOT_PRIVATE_KEY).sign(serialized_header),
    )

    bot_account = Account()
    bot_account.balance = 5000
    serialized_bot_account = bot_account.SerializeToString()

    zero_account = Account()
    zero_account.balance = 0
    serialized_zero_account = zero_account.SerializeToString()

    swap_commission_setting = Setting()
    swap_commission_setting.entries.add(key=SETTINGS_SWAP_COMMISSION, value=str(SWAP_COMMISSION_AMOUNT))
    serialized_swap_commission_setting = swap_commission_setting.SerializeToString()

    genesis_members_setting = Setting()
    genesis_members_setting.entries.add(key=SETTINGS_KEY_ZERO_ADDRESS_OWNERS, value=f'{BOT_PUBLIC_KEY},')
    serialized_genesis_members_setting = genesis_members_setting.SerializeToString()

    mock_context = StubContext(inputs=INPUTS, outputs=OUTPUTS, initial_state={
        BLOCK_INFO_CONFIG_ADDRESS: SERIALIZED_BLOCK_INFO_CONFIG,
        BLOCK_INFO_ADDRESS: SERIALIZED_BLOCK_INFO,
        BOT_ADDRESS: serialized_bot_account,
        ZERO_ADDRESS: serialized_zero_account,
        ADDRESS_TO_GET_SWAP_COMMISSION_AMOUNT_BY: serialized_swap_commission_setting,
        ADDRESS_TO_GET_GENESIS_MEMBERS_AS_STRING_BY: serialized_genesis_members_setting,
    })

    swap_info = AtomicSwapInfo()
    swap_info.swap_id = SWAP_ID
    swap_info.state = AtomicSwapInfo.OPENED
    swap_info.amount = TOKENS_AMOUNT_TO_SWAP
    swap_info.created_at = CURRENT_TIMESTAMP
    swap_info.email_address_encrypted_optional = ALICE_EMAIL_ADDRESS_ENCRYPTED_BY_INITIATOR
    swap_info.sender_address = BOT_ADDRESS
    swap_info.sender_address_non_local = BOT_ETHEREUM_ADDRESS
    swap_info.receiver_address = ALICE_ADDRESS
    swap_info.is_initiator = True
    serialized_swap_info = swap_info.SerializeToString()

    expected_bot_account = Account()
    expected_bot_account.balance = 5000 - TOKENS_AMOUNT_TO_SWAP - SWAP_COMMISSION_AMOUNT
    serialized_expected_bot_account = expected_bot_account.SerializeToString()

    expected_zero_account = Account()
    expected_zero_account.balance = SWAP_COMMISSION_AMOUNT
    serialized_expected_zero_account = expected_zero_account.SerializeToString()

    expected_state = {
        BOT_ADDRESS: serialized_expected_bot_account,
        ZERO_ADDRESS: serialized_expected_zero_account,
        ADDRESS_TO_STORE_SWAP_INFO_BY: serialized_swap_info,
    }

    AtomicSwapHandler().apply(transaction=transaction_request, context=mock_context)

    state_as_list = mock_context.get_state(addresses=[
        ADDRESS_TO_STORE_SWAP_INFO_BY, BOT_ADDRESS, ZERO_ADDRESS,
    ])
    state_as_dict = {entry.address: entry.data for entry in state_as_list}

    assert expected_state == state_as_dict