def setUpClass(cls, handler, client_class=None): url = os.getenv('TEST_BIND', 'tcp://127.0.0.1:4004') cls.validator = RemmeMockValidator() cls.validator.listen(url) for item in TP_HANDLERS: if not cls.validator.register_processor(): raise Exception('Failed to register processor') cls.factory = None cls._zmq_patcher = mock.patch('remme.clients.basic.Stream', return_value=cls.validator) cls._zmq_patcher_obj = cls._zmq_patcher.start() cls.handler = handler cls.client_class = client_class cls._pk_patcher = mock.patch( 'remme.clients.basic.BasicClient.get_signer_priv_key_from_file', return_value=BasicClient.generate_signer()) cls._pk_patcher_obj = cls._pk_patcher.start() # generate token account addresses cls.account_signer1 = cls.get_new_signer() cls.account_address1 = AccountHandler.make_address_from_data( cls.account_signer1.get_public_key().as_hex()) cls.account_signer2 = cls.get_new_signer() cls.account_address2 = AccountHandler.make_address_from_data( cls.account_signer2.get_public_key().as_hex()) cls._factory = cls.handler.get_message_factory(cls.account_signer1)
def _swap_expire(self, context, signer_pubkey, swap_expire_payload): """ Transaction initiator (Alice) decides to withdraw deposit in 24 hours, or Bob in 48 hours """ swap_info = self.get_swap_info_from_swap_id( context, swap_expire_payload.swap_id) if AccountHandler.make_address_from_data( signer_pubkey) != swap_info.sender_address: raise InvalidTransaction( 'Signer is not the one who opened the swap.') now = datetime.datetime.utcnow() created_at = self.get_datetime_from_timestamp(swap_info.created_at) time_delta = INITIATOR_TIME_DELTA_LOCK if swap_info.is_initiator else NON_INITIATOR_TIME_DELTA_LOCK if (created_at + time_delta) > now: intiator_name = "initiator" if swap_info.is_initiator else "non initiator" raise InvalidTransaction( 'Swap {} needs to wait {} hours since timestamp: {} to withdraw.' .format(intiator_name, INTIATOR_TIME_LOCK, swap_info.created_at)) swap_info.is_closed = True transfer_payload = AccountClient.get_transfer_payload( swap_info.sender_address, swap_info.amount) token_updated_state = AccountHandler._transfer_from_address( context, ZERO_ADDRESS, transfer_payload) return {**self.get_state_update(swap_info), **token_updated_state}
def _swap_approve(self, context, signer_pubkey, swap_approve_payload): """ Only called by Alice to approve REMchain => other transaction for Bob to close it. """ LOGGER.info('swap id: {}'.format(swap_approve_payload.swap_id)) swap_info = self.get_swap_info_from_swap_id( context, swap_approve_payload.swap_id) if not swap_info.is_initiator or swap_info.sender_address != AccountHandler.make_address_from_data( signer_pubkey): raise InvalidTransaction( 'Only transaction initiator (Alice) may approve the swap, ' 'once Bob provided a secret lock.') if not swap_info.secret_lock: raise InvalidTransaction( 'Secret Lock is needed for Bob to provide a secret key.') if swap_info.is_closed: raise InvalidTransaction('Swap id {} is already closed.'.format( swap_info.swap_id)) swap_info.is_approved = True return self.get_state_update(swap_info)
def store_pub_key(self, public_key, entity_hash, entity_hash_signature, valid_from, valid_to): payload = self.get_new_pub_key_payload(public_key, entity_hash, entity_hash_signature, valid_from, valid_to) crt_address = self.make_address_from_data(public_key) account_address = AccountHandler.make_address_from_data(self._signer.get_public_key().as_hex()) settings_address = _make_settings_key('remme.economy_enabled') addresses_input = [crt_address, account_address, settings_address, self.get_user_address()] addresses_output = [crt_address, self.get_user_address()] return self._send_transaction(PubKeyMethod.STORE, payload, addresses_input, addresses_output), crt_address
def store_pub_key(self, public_key, entity_hash, entity_hash_signature, valid_from, valid_to): payload = self.get_new_pub_key_payload(public_key, entity_hash, entity_hash_signature, valid_from, valid_to) crt_address = self.make_address_from_data(public_key) account_address = AccountHandler.make_address_from_data( self._signer.get_public_key().as_hex()) return self._send_transaction( PubKeyMethod.STORE, payload, [crt_address, account_address]), crt_address
def get_user_address(self): return AccountHandler.make_address_from_data( self._signer.get_public_key().as_hex())
def _store_pub_key(self, context, signer_pubkey, transaction_payload): address = self.make_address_from_data(transaction_payload.public_key) LOGGER.info('Pub key address {}'.format(address)) account_address = AccountHandler.make_address_from_data(signer_pubkey) LOGGER.info('Account address {}'.format(address)) data, account = get_multiple_data(context, [(address, PubKeyStorage), (account_address, Account)]) if data: raise InvalidTransaction('This pub key is already registered.') cert_signer_pubkey = load_pem_public_key( transaction_payload.public_key.encode('utf-8'), backend=default_backend()) try: ehs_bytes = binascii.unhexlify( transaction_payload.entity_hash_signature) eh_bytes = binascii.unhexlify(transaction_payload.entity_hash) except binascii.Error: LOGGER.debug( f'entity_hash_signature {transaction_payload.entity_hash_signature}' ) LOGGER.debug(f'entity_hash {transaction_payload.entity_hash}') raise InvalidTransaction( 'Entity hash or signature not a hex format') # FIXME: For support PKCS1v15 and PSS LOGGER.warn('HAZARD: Detecting padding for verification') sigerr = 0 pkcs = padding.PKCS1v15() pss = padding.PSS(mgf=padding.MGF1(hashes.SHA512()), salt_length=padding.PSS.MAX_LENGTH) for _padding in (pkcs, pss): try: cert_signer_pubkey.verify(ehs_bytes, eh_bytes, _padding, hashes.SHA512()) LOGGER.warn('HAZARD: Padding found: %s', _padding.name) except InvalidSignature: sigerr += 1 if sigerr == 2: raise InvalidTransaction('Invalid signature') valid_from = datetime.fromtimestamp(transaction_payload.valid_from) valid_to = datetime.fromtimestamp(transaction_payload.valid_to) if valid_to - valid_from > PUB_KEY_MAX_VALIDITY: raise InvalidTransaction( 'The public key validity exceeds the maximum value.') data = PubKeyStorage() data.owner = signer_pubkey data.payload.CopyFrom(transaction_payload) data.revoked = False if not account: account = Account() if _get_setting_value(context, 'remme.economy_enabled', 'true').lower() == 'true': if account.balance < PUB_KEY_STORE_PRICE: raise InvalidTransaction( 'Not enough tokens to register a new pub key. Current balance: {}' .format(account.balance)) account.balance -= PUB_KEY_STORE_PRICE if address not in account.pub_keys: account.pub_keys.append(address) return {address: data, account_address: account}
def _swap_init(self, context, signer_pubkey, swap_init_payload): """ if SecretLockOptionalBob is provided, Bob uses _swap_init to respond to requested swap Otherwise, Alice uses _swap_init to request a swap and thus, Bob can't receive funds until Alice "approves". """ LOGGER.info("0. Check if swap ID already exists") # 0. Check if swap ID already exists if self.get_swap_info_from_swap_id(context, swap_init_payload.swap_id, to_raise_exception=False): raise InvalidTransaction( 'Atomic swap ID has already been taken, please use a different one!' ) # END swap_info = AtomicSwapInfo() swap_info.swap_id = swap_init_payload.swap_id swap_info.is_closed = False swap_info.amount = swap_init_payload.amount swap_info.created_at = swap_init_payload.created_at swap_info.email_address_encrypted_optional = swap_init_payload.email_address_encrypted_by_initiator swap_info.sender_address = AccountHandler.make_address_from_data( signer_pubkey) swap_info.sender_address_non_local = swap_init_payload.sender_address_non_local swap_info.receiver_address = swap_init_payload.receiver_address if not AccountHandler.is_handler_address(swap_info.receiver_address): raise InvalidTransaction( 'Receiver address is not of a Token type.') LOGGER.info("1. Ensure transaction initiated within an hour") # 1. Ensure transaction initiated within an hour swap_info.secret_lock = swap_init_payload.secret_lock_by_solicitor created_at = self.get_datetime_from_timestamp(swap_info.created_at) now = datetime.datetime.utcnow() if not (now - datetime.timedelta(hours=1) < created_at < now): raise InvalidTransaction( 'Transaction is created a long time ago or timestamp is assigned set.' ) # END LOGGER.info("2. Check weather the sender is Alice") # 2. Check weather the sender is Alice: swap_info.is_initiator = not swap_init_payload.secret_lock_by_solicitor # if Bob swap_info.is_approved = not swap_info.is_initiator # END # 3. Transfer funds to zero address. LOGGER.info("3. Transfer funds to zero address") commission = int(_get_setting_value(context, SETTINGS_SWAP_COMMISSION)) if commission < 0: raise InvalidTransaction('Wrong commission address.') LOGGER.info("4. Get sender's account {}".format( swap_info.sender_address)) account = get_account_by_address(context, swap_info.sender_address) total_amount = swap_info.amount + commission if account.balance < total_amount: raise InvalidTransaction( 'Not enough balance to perform the transaction in ' 'the amount (with a commission) {}.'.format(total_amount)) transfer_payload = AccountClient.get_transfer_payload( ZERO_ADDRESS, total_amount) token_updated_state = AccountHandler._transfer_from_address( context, swap_info.sender_address, transfer_payload) LOGGER.info("Save state") return {**self.get_state_update(swap_info), **token_updated_state}
def is_valid_token_balance(): account_client = AccountClient() signer_pub_key = account_client.get_signer().get_public_key().as_hex() signer_balance = account_client.get_balance( AccountHandler.make_address_from_data(signer_pub_key)) return signer_balance >= PUB_KEY_STORE_PRICE
from remme.tp.account import AccountHandler, TransactionPayload from remme.settings import GENESIS_ADDRESS, ENABLE_ECONOMY OUTPUT_BATCH = '/genesis/batch/token-proposal.batch' if __name__ == '__main__': parser = argparse.ArgumentParser( description='File with a public key to assign initial supply.') parser.add_argument('token_supply') args = parser.parse_args() account_client = AccountClient() if ENABLE_ECONOMY: zero_address = AccountHandler.make_address('0' * 64) target_address = AccountHandler.make_address_from_data( account_client.get_signer().get_public_key().as_hex()) print('Issuing {} tokens to address {}'.format(args.token_supply, target_address)) addresses_input_output = [GENESIS_ADDRESS, target_address] payload = TransactionPayload() payload.method = AccountMethod.GENESIS payload.data = account_client.get_genesis_payload( args.token_supply).SerializeToString() batch_list = AccountClient().make_batch_list(payload, addresses_input_output) batch_file = open(OUTPUT_BATCH, 'wb')