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.state = AtomicSwapInfo.EXPIRED 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 test_account_handler_apply_decode_error(): """ Case: send transaction request, to send tokens to address, to account handler with invalid transaction payload. Expect: invalid transaction error is raised cannot decode transaction payload error message. """ serialized_not_valid_transaction_payload = b'F1120071db7c02f5731d06df194dc95465e9b27' transaction_header = TransactionHeader( signer_public_key=RANDOM_NODE_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_not_valid_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_not_valid_transaction_payload, signature=create_signer(private_key=ACCOUNT_FROM_PRIVATE_KEY).sign(serialized_header), ) mock_context = create_context(account_from_balance=ACCOUNT_FROM_BALANCE, account_to_balance=ACCOUNT_TO_BALANCE) with pytest.raises(InvalidTransaction) as error: AccountHandler().apply(transaction=transaction_request, context=mock_context) assert 'Cannot decode transaction payload.' == str(error.value)
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.state != AtomicSwapInfo.SECRET_LOCK_PROVIDED: raise InvalidTransaction('Swap id {} is already closed.'.format( swap_info.swap_id)) swap_info.state = AtomicSwapInfo.APPROVED return self.get_state_update(swap_info)
def _swap_close(self, context, signer_pubkey, swap_close_payload): """ Bob or Alice closes the swap by providing the secret key which matches secret lock. Requires "is_approved = True" Requires hash of secret key to match secret lock """ swap_info = self.get_swap_info_from_swap_id(context, swap_close_payload.swap_id) if not swap_info.secret_lock: raise InvalidTransaction( 'Secret lock is required to close the swap!') if web3_hash(swap_close_payload.secret_key) != swap_info.secret_lock: raise InvalidTransaction( 'Secret key doesn\'t match specified secret lock!') if swap_info.is_initiator and swap_info.state != AtomicSwapInfo.APPROVED: raise InvalidTransaction( 'Transaction cannot be closed before it\'s approved.') transfer_payload = AccountClient.get_transfer_payload( swap_info.receiver_address, swap_info.amount) token_updated_state = AccountHandler()._transfer_from_address( context, ZERO_ADDRESS, transfer_payload) swap_info.state = AtomicSwapInfo.CLOSED return {**self.get_state_update(swap_info), **token_updated_state}
def test_account_handler_apply(): """ Case: send transaction request, to send tokens to address, to the account handler. Expect: addresses data, stored in state, are changed according to transfer amount. """ expected_account_from_balance = ACCOUNT_FROM_BALANCE - TOKENS_AMOUNT_TO_SEND expected_account_to_balance = ACCOUNT_TO_BALANCE + TOKENS_AMOUNT_TO_SEND account_protobuf = Account() account_protobuf.balance = expected_account_from_balance expected_serialized_account_from_balance = account_protobuf.SerializeToString() account_protobuf.balance = expected_account_to_balance expected_serialized_account_to_balance = account_protobuf.SerializeToString() expected_state = { ACCOUNT_ADDRESS_FROM: expected_serialized_account_from_balance, ACCOUNT_ADDRESS_TO: expected_serialized_account_to_balance, } transfer_payload = TransferPayload() transfer_payload.address_to = ACCOUNT_ADDRESS_TO transfer_payload.value = TOKENS_AMOUNT_TO_SEND transaction_payload = TransactionPayload() transaction_payload.method = AccountMethod.TRANSFER transaction_payload.data = transfer_payload.SerializeToString() serialized_transaction_payload = transaction_payload.SerializeToString() transaction_header = TransactionHeader( signer_public_key=RANDOM_NODE_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=ACCOUNT_FROM_PRIVATE_KEY).sign(serialized_header), ) mock_context = create_context(account_from_balance=ACCOUNT_FROM_BALANCE, account_to_balance=ACCOUNT_TO_BALANCE) AccountHandler().apply(transaction=transaction_request, context=mock_context) state_as_list = mock_context.get_state(addresses=[ACCOUNT_ADDRESS_TO, ACCOUNT_ADDRESS_FROM]) state_as_dict = {entry.address: entry.data for entry in state_as_list} assert expected_state == state_as_dict
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 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 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 test_store_success(self): context = self.get_context() cert, key, _ = PubKeyClient.create_certificate( context.pub_key_payload, signer=context.client.get_signer()) transaction_signature, cert_address, transaction_payload = self._pre_parse_payload_and_exec( context, cert, key) crt_export, crt_bin, crt_sig, rem_sig, pub_key, \ valid_from, valid_to = PubKeyClient.get_crt_export_bin_sig_rem_sig(cert, key, context.client) account = AccountClient.get_account_model(PUB_KEY_STORE_PRICE) storage_account = AccountClient.get_account_model(0) storage_signer = self.get_new_signer() storage_pub_key = storage_signer.get_public_key().as_hex() storage_address = AccountHandler().make_address_from_data( storage_pub_key) data = PubKeyStorage() data.owner = self.account_signer1.get_public_key().as_hex() data.payload.CopyFrom(transaction_payload) data.revoked = False self.expect_get({cert_address: None, self.account_address1: account}) self.expect_get({_make_settings_key('remme.economy_enabled'): None}) self.expect_get({ _make_settings_key(SETTINGS_STORAGE_PUB_KEY): get_setting_from_key_value(SETTINGS_STORAGE_PUB_KEY, storage_pub_key) }) self.expect_get({ self.account_address1: account, storage_address: storage_account }) context.client.store_pub_key(pub_key, rem_sig, crt_sig, valid_from, valid_to) account.balance -= PUB_KEY_STORE_PRICE account.pub_keys.append(cert_address) storage_account.balance += PUB_KEY_STORE_PRICE self.expect_set( transaction_signature, PubKeyMethod.STORE, { self.account_address1: account, cert_address: data, storage_address: storage_account }) self.expect_ok()
def test_account_handler_genesis_already_initialized(): """ Case: send transaction request, to send tokens from genesis address, to the account handler when genesis was already initialized. Expect: invalid transaction error is raised with genesis is already initialized error message. """ genesis_payload = GenesisPayload() genesis_payload.total_supply = TOKENS_AMOUNT_TO_SUPPLY transaction_payload = TransactionPayload() transaction_payload.method = AccountMethod.GENESIS transaction_payload.data = genesis_payload.SerializeToString() serialized_transaction_payload = transaction_payload.SerializeToString() transaction_header = TransactionHeader( signer_public_key=NODE_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=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=NODE_PRIVATE_KEY).sign(serialized_header), ) genesis_status = GenesisStatus() genesis_status.status = True mock_context = StubContext( inputs=INPUTS, outputs=OUTPUTS, initial_state={GENESIS_ADDRESS: genesis_status.SerializeToString()}) with pytest.raises(InvalidTransaction) as error: AccountHandler().apply(transaction=transaction_request, context=mock_context) assert f'Genesis is already initialized.' == str(error.value)
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.') block = self._get_latest_block_info(context) block_time = self.get_datetime_from_timestamp(block.timestamp) 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) > block_time: intiator_name = "initiator" \ if swap_info.is_initiator else "non initiator" raise InvalidTransaction(f'Swap {intiator_name} needs to wait ' f'{INTIATOR_TIME_LOCK} hours since ' f'timestamp: {swap_info.created_at} ' f'to withdraw.') swap_info.state = AtomicSwapInfo.EXPIRED 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 test_account_handler_genesis_apply_with_empty_proto(): """ Case: send transaction request of genesis with empty proto Expect: invalid transaction error """ genesis_payload = GenesisPayload() transaction_payload = TransactionPayload() transaction_payload.method = AccountMethod.GENESIS transaction_payload.data = genesis_payload.SerializeToString() serialized_transaction_payload = transaction_payload.SerializeToString() transaction_header = TransactionHeader( signer_public_key=NODE_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=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=NODE_PRIVATE_KEY).sign(serialized_header), ) mock_context = StubContext(inputs=INPUTS, outputs=OUTPUTS, initial_state={}) with pytest.raises(InvalidTransaction) as error: AccountHandler().apply(transaction=transaction_request, context=mock_context) assert proto_error_msg( GenesisPayload, {'total_supply': ['This field is required.']}) == str(error.value)
def test_account_transfer_from_address_to_address_not_account_type(): """ Case: transfer tokens from address to address that is not account type. Expect: invalid transaction error is raised with receiver address is not account type error message. """ mock_context = create_context(account_from_balance=ACCOUNT_FROM_BALANCE, account_to_balance=ACCOUNT_TO_BALANCE) transfer_payload = TransferPayload() transfer_payload.address_to = ADDRESS_NOT_ACCOUNT_TYPE transfer_payload.value = TOKENS_AMOUNT_TO_SEND transaction_payload = TransactionPayload() transaction_payload.method = AccountMethod.TRANSFER transaction_payload.data = transfer_payload.SerializeToString() serialized_transaction_payload = transaction_payload.SerializeToString() transaction_header = TransactionHeader( signer_public_key=RANDOM_NODE_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=ACCOUNT_FROM_PRIVATE_KEY).sign(serialized_header), ) with pytest.raises(InvalidTransaction) as error: AccountHandler().apply(transaction=transaction_request, context=mock_context) assert proto_error_msg( TransferPayload, { 'address_to': ['Address is not of a blockchain token type.'], } ) == str(error.value)
def test_account_transfer_from_address_without_previous_usage(): """ Case: transfer tokens from address to address when them have never been used before. Expect: invalid transaction error is raised with not enough transferable balance error message. """ initial_state = { ACCOUNT_ADDRESS_FROM: None, ACCOUNT_ADDRESS_TO: None, } mock_context = StubContext(inputs=INPUTS, outputs=OUTPUTS, initial_state=initial_state) transfer_payload = TransferPayload() transfer_payload.address_to = ACCOUNT_ADDRESS_TO transfer_payload.value = TOKENS_AMOUNT_TO_SEND transaction_payload = TransactionPayload() transaction_payload.method = AccountMethod.TRANSFER transaction_payload.data = transfer_payload.SerializeToString() serialized_transaction_payload = transaction_payload.SerializeToString() transaction_header = TransactionHeader( signer_public_key=RANDOM_NODE_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=ACCOUNT_FROM_PRIVATE_KEY).sign(serialized_header), ) with pytest.raises(InvalidTransaction) as error: AccountHandler().apply(transaction=transaction_request, context=mock_context) assert f'Not enough transferable balance. Sender\'s current balance: 0.' == str(error.value)
def test_account_handler_with_empty_proto(): """ Case: send transaction request with empty proto Expect: invalid transaction error """ transfer_payload = TransferPayload() transaction_payload = TransactionPayload() transaction_payload.method = AccountMethod.TRANSFER transaction_payload.data = transfer_payload.SerializeToString() serialized_transaction_payload = transaction_payload.SerializeToString() transaction_header = TransactionHeader( signer_public_key=RANDOM_NODE_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=ACCOUNT_FROM_PRIVATE_KEY).sign(serialized_header), ) mock_context = StubContext(inputs=INPUTS, outputs=OUTPUTS, initial_state={}) with pytest.raises(InvalidTransaction) as error: AccountHandler().apply(transaction=transaction_request, context=mock_context) assert proto_error_msg( TransferPayload, { 'address_to': ['Missed address'], 'value': ['Could not transfer with zero amount.'], } ) == str(error.value)
def test_account_handler_apply_invalid_transfer_method(): """ Case: send transaction request, to send tokens to address, to account handler with invalid transfer method value. Expect: invalid transaction error is raised with invalid account method value error message. """ account_method_impossible_value = 5347 transfer_payload = TransferPayload() transfer_payload.address_to = ACCOUNT_ADDRESS_TO transfer_payload.value = TOKENS_AMOUNT_TO_SEND transaction_payload = TransactionPayload() transaction_payload.method = account_method_impossible_value transaction_payload.data = transfer_payload.SerializeToString() serialized_transaction_payload = transaction_payload.SerializeToString() transaction_header = TransactionHeader( signer_public_key=RANDOM_NODE_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=ACCOUNT_FROM_PRIVATE_KEY).sign(serialized_header), ) mock_context = create_context(account_from_balance=ACCOUNT_FROM_BALANCE, account_to_balance=ACCOUNT_TO_BALANCE) with pytest.raises(InvalidTransaction) as error: AccountHandler().apply(transaction=transaction_request, context=mock_context) assert f'Invalid account method value ({account_method_impossible_value}) has been set.' == str(error.value)
AccountMethod, GenesisPayload, GenesisStatus, TransferPayload, ) from remme.protos.transaction_pb2 import TransactionPayload from remme.shared.utils import hash512 from remme.tp.account import AccountHandler from testing.conftest import create_signer from testing.mocks.stub import StubContext from testing.utils.client import proto_error_msg TOKENS_AMOUNT_TO_SUPPLY = 1_000_000 TRANSACTION_REQUEST_ACCOUNT_HANDLER_PARAMS = { 'family_name': AccountHandler().family_name, 'family_version': AccountHandler()._family_versions[0], } GENESIS_ADDRESS = '0000000000000000000000000000000000000000000000000000000000000000000001' ACCOUNT_ADDRESS_TO = '112007d71fa7e120c60fb392a64fd69de891a60c667d9ea9e5d9d9d617263be6c20202' INPUTS = OUTPUTS = [ GENESIS_ADDRESS, ACCOUNT_ADDRESS_TO, ] NODE_PUBLIC_KEY = '039d6881f0a71d05659e1f40b443684b93c7b7c504ea23ea8949ef5216a2236940' NODE_PRIVATE_KEY = '1cb15ecfe1b3dc02df0003ac396037f85b98cf9f99b0beae000dc5e9e8b6dab4'
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ------------------------------------------------------------------------ import argparse from sawtooth_sdk.processor.core import TransactionProcessor from remme.tp.atomic_swap import AtomicSwapHandler from remme.tp.pub_key import PubKeyHandler from remme.tp.account import AccountHandler from remme.shared.logging import setup_logging from remme.settings.default import load_toml_with_defaults TP_HANDLERS = [AccountHandler(), PubKeyHandler(), AtomicSwapHandler()] if __name__ == '__main__': config = load_toml_with_defaults( '/config/remme-client-config.toml')['remme']['client'] parser = argparse.ArgumentParser(description='Transaction processor.') parser.add_argument('-v', '--verbosity', type=int, default=2) parser.add_argument('--account', action='store_true') parser.add_argument('--atomic-swap', action='store_true') parser.add_argument('--pubkey', action='store_true') args = parser.parse_args() setup_logging('remme', args.verbosity) processor = TransactionProcessor( url=f'tcp://{ config["validator_ip"] }:{ config["validator_port"] }')
# limitations under the License. # ------------------------------------------------------------------------ # pylint: disable=invalid-name import argparse from sawtooth_sdk.processor.core import TransactionProcessor from remme.tp.atomic_swap import AtomicSwapHandler from remme.tp.pub_key import PubKeyHandler from remme.tp.account import AccountHandler from remme.shared.logging_setup import setup_logging from remme.settings.default import load_toml_with_defaults TP_HANDLERS = [AccountHandler(), PubKeyHandler(), AtomicSwapHandler()] if __name__ == '__main__': config = load_toml_with_defaults( '/config/remme-client-config.toml')['remme']['client'] parser = argparse.ArgumentParser(description='Transaction processor.') parser.add_argument('-v', '--verbosity', type=int, default=2) args = parser.parse_args() setup_logging('remme-tp', args.verbosity) processor = TransactionProcessor( url=f'tcp://{ config["validator_ip"] }:{ config["validator_port"] }') for handler in TP_HANDLERS: processor.add_handler(handler) try:
OUTPUT_BATCH = '/genesis/batch/token-proposal.batch' if __name__ == '__main__': parameters = load_toml_with_defaults( '/config/remme-genesis-config.toml')['remme']['genesis'] parser = argparse.ArgumentParser( description='File with a public key to assign initial supply.') parser.add_argument('--token-supply', default=parameters['token_supply']) args = parser.parse_args() account_client = AccountClient() if parameters['economy_enabled']: 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 = [GENESIS_ADDRESS] addresses_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,
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
def get_user_address(self): return AccountHandler.make_address_from_data( self._signer.get_public_key().as_hex())
def get_user_address(self): from remme.tp.account import AccountHandler return AccountHandler().make_address_from_data(self._signer.get_public_key().as_hex())
def test_account_handler_genesis_apply(): """ Case: send transaction request, to send tokens from genesis address, to the account handler. Expect: """ account = Account() account.balance = TOKENS_AMOUNT_TO_SUPPLY expected_serialized_account_to_balance = account.SerializeToString() genesis_payload = GenesisPayload() genesis_payload.total_supply = TOKENS_AMOUNT_TO_SUPPLY transaction_payload = TransactionPayload() transaction_payload.method = AccountMethod.GENESIS transaction_payload.data = genesis_payload.SerializeToString() serialized_transaction_payload = transaction_payload.SerializeToString() transaction_header = TransactionHeader( signer_public_key=NODE_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=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=NODE_PRIVATE_KEY).sign(serialized_header), ) genesis_status = GenesisStatus() genesis_status.status = True expected_state = { GENESIS_ADDRESS: genesis_status.SerializeToString(), ACCOUNT_ADDRESS_TO: expected_serialized_account_to_balance, } mock_context = StubContext(inputs=INPUTS, outputs=OUTPUTS, initial_state={}) AccountHandler().apply(transaction=transaction_request, context=mock_context) state_as_list = mock_context.get_state( addresses=[GENESIS_ADDRESS, ACCOUNT_ADDRESS_TO]) state_as_dict = {entry.address: entry.data for entry in state_as_list} assert expected_state == state_as_dict
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.state = AtomicSwapInfo.OPENED 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 # 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}
# pylint: disable=invalid-name import argparse from sawtooth_sdk.processor.core import TransactionProcessor from remme.tp.atomic_swap import AtomicSwapHandler from remme.tp.pub_key import PubKeyHandler from remme.tp.account import AccountHandler from remme.shared.logging_setup import setup_logging from remme.settings.default import load_toml_with_defaults TP_HANDLERS = { handler._family_name: handler for handler in (AccountHandler(), PubKeyHandler(), AtomicSwapHandler()) } if __name__ == '__main__': config = load_toml_with_defaults( '/config/remme-client-config.toml')['remme']['client'] parser = argparse.ArgumentParser(description='Transaction processor.') parser.add_argument('-v', '--verbosity', type=int, default=2) args = parser.parse_args() setup_logging('remme-tp', args.verbosity) processor = TransactionProcessor( url=f'tcp://{ config["validator_ip"] }:{ config["validator_port"] }') for handler in TP_HANDLERS.values(): processor.add_handler(handler)