def test_create(self): alice_xmss = get_alice_xmss() slave_xmss = XMSS(alice_xmss.height, alice_xmss.get_seed()) staking_address = bytes(alice_xmss.get_address().encode()) h0 = sha256(b'hashchain_seed') h1 = sha256(h0) h2 = sha256(h1) stake_transaction = StakeTransaction.create(activation_blocknumber=0, xmss=alice_xmss, slavePK=slave_xmss.pk(), hashchain_terminator=h2) sv = StakeValidator(100, stake_transaction) self.assertEqual(staking_address, sv.address) self.assertEqual(slave_xmss.pk(), sv.slave_public_key) self.assertEqual(h2, sv.terminator_hash) self.assertEqual(100, sv.balance) self.assertEqual(0, sv.nonce) self.assertFalse(sv.is_banned) self.assertTrue(sv.is_active)
def create(activation_blocknumber: int, xmss: XMSS, slavePK: bytes, hashchain_terminator: bytes = None): """ >>> s = StakeTransaction() >>> slave = XMSS(4) >>> isinstance(s.create(0, XMSS(4), slave.pk(), None), StakeTransaction) True """ transaction = StakeTransaction() transaction._data.addr_from = bytes(xmss.get_address().encode()) transaction._data.public_key = bytes(xmss.pk()) # Stake specific transaction._data.stake.activation_blocknumber = activation_blocknumber transaction._data.stake.slavePK = slavePK if hashchain_terminator is None: epoch = activation_blocknumber // config.dev.blocks_per_epoch # FIXME: We are using the same xmss for the hashchain??? transaction._data.stake.hash = hashchain_reveal( xmss.get_seed_private(), epoch=epoch) else: transaction._data.stake.hash = hashchain_terminator # WARNING: These fields need to the calculated once all other fields are set transaction._data.ots_key = xmss.get_index() transaction._data.transaction_hash = transaction.calculate_txhash() return transaction
def test_negative_balance(self): alice_xmss = get_alice_xmss() slave_xmss = XMSS(alice_xmss.height, alice_xmss.get_seed()) stake_transaction = StakeTransaction.create(activation_blocknumber=0, xmss=alice_xmss, slavePK=slave_xmss.pk()) with self.assertRaises(ValueError): StakeValidator(-1, stake_transaction)
def test_empty_terminator(self): alice_xmss = get_alice_xmss() slave_xmss = XMSS(alice_xmss.height, alice_xmss.get_seed()) stake_transaction = StakeTransaction.create(activation_blocknumber=0, xmss=alice_xmss, slavePK=slave_xmss.pk()) stake_transaction._data.stake.hash = bytes([]) with self.assertRaises(ValueError): StakeValidator(0, stake_transaction)
def test_invalid_balance(self): alice_xmss = get_alice_xmss() slave_xmss = XMSS(alice_xmss.height, alice_xmss.get_seed()) stake_transaction = StakeTransaction.create(activation_blocknumber=0, xmss=alice_xmss, slavePK=slave_xmss.pk()) with self.assertRaises(ValueError): StakeValidator(config.dev.minimum_staking_balance_required - 1, stake_transaction)
def test_add_future_sv(self): alice_xmss = get_alice_xmss() slave_xmss = XMSS(alice_xmss.height, alice_xmss.get_seed()) stake_validators_tracker = StakeValidatorsTracker.create() stake_transaction = StakeTransaction.create(10, alice_xmss, slave_xmss.pk(), b'1111') stake_validators_tracker.add_sv(100, stake_transaction, 1) total_stake_amount = stake_validators_tracker.get_total_stake_amount() self.assertNotEqual(100, total_stake_amount)
def create(message_hash: bytes, fee: int, xmss: XMSS): transaction = MessageTransaction() transaction._data.addr_from = xmss.get_address().encode() transaction._data.message.message_hash = message_hash transaction._data.message.fee = fee transaction._data.public_key = bytes(xmss.pk()) transaction._data.ots_key = xmss.get_index() transaction._data.transaction_hash = transaction.calculate_txhash() return transaction
def create(addr_from: bytes, blocknumber: int, headerhash: bytes, xmss: XMSS): transaction = Vote() transaction._data.addr_from = addr_from transaction._data.vote.block_number = blocknumber transaction._data.vote.hash_header = headerhash transaction._data.public_key = bytes(xmss.pk()) transaction._data.ots_key = xmss.get_index() transaction._data.transaction_hash = transaction.calculate_txhash() return transaction
def test_add_sv(self): alice_xmss = get_alice_xmss() slave_xmss = XMSS(alice_xmss.height, alice_xmss.get_seed()) stake_validators_tracker = StakeValidatorsTracker.create() stake_transaction = StakeTransaction.create(0, alice_xmss, slave_xmss.pk(), b'1111') stake_validators_tracker.add_sv(100, stake_transaction, 1) balance = stake_validators_tracker.get_stake_balance(alice_xmss.get_address().encode()) self.assertEqual(100, balance) total_stake_amount = stake_validators_tracker.get_total_stake_amount() self.assertEqual(100, total_stake_amount) stake_validators_tracker.to_json()
def test_sign_verify(self): message = "This is a test" message_bin = str2bin(message) xmss_height = 10 seed = bytearray([i for i in range(48)]) xmss = XMSS(xmss_height, seed) pk = xmss.pk() xmss.set_index(1) for i in range(10): self.assertTrue(xmss.get_index() == i + 1) signature = xmss.SIGN(message_bin) self.assertTrue(XMSS.VERIFY(message_bin, signature, pk))
def create(mining_nonce: int, block_number: int, prevblock_headerhash: bytes, transactions: list, signing_xmss: XMSS, master_address: bytes, nonce: int): block = Block() block._data.transactions.extend([qrl_pb2.Transaction()]) # FIXME: Empty for coinbase? # Process transactions hashedtransactions = [] fee_reward = 0 for tx in transactions: fee_reward += tx.fee hashedtransactions.append(tx.txhash) block._data.transactions.extend([tx.pbdata]) # copy memory rather than sym link if not hashedtransactions: hashedtransactions = [sha256(b'')] txs_hash = merkle_tx_hash(hashedtransactions) # FIXME: Find a better name, type changes tmp_blockheader = BlockHeader.create(blocknumber=block_number, mining_nonce=mining_nonce, PK=signing_xmss.pk(), prev_blockheaderhash=prevblock_headerhash, hashedtransactions=txs_hash, fee_reward=fee_reward) block._data.header.MergeFrom(tmp_blockheader.pbdata) # Prepare coinbase tx coinbase_tx = CoinBase.create(tmp_blockheader, signing_xmss, master_address) coinbase_tx.pbdata.nonce = nonce coinbase_tx.sign(signing_xmss) # Sign after nonce has been set # Replace first tx block._data.transactions[0].CopyFrom(coinbase_tx.pbdata) return block
def test_create2(self): alice_xmss = get_alice_xmss() slave_xmss = XMSS(alice_xmss.height, alice_xmss.get_seed()) h0 = sha256(b'hashchain_seed') h1 = sha256(h0) h2 = sha256(h1) h3 = sha256(h2) stake_transaction = StakeTransaction.create(activation_blocknumber=0, xmss=alice_xmss, slavePK=slave_xmss.pk(), hashchain_terminator=h3) sv = StakeValidator(100, stake_transaction) self.assertTrue(sv.validate_hash(h0, 2)) self.assertTrue(sv.validate_hash(h2, 0)) self.assertTrue(sv.validate_hash(h2, 0)) self.assertTrue(sv.validate_hash(h1, 1)) self.assertTrue(sv.validate_hash(h0, 2))
def test_add_2(self): destroy_state() with State() as state: with set_wallet_dir("test_wallet"): chain = Chain(state) buffered_chain = BufferedChain(chain) alice_xmss = get_alice_xmss() slave_xmss = XMSS(alice_xmss.height, alice_xmss.get_seed()) staking_address = bytes(alice_xmss.get_address().encode()) h0 = sha256(b'hashchain_seed') h1 = sha256(h0) with mocked_genesis() as custom_genesis: custom_genesis.genesis_balance.extend([ qrl_pb2.GenesisBalance( address=alice_xmss.get_address(), balance=700000000000000) ]) res = buffered_chain.add_block(block=custom_genesis) self.assertTrue(res) stake_transaction = StakeTransaction.create( activation_blocknumber=1, xmss=alice_xmss, slavePK=slave_xmss.pk(), hashchain_terminator=h1) vote = Vote.create( addr_from=alice_xmss.get_address().encode(), blocknumber=0, headerhash=custom_genesis.headerhash, xmss=slave_xmss) vote.sign(slave_xmss) buffered_chain.add_vote(vote) vote_metadata = buffered_chain.get_consensus(0) # FIXME: The test needs private access.. This is an API issue stake_transaction._data.nonce = 1 stake_transaction.sign(alice_xmss) chain.pstate.stake_validators_tracker.add_sv( balance=700000000000000, stake_txn=stake_transaction, blocknumber=1) sv = chain.pstate.stake_validators_tracker.sv_dict[ staking_address] self.assertEqual(0, sv.nonce) tmp_block = Block.create( staking_address=bytes( alice_xmss.get_address().encode()), block_number=1, reveal_hash=h0, prevblock_headerhash=custom_genesis.headerhash, transactions=[stake_transaction], duplicate_transactions=OrderedDict(), vote=vote_metadata, signing_xmss=alice_xmss, nonce=1) res = buffered_chain.add_block(block=tmp_block) self.assertTrue(res)
def test_add_4(self): destroy_state() with State() as state: with set_wallet_dir("test_wallet"): chain = Chain(state) buffered_chain = BufferedChain(chain) alice_xmss = get_alice_xmss() slave_xmss = XMSS(alice_xmss.height, alice_xmss.get_seed()) random_xmss1 = get_random_xmss() random_xmss2 = get_random_xmss() staking_address = bytes(alice_xmss.get_address().encode()) # FIXME: Replace this with a call to create a hash_chain h0 = sha256(b'hashchain_seed') h1 = sha256(h0) h2 = sha256(h1) h3 = sha256(h2) h4 = sha256(h3) with mocked_genesis() as custom_genesis: custom_genesis.genesis_balance.extend([ qrl_pb2.GenesisBalance( address=alice_xmss.get_address(), balance=700000000000000) ]) res = buffered_chain.add_block(block=GenesisBlock()) self.assertTrue(res) stake_transaction = StakeTransaction.create( activation_blocknumber=1, xmss=alice_xmss, slavePK=slave_xmss.pk(), hashchain_terminator=h4) stake_transaction._data.nonce = 1 # FIXME: The test needs private access.. This is an API issue stake_transaction.sign(alice_xmss) vote = Vote.create( addr_from=alice_xmss.get_address().encode(), blocknumber=0, headerhash=GenesisBlock().headerhash, xmss=slave_xmss) vote.sign(slave_xmss) buffered_chain.add_vote(vote) vote_metadata = buffered_chain.get_consensus(0) chain.pstate.stake_validators_tracker.add_sv( balance=700000000000000, stake_txn=stake_transaction, blocknumber=1) sv = chain.pstate.stake_validators_tracker.sv_dict[ staking_address] self.assertEqual(0, sv.nonce) # Token Transaction to create a token for test token_transaction = get_token_transaction( random_xmss1, random_xmss2) token_transaction._data.nonce = 1 token_transaction.sign(random_xmss1) # Transfer Token Transaction transfer_token1 = TransferTokenTransaction.create( addr_from=random_xmss1.get_address().encode(), token_txhash=token_transaction.txhash, addr_to=alice_xmss.get_address().encode(), amount=100000000, fee=1, xmss_pk=random_xmss1.pk(), xmss_ots_index=random_xmss1.get_index()) transfer_token1._data.nonce = 2 transfer_token1.sign(random_xmss1) transfer_token2 = TransferTokenTransaction.create( addr_from=random_xmss2.get_address().encode(), token_txhash=token_transaction.txhash, addr_to=alice_xmss.get_address().encode(), amount=200000000, fee=1, xmss_pk=random_xmss2.pk(), xmss_ots_index=random_xmss2.get_index()) transfer_token2._data.nonce = 1 transfer_token2.sign(random_xmss2) # Transfer Coin Transaction transfer_transaction = TransferTransaction.create( addr_from=random_xmss1.get_address().encode(), addr_to=random_xmss2.get_address().encode(), amount=10, fee=1, xmss_pk=random_xmss1.pk(), xmss_ots_index=random_xmss1.get_index()) transfer_transaction._data.nonce = 3 transfer_transaction.sign(random_xmss1) tmp_block1 = Block.create( staking_address=staking_address, block_number=1, reveal_hash=h3, prevblock_headerhash=GenesisBlock().headerhash, transactions=[stake_transaction, token_transaction], duplicate_transactions=OrderedDict(), vote=vote_metadata, signing_xmss=slave_xmss, nonce=1) res = buffered_chain.add_block(block=tmp_block1) self.assertTrue(res) # Need to move forward the time to align with block times with mock.patch('qrl.core.ntp.getTime') as time_mock: time_mock.return_value = tmp_block1.timestamp + config.dev.minimum_minting_delay vote = Vote.create( addr_from=alice_xmss.get_address().encode(), blocknumber=1, headerhash=tmp_block1.headerhash, xmss=slave_xmss) vote.sign(slave_xmss) buffered_chain.add_vote(vote) vote_metadata = buffered_chain.get_consensus(1) tmp_block2 = Block.create( staking_address=staking_address, block_number=2, reveal_hash=h2, prevblock_headerhash=tmp_block1.headerhash, transactions=[ transfer_token1, transfer_token2, transfer_transaction ], duplicate_transactions=OrderedDict(), vote=vote_metadata, signing_xmss=slave_xmss, nonce=2) res = buffered_chain.add_block(block=tmp_block2) self.assertTrue(res) # Need to move forward the time to align with block times with mock.patch('qrl.core.ntp.getTime') as time_mock: time_mock.return_value = tmp_block2.timestamp + config.dev.minimum_minting_delay vote = Vote.create( addr_from=alice_xmss.get_address().encode(), blocknumber=2, headerhash=tmp_block2.headerhash, xmss=slave_xmss) vote.sign(slave_xmss) buffered_chain.add_vote(vote) vote_metadata = buffered_chain.get_consensus(2) tmp_block3 = Block.create( staking_address=staking_address, block_number=3, reveal_hash=h1, prevblock_headerhash=tmp_block2.headerhash, transactions=[], duplicate_transactions=OrderedDict(), vote=vote_metadata, signing_xmss=slave_xmss, nonce=3) res = buffered_chain.add_block(block=tmp_block3) self.assertTrue(res) chain = buffered_chain._chain random_xmss1_state = chain.pstate._get_address_state( random_xmss1.get_address().encode()) random_xmss2_state = chain.pstate._get_address_state( random_xmss2.get_address().encode()) self.assertEqual( random_xmss1_state.tokens[bin2hstr( token_transaction.txhash).encode()], 400000000) self.assertEqual( random_xmss2_state.tokens[bin2hstr( token_transaction.txhash).encode()], 200000000) # Need to move forward the time to align with block times with mock.patch('qrl.core.ntp.getTime') as time_mock: time_mock.return_value = tmp_block3.timestamp + config.dev.minimum_minting_delay vote = Vote.create( addr_from=alice_xmss.get_address().encode(), blocknumber=3, headerhash=tmp_block3.headerhash, xmss=slave_xmss) vote.sign(slave_xmss) buffered_chain.add_vote(vote) vote_metadata = buffered_chain.get_consensus(3) tmp_block4 = Block.create( staking_address=staking_address, block_number=4, reveal_hash=h0, prevblock_headerhash=tmp_block3.headerhash, transactions=[], duplicate_transactions=OrderedDict(), vote=vote_metadata, signing_xmss=slave_xmss, nonce=4) res = buffered_chain.add_block(block=tmp_block4) self.assertTrue(res) token_metadata = buffered_chain.get_token_metadata( token_transaction.txhash) self.assertEqual(token_metadata.token_txhash, token_transaction.txhash) self.assertEqual( len(token_metadata.transfer_token_tx_hashes), 3) self.assertEqual( token_metadata.transfer_token_tx_hashes[0], token_transaction.txhash) random_xmss1_state = chain.pstate._get_address_state( random_xmss1.get_address().encode()) random_xmss2_state = chain.pstate._get_address_state( random_xmss2.get_address().encode()) alice_state = chain.pstate._get_address_state( alice_xmss.get_address().encode()) self.assertEqual( random_xmss1_state.tokens[bin2hstr( token_transaction.txhash).encode()], 300000000) self.assertEqual( random_xmss2_state.tokens[bin2hstr( token_transaction.txhash).encode()], 0) self.assertEqual( alice_state.tokens[bin2hstr( token_transaction.txhash).encode()], 300000000) self.assertEqual(random_xmss1_state.balance, config.dev.default_account_balance - 13) self.assertEqual(random_xmss2_state.balance, config.dev.default_account_balance + 9)
def test_add_3(self): destroy_state() with State() as state: with set_wallet_dir("test_wallet"): chain = Chain(state) buffered_chain = BufferedChain(chain) alice_xmss = get_alice_xmss() slave_xmss = XMSS(alice_xmss.height, alice_xmss.get_seed()) staking_address = bytes(alice_xmss.get_address().encode()) # FIXME: Replace this with a call to create a hash_chain h0 = sha256(b'hashchain_seed') h1 = sha256(h0) h2 = sha256(h1) h3 = sha256(h2) with mocked_genesis() as custom_genesis: custom_genesis.genesis_balance.extend([ qrl_pb2.GenesisBalance( address=alice_xmss.get_address(), balance=700000000000000) ]) res = buffered_chain.add_block(block=GenesisBlock()) self.assertTrue(res) stake_transaction = StakeTransaction.create( activation_blocknumber=1, xmss=alice_xmss, slavePK=slave_xmss.pk(), hashchain_terminator=h3) stake_transaction._data.nonce = 1 # FIXME: The test needs private access.. This is an API issue stake_transaction.sign(alice_xmss) vote = Vote.create( addr_from=alice_xmss.get_address().encode(), blocknumber=0, headerhash=GenesisBlock().headerhash, xmss=slave_xmss) vote.sign(slave_xmss) buffered_chain.add_vote(vote) vote_metadata = buffered_chain.get_consensus(0) chain.pstate.stake_validators_tracker.add_sv( balance=700000000000000, stake_txn=stake_transaction, blocknumber=1) sv = chain.pstate.stake_validators_tracker.sv_dict[ staking_address] self.assertEqual(0, sv.nonce) tmp_block1 = Block.create( staking_address=staking_address, block_number=1, reveal_hash=h2, prevblock_headerhash=GenesisBlock().headerhash, transactions=[stake_transaction], duplicate_transactions=OrderedDict(), vote=vote_metadata, signing_xmss=slave_xmss, nonce=1) res = buffered_chain.add_block(block=tmp_block1) self.assertTrue(res) # Need to move forward the time to align with block times with mock.patch('qrl.core.ntp.getTime') as time_mock: time_mock.return_value = tmp_block1.timestamp + config.dev.minimum_minting_delay vote = Vote.create( addr_from=alice_xmss.get_address().encode(), blocknumber=1, headerhash=tmp_block1.headerhash, xmss=slave_xmss) vote.sign(slave_xmss) buffered_chain.add_vote(vote) vote_metadata = buffered_chain.get_consensus(1) tmp_block2 = Block.create( staking_address=staking_address, block_number=2, reveal_hash=h1, prevblock_headerhash=tmp_block1.headerhash, transactions=[], duplicate_transactions=OrderedDict(), vote=vote_metadata, signing_xmss=slave_xmss, nonce=2) res = buffered_chain.add_block(block=tmp_block2) self.assertTrue(res) # Need to move forward the time to align with block times with mock.patch('qrl.core.ntp.getTime') as time_mock: time_mock.return_value = tmp_block2.timestamp + config.dev.minimum_minting_delay vote = Vote.create( addr_from=alice_xmss.get_address().encode(), blocknumber=2, headerhash=tmp_block2.headerhash, xmss=slave_xmss) vote.sign(slave_xmss) buffered_chain.add_vote(vote) vote_metadata = buffered_chain.get_consensus(2) tmp_block3 = Block.create( staking_address=staking_address, block_number=3, reveal_hash=h0, prevblock_headerhash=tmp_block2.headerhash, transactions=[], duplicate_transactions=OrderedDict(), vote=vote_metadata, signing_xmss=slave_xmss, nonce=3) res = buffered_chain.add_block(block=tmp_block3) self.assertTrue(res)
class TestTokenTransaction(TestCase): def __init__(self, *args, **kwargs): super(TestTokenTransaction, self).__init__(*args, **kwargs) self.alice = XMSS(4, seed='a' * 48) self.bob = XMSS(4, seed='b' * 48) self.alice.set_index(10) self.maxDiff = None def test_create(self): # Alice creates Token initial_balances = list() initial_balances.append( qrl_pb2.AddressAmount(address=self.alice.get_address().encode(), amount=400000000)) initial_balances.append( qrl_pb2.AddressAmount(address=self.bob.get_address().encode(), amount=200000000)) tx = TokenTransaction.create( addr_from=self.alice.get_address().encode(), symbol=b'QRL', name=b'Quantum Resistant Ledger', owner= b'Q223bc5e5b78edfd778b1bf72702061cc053010711ffeefb9d969318be5d7b86b021b73c2', decimals=4, initial_balances=initial_balances, fee=1, xmss_pk=self.alice.pk(), xmss_ots_index=self.alice.get_index()) self.assertTrue(tx) def test_create_negative_fee(self): with self.assertRaises(ValueError): TokenTransaction.create( addr_from=self.alice.get_address().encode(), symbol=b'QRL', name=b'Quantum Resistant Ledger', owner= b'Q223bc5e5b78edfd778b1bf72702061cc053010711ffeefb9d969318be5d7b86b021b73c2', decimals=4, initial_balances=[], fee=-1, xmss_pk=self.alice.pk(), xmss_ots_index=self.alice.get_index()) def test_to_json(self): initial_balances = list() initial_balances.append( qrl_pb2.AddressAmount(address=self.alice.get_address().encode(), amount=400000000)) initial_balances.append( qrl_pb2.AddressAmount(address=self.bob.get_address().encode(), amount=200000000)) tx = TokenTransaction.create( addr_from=self.alice.get_address().encode(), symbol=b'QRL', name=b'Quantum Resistant Ledger', owner= b'Q223bc5e5b78edfd778b1bf72702061cc053010711ffeefb9d969318be5d7b86b021b73c2', decimals=4, initial_balances=initial_balances, fee=1, xmss_pk=self.alice.pk(), xmss_ots_index=self.alice.get_index()) txjson = tx.to_json() self.assertEqual(json.loads(test_json_Token), json.loads(txjson)) def test_from_json(self): tx = Transaction.from_json(test_json_Token) self.assertIsInstance(tx, TokenTransaction) self.assertEqual(tx.subtype, qrl_pb2.Transaction.TOKEN) # Test that common Transaction components were copied over. self.assertEqual( b'Q223bc5e5b78edfd778b1bf72702061cc053010711ffeefb9d969318be5d7b86b021b73c2', tx.txfrom) self.assertEqual( '3c523f9cc26f800863c003524392806ff6df373acb4d47cc607b62365fe4ab77' 'cf3018d321df7dcb653c9f7968673e43d12cc26e3461b5f425fd5d977400fea5', bin2hstr(tx.PK)) self.assertEqual(b'QRL', tx.symbol) self.assertEqual(b'Quantum Resistant Ledger', tx.name) self.assertEqual( b'Q223bc5e5b78edfd778b1bf72702061cc053010711ffeefb9d969318be5d7b86b021b73c2', tx.owner) self.assertEqual( 'f6d115628207da9c1bffec208aea7fb196d39433062b18f43619106c43cff4e9', bin2hstr(tx.txhash)) self.assertEqual(10, tx.ots_key) self.assertEqual(b'', tx.signature) self.assertEqual( 'e2e3d8b08e65b25411af455eb9bb402827fa7b600fa0b36011d62e26899dfa05', bin2hstr(tx.pubhash)) total_supply = 0 for initial_balance in tx.initial_balances: total_supply += initial_balance.amount self.assertEqual(600000000, total_supply) self.assertEqual(1, tx.fee) def test_validate_tx(self): initial_balances = list() initial_balances.append( qrl_pb2.AddressAmount(address=self.alice.get_address().encode(), amount=400000000)) initial_balances.append( qrl_pb2.AddressAmount(address=self.bob.get_address().encode(), amount=200000000)) tx = TokenTransaction.create( addr_from=self.alice.get_address().encode(), symbol=b'QRL', name=b'Quantum Resistant Ledger', owner= b'Q223bc5e5b78edfd778b1bf72702061cc053010711ffeefb9d969318be5d7b86b021b73c2', decimals=4, initial_balances=initial_balances, fee=1, xmss_pk=self.alice.pk(), xmss_ots_index=self.alice.get_index()) # We must sign the tx before validation will work. tx.sign(self.alice) # We have not touched the tx: validation should pass. self.assertTrue(tx.validate_or_raise()) def test_state_validate_tx(self): # Test balance not enough # Test negative tx amounts pass
class TestTransferTokenTransaction(TestCase): def __init__(self, *args, **kwargs): super(TestTransferTokenTransaction, self).__init__(*args, **kwargs) self.alice = XMSS(4, seed='a' * 48) self.bob = XMSS(4, seed='b' * 48) self.alice.set_index(10) self.maxDiff = None def test_create(self): tx = TransferTokenTransaction.create( addr_from=self.alice.get_address().encode(), token_txhash=b'000000000000000', addr_to=self.bob.get_address().encode(), amount=200000, fee=1, xmss_pk=self.alice.pk(), xmss_ots_index=self.alice.get_index()) self.assertTrue(tx) def test_to_json(self): tx = TransferTokenTransaction.create( addr_from=self.alice.get_address().encode(), token_txhash=b'000000000000000', addr_to=self.bob.get_address().encode(), amount=200000, fee=1, xmss_pk=self.alice.pk(), xmss_ots_index=self.alice.get_index()) txjson = tx.to_json() self.assertEqual(json.loads(test_json_TransferToken), json.loads(txjson)) def test_from_json(self): tx = Transaction.from_json(test_json_TransferToken) self.assertIsInstance(tx, TransferTokenTransaction) self.assertEqual(tx.subtype, qrl_pb2.Transaction.TRANSFERTOKEN) # Test that common Transaction components were copied over. self.assertEqual( b'Q223bc5e5b78edfd778b1bf72702061cc053010711ffeefb9d969318be5d7b86b021b73c2', tx.txfrom) self.assertEqual( '3c523f9cc26f800863c003524392806ff6df373acb4d47cc607b62365fe4ab77' 'cf3018d321df7dcb653c9f7968673e43d12cc26e3461b5f425fd5d977400fea5', bin2hstr(tx.PK)) self.assertEqual(b'000000000000000', tx.token_txhash) self.assertEqual(200000, tx.amount) self.assertEqual( '712ec52c483d1e513b83fd4d1210fd943903ae88e0c8048058b06d4e28a8727b', bin2hstr(tx.txhash)) self.assertEqual(10, tx.ots_key) self.assertEqual(b'', tx.signature) self.assertEqual( 'e2e3d8b08e65b25411af455eb9bb402827fa7b600fa0b36011d62e26899dfa05', bin2hstr(tx.pubhash)) self.assertEqual(1, tx.fee) def test_validate_tx(self): tx = TransferTokenTransaction.create( addr_from=self.alice.get_address().encode(), token_txhash=b'000000000000000', addr_to=self.bob.get_address().encode(), amount=200000, fee=1, xmss_pk=self.alice.pk(), xmss_ots_index=self.alice.get_index()) # We must sign the tx before validation will work. tx.sign(self.alice) # We have not touched the tx: validation should pass. self.assertTrue(tx.validate_or_raise()) def test_state_validate_tx(self): # Test balance not enough # Test negative tx amounts pass
class TestStakeTransaction(TestCase): def __init__(self, *args, **kwargs): super(TestStakeTransaction, self).__init__(*args, **kwargs) self.alice = XMSS(4, seed='a' * 48) self.bob = XMSS(4, seed='b' * 48) self.alice.set_index(10) self.maxDiff = None def test_create(self): tx = StakeTransaction.create(activation_blocknumber=2, xmss=self.alice, slavePK=self.bob.pk(), hashchain_terminator=sha256(b'T1')) self.assertTrue(tx) def test_to_json(self): tx = StakeTransaction.create(activation_blocknumber=2, xmss=self.alice, slavePK=self.bob.pk(), hashchain_terminator=sha256(b'T1')) txjson = tx.to_json() self.assertEqual(json.loads(test_json_Stake), json.loads(txjson)) def test_from_json(self): tx = Transaction.from_json(test_json_Stake) self.assertIsInstance(tx, StakeTransaction) # Test that common Transaction components were copied over. self.assertEqual(0, tx.nonce) self.assertEqual( b'Q223bc5e5b78edfd778b1bf72702061cc053010711ffeefb9d969318be5d7b86b021b73c2', tx.txfrom) self.assertEqual( '3c523f9cc26f800863c003524392806ff6df373acb4d47cc607b62365fe4ab77' 'cf3018d321df7dcb653c9f7968673e43d12cc26e3461b5f425fd5d977400fea5', bin2hstr(tx.PK)) self.assertEqual( '06b0fcaf2e2ca69299a8a2ce32f0c05cd14cd61e25a9e324ffad8abc5a88aa7f', bin2hstr(tx.txhash)) self.assertEqual(10, tx.ots_key) self.assertEqual(b'', tx.signature) self.assertEqual( 'e2e3d8b08e65b25411af455eb9bb402827fa7b600fa0b36011d62e26899dfa05', bin2hstr(tx.pubhash)) # Test that specific content was copied over. self.assertEqual(2, tx.activation_blocknumber) self.assertEqual( '380793debf8f72e70ef7351ee5005df6c7ca2320ff49e0ead0c40b19c7bb1cc1' '496e19a482c06350bdc054e4ed52a24ec8c994c44f9341d01190a81ab093ade8', bin2hstr(tx.slave_public_key)) self.assertEqual( '1f93603db53bfad5c92390f735d0cbb8617b4ab8214ae91c5664a3d1e9b009c8', bin2hstr(tx.hash)) def test_validate_tx(self): tx = StakeTransaction.create(activation_blocknumber=2, xmss=self.alice, slavePK=self.bob.pk(), hashchain_terminator=sha256(b'T1')) # We must sign the tx before validation will work. tx.sign(self.alice) # We haven't touched the tx: validation should pass self.assertTrue(tx.validate_or_raise()) def test_get_message_hash(self): tx = StakeTransaction.create(activation_blocknumber=2, xmss=self.alice, slavePK=self.bob.pk(), hashchain_terminator=sha256(b'T1')) # Currently, a Transaction's message is always blank (what is it used for?) self.assertEqual( '06b0fcaf2e2ca69299a8a2ce32f0c05cd14cd61e25a9e324ffad8abc5a88aa7f', bin2hstr(tuple(tx.get_message_hash())))
class TestSimpleTransaction(TestCase): def __init__(self, *args, **kwargs): super(TestSimpleTransaction, self).__init__(*args, **kwargs) self.alice = XMSS(4, seed='a' * 48) self.bob = XMSS(4, seed='b' * 48) self.alice.set_index(10) self.maxDiff = None def test_create(self): # Alice sending coins to Bob tx = TransferTransaction.create( addr_from=self.alice.get_address().encode(), addr_to=self.bob.get_address().encode(), amount=100, fee=1, xmss_pk=self.alice.pk(), xmss_ots_index=self.alice.get_index()) self.assertTrue(tx) def test_create_negative_amount(self): with self.assertRaises(ValueError): TransferTransaction.create( addr_from=self.alice.get_address().encode(), addr_to=self.bob.get_address().encode(), amount=-100, fee=1, xmss_pk=self.alice.pk(), xmss_ots_index=self.alice.get_index()) def test_create_negative_fee(self): with self.assertRaises(ValueError): TransferTransaction.create( addr_from=self.alice.get_address().encode(), addr_to=self.bob.get_address().encode(), amount=-100, fee=-1, xmss_pk=self.alice.pk(), xmss_ots_index=self.alice.get_index()) def test_to_json(self): tx = TransferTransaction.create( addr_from=self.alice.get_address().encode(), addr_to=self.bob.get_address().encode(), amount=100, fee=1, xmss_pk=self.alice.pk(), xmss_ots_index=self.alice.get_index()) txjson = tx.to_json() self.assertEqual(json.loads(test_json_Simple), json.loads(txjson)) def test_from_json(self): tx = Transaction.from_json(test_json_Simple) self.assertIsInstance(tx, TransferTransaction) self.assertEqual(tx.subtype, qrl_pb2.Transaction.TRANSFER) # Test that common Transaction components were copied over. self.assertEqual(0, tx.nonce) self.assertEqual( b'Q223bc5e5b78edfd778b1bf72702061cc053010711ffeefb9d969318be5d7b86b021b73c2', tx.txfrom) self.assertEqual( '3c523f9cc26f800863c003524392806ff6df373acb4d47cc607b62365fe4ab77' 'cf3018d321df7dcb653c9f7968673e43d12cc26e3461b5f425fd5d977400fea5', bin2hstr(tx.PK)) self.assertEqual( '986299314d1489f0c23d70b689639c9c0059588563582cb7b21439b61583a5c0', bin2hstr(tx.txhash)) self.assertEqual(10, tx.ots_key) self.assertEqual(b'', tx.signature) self.assertEqual( 'e2e3d8b08e65b25411af455eb9bb402827fa7b600fa0b36011d62e26899dfa05', bin2hstr(tx.pubhash)) # Test that specific content was copied over. self.assertEqual( b'Qfd5d64455903b8e500a14cafb1c4ea95a1f97562aaaa24d83e5b9dc3861a47386ce9ad15', tx.txto) self.assertEqual(100, tx.amount) self.assertEqual(1, tx.fee) def test_validate_tx(self): # If we change amount, fee, txfrom, txto, (maybe include xmss stuff) txhash should change. tx = TransferTransaction.create( addr_from=self.alice.get_address().encode(), addr_to=self.bob.get_address().encode(), amount=100, fee=1, xmss_pk=self.alice.pk(), xmss_ots_index=self.alice.get_index()) # We must sign the tx before validation will work. tx.sign(self.alice) # We have not touched the tx: validation should pass. self.assertTrue(tx.validate_or_raise()) def test_state_validate_tx(self): # Test balance not enough # Test negative tx amounts pass
def slave_tx_generate(ctx, src, addr_from, number_of_slaves, access_type, fee, pk, otsidx): """ Generates Slave Transaction for the wallet """ try: address_src, src_xmss = _select_wallet(ctx, src) if len(addr_from.strip()) == 0: addr_from = address_src if src_xmss: address_src_pk = src_xmss.pk() address_src_otsidx = src_xmss.get_index() else: address_src_pk = pk.encode() address_src_otsidx = int(otsidx) fee_shor = int(fee * 1.e9) except Exception as e: click.echo("Error validating arguments") quit(1) slave_xmss = [] slave_pks = [] access_types = [] slave_xmss_seed = [] if number_of_slaves > 100: click.echo("Error: Max Limit for the number of slaves is 100") quit(1) for i in range(number_of_slaves): print("Generating Slave #"+str(i+1)) xmss = XMSS(config.dev.xmss_tree_height) slave_xmss.append(xmss) slave_xmss_seed.append(xmss.get_seed()) slave_pks.append(xmss.pk()) access_types.append(access_type) print("Successfully Generated Slave %s/%s" % (str(i + 1), number_of_slaves)) channel = grpc.insecure_channel(ctx.obj.node_public_address) stub = qrl_pb2_grpc.PublicAPIStub(channel) # FIXME: This could be problematic. Check slaveTxnReq = qrl_pb2.SlaveTxnReq(address_from=addr_from, slave_pks=slave_pks, access_types=access_types, fee=fee_shor, xmss_pk=address_src_pk, xmss_ots_index=address_src_otsidx) try: slaveTxnResp = stub.GetSlaveTxn(slaveTxnReq, timeout=5) tx = Transaction.from_pbdata(slaveTxnResp.transaction_unsigned) tx.sign(src_xmss) with open('slaves.json', 'w') as f: json.dump([src_xmss.get_address(), slave_xmss_seed, tx.to_json()], f) click.echo('Successfully created slaves.json') click.echo('Move slaves.json file from current directory to the mining node inside ~/.qrl/') except grpc.RpcError as e: click.echo(e.details()) quit(1) except Exception as e: click.echo("Unhandled error: {}".format(str(e))) quit(1)