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_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 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 pre_pos_1(self, data=None): # triggered after genesis for block 1.. logger.info('pre_pos_1') # are we a staker in the stake list? genesis_block = self.buffered_chain.get_block(0) found = False for genesisBalance in genesis_block.genesis_balance: if genesisBalance.address.encode( ) == self.buffered_chain.staking_address: logger.info('Found in Genesis Address %s %s', genesisBalance.address.encode(), genesisBalance.balance) found = True break if not found: return logger.info('mining address: %s in the genesis.stake_list', self.buffered_chain.staking_address) xmss = self.buffered_chain.wallet.address_bundle[0].xmss tmphc = hashchain(xmss.get_seed_private(), epoch=0) self.buffered_chain.hash_chain[0] = tmphc.hashchain slave_xmss = self.buffered_chain.get_slave_xmss(0) if not slave_xmss: logger.info('Waiting for SLAVE XMSS to be done') reactor.callLater(5, self.pre_pos_1) return signing_xmss = self.buffered_chain.wallet.address_bundle[0].xmss st = StakeTransaction.create(activation_blocknumber=1, xmss=signing_xmss, slavePK=slave_xmss.pk(), hashchain_terminator=tmphc.hc_terminator) st.sign(signing_xmss) self.buffered_chain.tx_pool.add_tx_to_pool(st) # send the stake tx to generate hashchain terminators for the staker addresses.. self.p2p_factory.broadcast_st(st) vote = Vote.create( addr_from=self.buffered_chain.wallet.address_bundle[0].address, blocknumber=0, headerhash=genesis_block.headerhash, xmss=slave_xmss) vote.sign(slave_xmss) self.buffered_chain.add_vote(vote) # send the stake votes for genesis block self.p2p_factory.broadcast_vote(vote) logger.info('await delayed call to build staker list from genesis') reactor.callLater(5, self.pre_pos_2, st)
def test_getStakers(self): db_state = Mock(spec=State) db_state.stake_validators_tracker = Mock(spec=StakeValidatorsTracker) db_state.stake_validators_tracker.sv_dict = dict() p2p_factory = Mock(spec=P2PFactory) buffered_chain = Mock(spec=BufferedChain) buffered_chain.tx_pool = Mock() buffered_chain.get_block = Mock() buffered_chain._chain = Mock() qrlnode = QRLNode(db_state) qrlnode.set_p2pfactory(p2p_factory) qrlnode.set_chain(buffered_chain) service = PublicAPIService(qrlnode) context = Mock(spec=ServicerContext) request = qrl_pb2.GetStakersReq(filter=qrl_pb2.GetStakersReq.CURRENT, offset=0, quantity=3) response = service.GetStakers(request=request, context=context) context.set_code.assert_not_called() context.set_details.assert_not_called() self.assertEqual(0, len(response.stakers)) # Add a few validators stake_tx = StakeTransaction.create(1, get_alice_xmss(), get_bob_xmss().pk(), sha256(b'terminator')) expected_address = bytes(get_alice_xmss().get_address().encode()) db_state.get_address = MagicMock( return_value=AddressState.create(address=expected_address, nonce=1, balance=100, pubhashes=[], tokens=dict())) db_state.get_address_tx_hashes = MagicMock(return_value=[]) validator1 = StakeValidator.create(100, stake_tx) db_state.stake_validators_tracker.sv_dict[ validator1.address] = validator1 request = qrl_pb2.GetStakersReq(filter=qrl_pb2.GetStakersReq.CURRENT, offset=0, quantity=3) response = service.GetStakers(request=request, context=context) context.set_code.assert_not_called() context.set_details.assert_not_called() self.assertEqual(1, len(response.stakers)) self.assertEqual(expected_address, response.stakers[0].address_state.address)
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_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())))
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_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_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_stake_tx(self, curr_blocknumber): sv_dict = self.buffered_chain.stake_list_get(curr_blocknumber) if self.buffered_chain.staking_address in sv_dict: activation_blocknumber = sv_dict[ self.buffered_chain. staking_address].activation_blocknumber + config.dev.blocks_per_epoch else: activation_blocknumber = curr_blocknumber + 2 # Activate as Stake Validator, 2 blocks after current block if activation_blocknumber < curr_blocknumber: activation_blocknumber = curr_blocknumber + 2 balance = self.buffered_chain.get_stxn_state( curr_blocknumber, self.buffered_chain.staking_address).balance if balance < config.dev.minimum_staking_balance_required: logger.warning('Staking not allowed due to insufficient balance') logger.warning('Balance %s', balance) return slave_xmss = self.buffered_chain.get_slave_xmss(activation_blocknumber) if not slave_xmss: return signing_xmss = self.buffered_chain.wallet.address_bundle[0].xmss st = StakeTransaction.create( activation_blocknumber=activation_blocknumber, xmss=signing_xmss, slavePK=slave_xmss.pk()) st.sign(signing_xmss) tx_state = self.buffered_chain.get_stxn_state(curr_blocknumber, st.txfrom) if not (st.validate() and st.validate_extended(tx_state)): logger.warning( 'Create St Txn failed due to validation failure, will retry next block' ) return self.p2p_factory.broadcast_st(st) for num in range(len(self.buffered_chain.tx_pool.transaction_pool)): t = self.buffered_chain.tx_pool.transaction_pool[num] if t.subtype == qrl_pb2.Transaction.STAKE and st.hash == t.hash: if st.get_message_hash() == t.get_message_hash(): return self.buffered_chain.tx_pool.remove_tx_from_pool(t) break self.buffered_chain.tx_pool.add_tx_to_pool(st) self.buffered_chain.wallet.save_wallet()
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_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)
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)