def test_create_negative_fee(self, m_logger): with self.assertRaises(ValueError): TransferTransaction.create(addrs_to=[self.bob.address], amounts=[-100], message_data=None, fee=-1, xmss_pk=self.alice.pk)
def test_get_mini_transactions_by_address(self, mock_get_tx_metadata, mock_get_optimized_address_state, mock_get_paginated_data): """ xrdNode.get_transactions_by_address() returns all the changes in balance caused by a transaction. """ get_tx_metadata = GetTXMetadata() xmss = get_alice_xmss() xmss2 = get_random_xmss() addr_state = OptimizedAddressState.get_default(xmss.address) addr_state.pbdata.balance = 100 addr_state.pbdata.transaction_hash_count = 3 mock_get_optimized_address_state.return_value = addr_state tx1 = CoinBase.create(config.dev, 100, xmss.address, 5) get_tx_metadata.register_tx_metadata(tx1, 1) tx2 = TransferTransaction.create(addrs_to=[xmss2.address], amounts=[10], message_data=None, fee=1, xmss_pk=xmss.pk) tx2.sign(xmss) get_tx_metadata.register_tx_metadata(tx2, 1) tx3 = TransferTransaction.create(addrs_to=[xmss.address], amounts=[100], message_data=None, fee=1, xmss_pk=xmss2.pk) tx3.sign(xmss) get_tx_metadata.register_tx_metadata(tx3, 2) mock_get_paginated_data.return_value = [ tx1.txhash, tx2.txhash, tx3.txhash ] mock_get_tx_metadata.side_effect = get_tx_metadata.get_tx_metadata response = self.xrdnode.get_mini_transactions_by_address( alice.address, 3, 1) result, balance = response.mini_transactions, response.balance self.assertEqual(len(result), 3) self.assertEqual(result[0].amount, 100) self.assertEqual(result[0].out, False) self.assertEqual(result[1].amount, 11) self.assertEqual(result[1].out, True) self.assertEqual(result[2].amount, 100) self.assertEqual(result[2].out, False) self.assertEqual(balance, 100)
def setUp(self): with set_xrd_dir('no_data'): self.state = State() self.chain_manager = ChainManager(self.state) self.alice = get_alice_xmss() self.bob = get_bob_xmss() self.slave = get_slave_xmss() self.tx1 = TransferTransaction.create(addrs_to=[self.bob.address], amounts=[10], message_data=None, fee=1, xmss_pk=self.alice.pk) self.tx2 = TransferTransaction.create(addrs_to=[self.bob.address], amounts=[10], message_data=None, fee=1, xmss_pk=self.slave.pk, master_addr=self.alice.address) self.tx1._data.nonce = 3 self.tx2._data.nonce = 6 self.tx1.sign(self.alice) self.tx2.sign(self.slave) self.block_attrs = { "dev_config": config.dev, "block_number": 5, "prev_headerhash": bytes(sha2_256(b'test')), "prev_timestamp": 10, "transactions": [self.tx1, self.tx2], "miner_address": self.alice.address, "seed_height": 0, "seed_hash": None, } self.coinbase_addrstate_attrs = OptimizedAddressState.get_default( config.dev.coinbase_address) self.coinbase_addrstate_attrs.update_balance( None, int(config.dev.coin_remaining_at_genesis * config.dev.shor_per_quanta)) self.bob_addrstate_attrs = OptimizedAddressState.get_default( self.bob.address) self.bob_addrstate_attrs.update_balance(None, 20) self.alice_addrstate_attrs = OptimizedAddressState.get_default( self.alice.address) self.alice_addrstate_attrs.update_balance(None, 100) self.alice_addrstate_attrs.pbdata.nonce = 2 self.slave_addrstate_attrs = OptimizedAddressState.get_default( self.slave.address) self.slave_addrstate_attrs.pbdata.nonce = 5
def setUp(self): self.tx = TransferTransaction.create(addrs_to=[self.bob.address], amounts=[100], message_data=None, fee=1, xmss_pk=self.alice.pk) self.tx._data.nonce = 1
def test_validate_transaction_pool_reusing_ots_index(self, m_logger): """ Two different TransferTransactions. They are signed with the same OTS indexe, from the same public key. Therefore they should conflict. :return: """ tx = self.tx tx2 = TransferTransaction.create(addrs_to=[self.bob.address], amounts=[100], message_data=None, fee=5, xmss_pk=self.alice.pk) # alice_clone's OTS index is still at 10, while self.alice will be at 11 after signing. alice_clone = get_alice_xmss() alice_clone.set_ots_index(10) tx.sign(self.alice) tx2.sign(alice_clone) tx_info = Mock(autospec=TransactionInfo, transaction=tx) tx2_info = Mock(autospec=TransactionInfo, transaction=tx2) transaction_pool = [(replacement_getTime(), tx_info), (replacement_getTime(), tx2_info)] result = tx.validate_transaction_pool(transaction_pool) self.assertFalse(result)
def test_rollback_tx_metadata(self): alice_xmss = get_alice_xmss() tx1 = TransferTransaction.create( addrs_to=[get_some_address(1), get_some_address(2)], amounts=[1, 2], message_data=None, fee=0, xmss_pk=alice_xmss.pk) block = Block.create(dev_config=config.dev, block_number=5, prev_headerhash=b'', prev_timestamp=10, transactions=[tx1], miner_address=b'', seed_height=0, seed_hash=None) TransactionMetadata.update_tx_metadata(self.state, block=block, batch=None) tx_metadata = TransactionMetadata.get_tx_metadata( self.state, tx1.txhash) self.assertEqual(tx_metadata[0].to_json(), tx1.to_json()) TransactionMetadata.rollback_tx_metadata(self.state, block, None) self.assertIsNone( TransactionMetadata.get_tx_metadata(self.state, tx1.txhash))
def broadcast_tx(self, tx: TransferTransaction): logger.info('<<<Transmitting TX: %s', bin2hstr(tx.txhash)) if isinstance(tx, MessageTransaction): legacy_type = xrdlegacy_pb2.LegacyMessage.MT elif isinstance(tx, TransferTransaction): legacy_type = xrdlegacy_pb2.LegacyMessage.TX elif isinstance(tx, TokenTransaction): legacy_type = xrdlegacy_pb2.LegacyMessage.TK elif isinstance(tx, TransferTokenTransaction): legacy_type = xrdlegacy_pb2.LegacyMessage.TT elif isinstance(tx, SlaveTransaction): legacy_type = xrdlegacy_pb2.LegacyMessage.SL elif isinstance(tx, LatticeTransaction): legacy_type = xrdlegacy_pb2.LegacyMessage.LT elif isinstance(tx, MultiSigCreate): legacy_type = xrdlegacy_pb2.LegacyMessage.MC elif isinstance(tx, MultiSigSpend): legacy_type = xrdlegacy_pb2.LegacyMessage.MS elif isinstance(tx, MultiSigVote): legacy_type = xrdlegacy_pb2.LegacyMessage.MV else: raise ValueError('Invalid Transaction Type') self.register_and_broadcast(legacy_type, tx.get_message_hash(), tx.pbdata)
def test_update_last_tx(self): alice_xmss = get_alice_xmss() # Test Case: When there is no last txns self.assertEqual(LastTransactions.get_last_txs(self.state), []) block = Block() tx1 = TransferTransaction.create( addrs_to=[get_some_address(1), get_some_address(2)], amounts=[1, 2], message_data=None, fee=0, xmss_pk=alice_xmss.pk) block._data.transactions.extend([tx1.pbdata]) LastTransactions._update_last_tx(self.state, block, None) last_txns = LastTransactions.get_last_txs(self.state) # Test Case: When there is only 1 last txns self.assertEqual(len(last_txns), 1) self.assertEqual(last_txns[0].to_json(), tx1.to_json()) block = Block() tx2 = TransferTransaction.create( addrs_to=[get_some_address(2), get_some_address(3)], amounts=[1, 2], message_data=None, fee=0, xmss_pk=alice_xmss.pk) tx3 = TransferTransaction.create( addrs_to=[get_some_address(4), get_some_address(5)], amounts=[1, 2], message_data=None, fee=0, xmss_pk=alice_xmss.pk) block._data.transactions.extend([tx2.pbdata, tx3.pbdata]) LastTransactions._update_last_tx(self.state, block, None) last_txns = LastTransactions.get_last_txs(self.state) # Test Case: When there are 3 last txns self.assertEqual(len(last_txns), 3) self.assertEqual(last_txns[0].to_json(), tx3.to_json()) self.assertEqual(last_txns[1].to_json(), tx2.to_json()) self.assertEqual(last_txns[2].to_json(), tx1.to_json())
def test_create(self, m_logger): # Alice sending coins to Bob tx = TransferTransaction.create(addrs_to=[self.bob.address], amounts=[100], message_data=None, fee=1, xmss_pk=self.alice.pk) self.assertTrue(tx)
def create_tx(addrs_to, amounts, signing_xmss, nonce): tx = TransferTransaction.create(addrs_to=addrs_to, amounts=amounts, message_data=None, fee=0, xmss_pk=signing_xmss.pk) tx.sign(signing_xmss) tx._data.nonce = nonce return tx
def test_to_json(self, m_logger): tx = TransferTransaction.create(addrs_to=[self.bob.address], amounts=[100], message_data=None, fee=1, xmss_pk=self.alice.pk) txjson = tx.to_json() self.assertEqual(json.loads(test_json_Simple), json.loads(txjson))
def test_broadcast_tx(self, m_reactor, m_logger): # broadcast_tx() should handle all Transaction Types self.factory.broadcast_tx(MessageTransaction()) self.factory.broadcast_tx(TransferTransaction()) self.factory.broadcast_tx(TokenTransaction()) self.factory.broadcast_tx(TransferTokenTransaction()) self.factory.broadcast_tx(SlaveTransaction()) with self.assertRaises(ValueError): m_tx = Mock(autospec=TransferTransaction, txhash=bhstr2bin('deadbeef')) self.factory.broadcast_tx(m_tx)
def test_check_stale_txn(self, m_is_full_transaction_pool, m_config): """ Stale Transactions are Transactions that were supposed to go into block 5, but for some reason didn't make it. They languish in TransactionPool until check_stale_txn() checks the Pool and updates the tx_info to make them go into a higher block. For each stale transaction, P2PFactory.broadcast_tx() will be called. """ # Redefine at what point should txs be considered stale m_config.user.stale_transaction_threshold = 2 bob_xmss = get_bob_xmss(4) alice_xmss = get_alice_xmss(4) tx1 = TransferTransaction.create(addrs_to=[bob_xmss.address], amounts=[1000000], message_data=None, fee=1, xmss_pk=alice_xmss.pk) tx1.sign(alice_xmss) tx2 = TransferTransaction.create(addrs_to=[bob_xmss.address], amounts=[10000], message_data=None, fee=1, xmss_pk=alice_xmss.pk) tx2.sign(alice_xmss) m_broadcast_tx = Mock(name='Mock Broadcast TX function (in P2PFactory)') self.txpool.add_tx_to_pool(tx1, 5) self.txpool.add_tx_to_pool(tx2, 5) self.txpool.set_broadcast_tx(m_broadcast_tx) with set_xrd_dir('no_data'): state = State() chain_manager = ChainManager(state) self.txpool.check_stale_txn(chain_manager.new_state_container, chain_manager.update_state_container, 8) self.assertEqual(m_broadcast_tx.call_count, 0) m = MockFunction() bob_address_state = OptimizedAddressState.get_default(bob_xmss.address) bob_address_state.pbdata.balance = 1000000000000 m.put(bob_xmss.address, bob_address_state) chain_manager.get_optimized_address_state = m.get tx3 = TransferTransaction.create(addrs_to=[alice_xmss.address], amounts=[10000], message_data=None, fee=1, xmss_pk=bob_xmss.pk) tx3.sign(bob_xmss) self.txpool.add_tx_to_pool(tx3, 5) self.txpool.check_stale_txn(chain_manager.new_state_container, chain_manager.update_state_container, 8) self.assertEqual(m_broadcast_tx.call_count, 1)
def test_validate_tx3(self, m_logger): tx = TransferTransaction.create(addrs_to=[self.bob.address], amounts=[100], message_data=None, fee=1, xmss_pk=self.alice.pk) tx.sign(self.alice) tx._data.signature = tx.signature * 4183 + tx.signature[0:104] tx._data.transaction_hash = tx.generate_txhash() with self.assertRaises(ValueError): tx.validate_or_raise()
def test_revert_state_changes_for_PK_master_slave_XMSS(self, m_logger): addresses_state = { self.alice.address: OptimizedAddressState.get_default(self.alice.address), self.slave.address: OptimizedAddressState.get_default(self.slave.address) } addresses_state[self.alice.address].pbdata.balance = 101 addresses_state[self.slave.address].pbdata.nonce = 1 tx = TransferTransaction.create(addrs_to=[self.bob.address], amounts=[100], message_data=None, fee=1, xmss_pk=self.slave.pk, master_addr=self.alice.address) tx.sign(self.slave) ots_key = self.slave.ots_index - 1 state_container = StateContainer(addresses_state=addresses_state, tokens=Indexer(b'token', None), slaves=Indexer(b'slave', None), lattice_pk=Indexer( b'lattice_pk', None), multi_sig_spend_txs=dict(), votes_stats=dict(), block_number=1, total_coin_supply=100, current_dev_config=config.dev, write_access=True, my_db=self.state._db, batch=None) state_container.paginated_bitfield.set_ots_key(addresses_state, self.slave.address, ots_key) state_container.paginated_bitfield.put_addresses_bitfield(None) self.assertTrue( state_container.paginated_bitfield.load_bitfield_and_ots_key_reuse( self.slave.address, ots_key)) self.assertFalse( state_container.paginated_bitfield.load_bitfield_and_ots_key_reuse( self.alice.address, self.alice.ots_index)) tx._apply_state_changes_for_PK(state_container) tx._revert_state_changes_for_PK(state_container) self.assertFalse( state_container.paginated_bitfield.load_bitfield_and_ots_key_reuse( self.slave.address, ots_key)) self.assertFalse( state_container.paginated_bitfield.load_bitfield_and_ots_key_reuse( self.alice.address, self.alice.ots_index))
def test_apply_state_changes_for_PK_master_slave_XMSS(self, m_logger): """ If the TX was signed by a slave XMSS, the slave XMSS's AddressState should be updated (not the master's). :return: """ tx = TransferTransaction.create(addrs_to=[self.bob.address], amounts=[100], message_data=None, fee=1, xmss_pk=self.slave.pk, master_addr=self.alice.address) addresses_state = { self.alice.address: OptimizedAddressState.get_default(self.alice.address), self.slave.address: OptimizedAddressState.get_default(self.slave.address) } tx.sign(self.slave) ots_key = self.slave.ots_index - 1 state_container = StateContainer(addresses_state=addresses_state, tokens=Indexer(b'token', None), slaves=Indexer(b'slave', None), lattice_pk=Indexer( b'lattice_pk', None), multi_sig_spend_txs=dict(), votes_stats=dict(), block_number=1, total_coin_supply=100, current_dev_config=config.dev, write_access=True, my_db=self.state._db, batch=None) self.assertFalse( state_container.paginated_bitfield.load_bitfield_and_ots_key_reuse( self.slave.address, ots_key)) self.assertFalse( state_container.paginated_bitfield.load_bitfield_and_ots_key_reuse( self.alice.address, self.alice.ots_index)) tx._apply_state_changes_for_PK(state_container) self.assertTrue( state_container.paginated_bitfield.load_bitfield_and_ots_key_reuse( self.slave.address, ots_key)) self.assertFalse( state_container.paginated_bitfield.load_bitfield_and_ots_key_reuse( self.alice.address, self.alice.ots_index)) self.assertEqual(1, addresses_state[self.slave.address].nonce) self.assertEqual(0, addresses_state[self.alice.address].nonce)
def test_getTransaction(self): db_state = Mock(spec=State) db_state.get_tx_metadata = MagicMock(return_value=None) db_state.get_block = MagicMock(return_value=None) p2p_factory = Mock(spec=P2PFactory) p2p_factory.pow = Mock(spec=POW) chain_manager = ChainManager(db_state) xrdnode = xrdNode(mining_address=b'') xrdnode.set_chain_manager(chain_manager) xrdnode._p2pfactory = p2p_factory xrdnode._pow = p2p_factory.pow xrdnode._peer_addresses = ['127.0.0.1', '192.168.1.1'] service = PublicAPIService(xrdnode) # Find an address bob_xmss = get_bob_xmss() # Find a transaction alice_xmss = get_alice_xmss() db_state.address_used = MagicMock(return_value=False) tx1 = TransferTransaction.create( addrs_to=[bob_xmss.address], amounts=[125], message_data=None, fee=19, xmss_pk=bob_xmss.pk, master_addr=alice_xmss.address) chain_manager.tx_pool.transaction_pool = [(0, TransactionInfo(tx1, 0))] context = Mock(spec=ServicerContext) request = xrd_pb2.GetTransactionReq() request.tx_hash = tx1.txhash response = service.GetTransaction(request=request, context=context) context.set_code.assert_not_called() self.assertIsNotNone(response.tx) self.assertEqual('transfer', response.tx.WhichOneof('transactionType')) self.assertEqual(alice_xmss.address, response.tx.master_addr) self.assertEqual(bob_xmss.pk, response.tx.public_key) self.assertEqual(tx1.txhash, response.tx.transaction_hash) self.assertEqual(b'', response.tx.signature) self.assertEqual(bob_xmss.address, response.tx.transfer.addrs_to[0]) self.assertEqual(125, response.tx.transfer.amounts[0]) self.assertEqual(19, response.tx.fee)
def test_validate_tx2(self, m_logger): tx = TransferTransaction.create(addrs_to=[self.bob.address], amounts=[100], message_data=None, fee=1, xmss_pk=self.alice.pk) tx.sign(self.alice) self.assertTrue(tx.validate_or_raise()) tx._data.transaction_hash = b'abc' # Should fail, as we have modified with invalid transaction_hash with self.assertRaises(ValueError): tx.validate_or_raise()
def test_revert_transfer_txn_tx_sends_to_self(self, m_logger): """ Alice sent coins to herself, but she still lost the Transaction fee. Undo this. """ addresses_state = { self.alice.address: OptimizedAddressState.get_default(self.alice.address), self.bob.address: OptimizedAddressState.get_default(self.bob.address) } addresses_state[self.alice.address].pbdata.balance = 200 tx = TransferTransaction.create(addrs_to=[self.alice.address], amounts=[100], message_data=None, fee=1, xmss_pk=self.alice.pk) tx.sign(self.alice) ots_key = self.alice.ots_index - 1 state_container = StateContainer(addresses_state=addresses_state, tokens=Indexer(b'token', None), slaves=Indexer(b'slave', None), lattice_pk=Indexer( b'lattice_pk', None), multi_sig_spend_txs=dict(), votes_stats=dict(), block_number=1, total_coin_supply=100, current_dev_config=config.dev, write_access=True, my_db=self.state._db, batch=None) state_container.paginated_bitfield.set_ots_key(addresses_state, self.alice.address, ots_key) state_container.paginated_bitfield.put_addresses_bitfield(None) self.assertTrue( state_container.paginated_bitfield.load_bitfield_and_ots_key_reuse( self.alice.address, ots_key)) tx.apply(self.state, state_container) tx.revert(self.state, state_container) self.assertFalse( state_container.paginated_bitfield.load_bitfield_and_ots_key_reuse( self.alice.address, ots_key)) self.assertEqual(200, addresses_state[self.alice.address].balance) self.assertEqual(0, addresses_state[self.bob.address].balance)
def test_affected_address(self, m_logger): # The default transaction params involve only two addresses. affected_addresses = set() self.tx.set_affected_address(affected_addresses) self.assertEqual(2, len(affected_addresses)) # This transaction should involve 3 addresses. affected_addresses = set() tx = TransferTransaction.create( addrs_to=[self.bob.address, self.slave.address], amounts=[100, 100], message_data=None, fee=1, xmss_pk=self.alice.pk) tx.set_affected_address(affected_addresses) self.assertEqual(3, len(affected_addresses))
def test_apply_transfer_txn_tx_sends_to_self(self, m_logger): """ If you send coins to yourself, you should only lose the fee for the Transaction. """ addresses_state = { self.alice.address: OptimizedAddressState.get_default(self.alice.address), self.bob.address: OptimizedAddressState.get_default(self.bob.address), self.slave.address: OptimizedAddressState.get_default(self.slave.address) } addresses_state[self.alice.address].pbdata.balance = 200 tx = TransferTransaction.create(addrs_to=[self.alice.address], amounts=[100], message_data=None, fee=1, xmss_pk=self.alice.pk) tx.sign(self.alice) ots_key = self.alice.ots_index - 1 state_container = StateContainer(addresses_state=addresses_state, tokens=Indexer(b'token', None), slaves=Indexer(b'slave', None), lattice_pk=Indexer( b'lattice_pk', None), multi_sig_spend_txs=dict(), votes_stats=dict(), block_number=1, total_coin_supply=100, current_dev_config=config.dev, write_access=True, my_db=self.state._db, batch=None) self.assertFalse( state_container.paginated_bitfield.load_bitfield_and_ots_key_reuse( self.alice.address, ots_key)) tx.apply(self.state, state_container) self.assertTrue( state_container.paginated_bitfield.load_bitfield_and_ots_key_reuse( self.alice.address, ots_key)) self.assertEqual(199, addresses_state[self.alice.address].balance) storage_key = state_container.paginated_tx_hash.generate_key( self.alice.address, 1) self.assertIn(tx.txhash, state_container.paginated_tx_hash.key_value[storage_key])
def test_apply_transfer_txn_multi_send(self, m_logger): """ Test that apply_state_changes() also works with multiple recipients. """ addresses_state = { self.alice.address: OptimizedAddressState.get_default(self.alice.address), self.bob.address: OptimizedAddressState.get_default(self.bob.address), self.slave.address: OptimizedAddressState.get_default(self.slave.address) } addresses_state[self.alice.address].pbdata.balance = 200 tx_multisend = TransferTransaction.create( addrs_to=[self.bob.address, self.slave.address], amounts=[20, 20], message_data=None, fee=1, xmss_pk=self.alice.pk) tx_multisend.sign(self.alice) ots_key = self.alice.ots_index - 1 state_container = StateContainer(addresses_state=addresses_state, tokens=Indexer(b'token', None), slaves=Indexer(b'slave', None), lattice_pk=Indexer( b'lattice_pk', None), multi_sig_spend_txs=dict(), votes_stats=dict(), block_number=1, total_coin_supply=100, current_dev_config=config.dev, write_access=True, my_db=self.state._db, batch=None) self.assertFalse( state_container.paginated_bitfield.load_bitfield_and_ots_key_reuse( self.alice.address, ots_key)) tx_multisend.apply(self.state, state_container) self.assertTrue( state_container.paginated_bitfield.load_bitfield_and_ots_key_reuse( self.alice.address, ots_key)) self.assertEqual(159, addresses_state[self.alice.address].balance) self.assertEqual(20, addresses_state[self.bob.address].balance) self.assertEqual(20, addresses_state[self.slave.address].balance)
def test_update_tx_metadata(self): alice_xmss = get_alice_xmss() tx = TransferTransaction.create( addrs_to=[get_some_address(1), get_some_address(2)], amounts=[1, 2], message_data=None, fee=0, xmss_pk=alice_xmss.pk) block_number = 5 TransactionMetadata.put_tx_metadata(self.state, tx, block_number, 10000, None) tx_metadata = TransactionMetadata.get_tx_metadata( self.state, tx.txhash) self.assertEqual(tx_metadata[0].to_json(), tx.to_json()) self.assertEqual(tx_metadata[1], block_number)
def create_send_tx(self, addrs_to: list, amounts: list, message_data: bytes, fee: int, xmss_pk: bytes, master_addr: bytes) -> TransferTransaction: addr_from = self.get_addr_from(xmss_pk, master_addr) balance = self._chain_manager.get_address_balance(addr_from) if sum(amounts) + fee > balance: raise ValueError("Not enough funds in the source address") return TransferTransaction.create(addrs_to=addrs_to, amounts=amounts, message_data=message_data, fee=fee, xmss_pk=xmss_pk, master_addr=master_addr)
def relay_transfer_txn(self, qaddresses_to: list, amounts: list, fee: int, master_qaddress, signer_address: str, ots_index: int): self.authenticate() index, xmss = self._get_wallet_index_xmss(signer_address, ots_index) self.verify_ots(signer_address, xmss, user_ots_index=ots_index) tx = TransferTransaction.create( addrs_to=self.qaddresses_to_address(qaddresses_to), amounts=amounts, message_data=None, fee=fee, xmss_pk=xmss.pk, master_addr=self.qaddress_to_address(master_qaddress)) self.sign_and_push_transaction(tx, xmss, index) return self.to_plain_transaction(tx.pbdata)
def relay_transfer_txn_by_slave(self, qaddresses_to: list, amounts: list, fee: int, master_qaddress): self.authenticate() index, group_index, slave_index, slave_xmss = self.get_slave_xmss( master_qaddress) if slave_index == -1: raise Exception("No Slave Found") tx = TransferTransaction.create( addrs_to=self.qaddresses_to_address(qaddresses_to), amounts=amounts, message_data=None, fee=fee, xmss_pk=slave_xmss.pk, master_addr=self.qaddress_to_address(master_qaddress)) self.sign_and_push_transaction(tx, slave_xmss, index, group_index, slave_index) return self.to_plain_transaction(tx.pbdata)
def test_validate_transaction_pool(self, m_logger): """ Two TransferTransactions. Although they're the same, they are signed with different OTS indexes. Therefore they should not conflict when they are both in the TransactionPool. :return: """ tx = self.tx tx2 = TransferTransaction.create(addrs_to=[self.bob.address], amounts=[100], message_data=None, fee=1, xmss_pk=self.alice.pk) tx.sign(self.alice) tx2.sign(self.alice) tx_info = Mock(autospec=TransactionInfo, transaction=tx) tx2_info = Mock(autospec=TransactionInfo, transaction=tx2) transaction_pool = [(replacement_getTime(), tx_info), (replacement_getTime(), tx2_info)] result = tx.validate_transaction_pool(transaction_pool) self.assertTrue(result)
def test_remove_last_tx(self): # Test Case: When there is no last txns self.assertEqual(LastTransactions.get_last_txs(self.state), []) alice_xmss = get_alice_xmss() block = Block() tx1 = TransferTransaction.create( addrs_to=[get_some_address(1), get_some_address(2)], amounts=[1, 2], message_data=None, fee=0, xmss_pk=alice_xmss.pk) block._data.transactions.extend([tx1.pbdata]) LastTransactions._update_last_tx(self.state, block, None) last_txns = LastTransactions.get_last_txs(self.state) self.assertEqual(last_txns[0].to_json(), tx1.to_json()) LastTransactions._remove_last_tx(self.state, block, None) last_txns = LastTransactions.get_last_txs(self.state) self.assertEqual(last_txns, [])
def transfer(destinations, fee, mixin, unlock_time): if len(destinations) > config.dev.transaction_multi_output_limit: raise Exception('Payment Failed: Amount exceeds the allowed limit') addrs_to = [] amounts = [] for tx in destinations: addrs_to.append(bytes(hstr2bin(tx['address'][1:]))) # Skipping 'Q' amounts.append(tx['amount']) stub = get_public_stub() xmss = get_unused_payment_xmss(stub) if not xmss: raise Exception('Payment Failed: No Unused Payment XMSS found') tx = TransferTransaction.create(addrs_to=addrs_to, amounts=amounts, message_data=None, fee=fee, xmss_pk=xmss.pk, master_addr=payment_slaves[0]) tx.sign(xmss) response = stub.PushTransaction(request=xrd_pb2.PushTransactionReq( transaction_signed=tx.pbdata)) if response.error_code != 3: raise Exception('Transaction Submission Failed, Response Code: %s', response.error_code) response = {'tx_hash': bin2hstr(tx.txhash)} return response
def test_validate_transaction_pool_different_pk_same_ots_index( self, m_logger): """ Two TransferTransactions. They are signed with the same OTS indexes, but from different public keys. Therefore they should NOT conflict. :return: """ tx = self.tx tx2 = TransferTransaction.create(addrs_to=[self.bob.address], amounts=[100], message_data=None, fee=1, xmss_pk=self.bob.pk) tx.sign(self.alice) tx2.sign(self.bob) tx_info = Mock(autospec=TransactionInfo, transaction=tx) tx2_info = Mock(autospec=TransactionInfo, transaction=tx2) transaction_pool = [(replacement_getTime(), tx_info), (replacement_getTime(), tx2_info)] result = tx.validate_transaction_pool(transaction_pool) self.assertTrue(result)