Exemple #1
0
    def run_test(self):
        self.reset()

        daemon = Daemon()
        wallet = Wallet()

        # close the wallet if any, will throw if none is loaded
        try:
            wallet.close_wallet()
        except:
            pass
        wallet.restore_deterministic_wallet(
            'velvet lymph giddy number token physics poetry unquoted nibs useful sabotage limits benches lifestyle eden nitrogen anvil fewest avoid batch vials washing fences goat unquoted'
        )

        destinations = []
        for i in range(3):
            destinations.append({
                "amount":
                1,
                "address":
                '888tNkZrPN6JsEgekjMnABU4TBzc2Dt29EPAvkRxbANsAnjyPbb3iQ1YBRk1UXcdRsiKc9dhwMVgN5S9cQUiyoogDavup3H'
            })

        self._test_speed_generateblocks(daemon=daemon, blocks=70)
        for i in range(1, 10):
            while wallet.get_balance().unlocked_balance == 0:
                print('Waiting for wallet to refresh...')
                sleep(1)
            self._test_speed_transfer_split(wallet=wallet)
        self._test_speed_generateblocks(daemon=daemon, blocks=10)
Exemple #2
0
    def run_test(self):
        self.reset()

        daemon = Daemon()
        wallet = Wallet()

        # close the wallet if any, will throw if none is loaded
        try:
            wallet.close_wallet()
        except:
            pass
        wallet.restore_deterministic_wallet(
            'velvet lymph giddy number token physics poetry unquoted nibs useful sabotage limits benches lifestyle eden nitrogen anvil fewest avoid batch vials washing fences goat unquoted'
        )

        destinations = []
        for i in range(3):
            destinations.append({
                "amount":
                1,
                "address":
                '44AFFq5kSiGBoZ4NMDwYtN18obc8AemS33DBLWs3H7otXft3XjrpDtQGv7SqSsaBYBb98uNbr2VBBEt7f2wfn3RVGQBEP3A'
            })

        self._test_speed_generateblocks(daemon=daemon, blocks=70)
        for i in range(1, 10):
            while wallet.get_balance().unlocked_balance == 0:
                print('Waiting for wallet to refresh...')
                sleep(1)
            self._test_speed_transfer_split(wallet=wallet)
        self._test_speed_generateblocks(daemon=daemon, blocks=10)
    def open_close(self):
        print('Testing open/close')
        wallet = Wallet()

        res = wallet.get_address()
        assert res.address == '42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm'

        wallet.close_wallet()
        ok = False
        try: res = wallet.get_address()
        except: ok = True
        assert ok

        wallet.restore_deterministic_wallet(seed = 'peeled mixture ionic radar utopia puddle buying illness nuns gadget river spout cavernous bounced paradise drunk looking cottage jump tequila melting went winter adjust spout')
        res = wallet.get_address()
        assert res.address == '44Kbx4sJ7JDRDV5aAhLJzQCjDz2ViLRduE3ijDZu3osWKBjMGkV1XPk4pfDUMqt1Aiezvephdqm6YD19GKFD9ZcXVUTp6BW'

        wallet.close_wallet()
        ok = False
        try: wallet.get_address()
        except: ok = True
        assert ok

        wallet.restore_deterministic_wallet(seed = 'velvet lymph giddy number token physics poetry unquoted nibs useful sabotage limits benches lifestyle eden nitrogen anvil fewest avoid batch vials washing fences goat unquoted')
        res = wallet.get_address()
        assert res.address == '42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm'
    def open_close(self):
        print('Testing open/close')
        wallet = Wallet()

        res = wallet.get_address()
        assert res.address == '42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm'

        wallet.close_wallet()
        ok = False
        try: res = wallet.get_address()
        except: ok = True
        assert ok

        wallet.restore_deterministic_wallet(seed = 'peeled mixture ionic radar utopia puddle buying illness nuns gadget river spout cavernous bounced paradise drunk looking cottage jump tequila melting went winter adjust spout')
        res = wallet.get_address()
        assert res.address == '44Kbx4sJ7JDRDV5aAhLJzQCjDz2ViLRduE3ijDZu3osWKBjMGkV1XPk4pfDUMqt1Aiezvephdqm6YD19GKFD9ZcXVUTp6BW'

        wallet.close_wallet()
        ok = False
        try: wallet.get_address()
        except: ok = True
        assert ok

        wallet.restore_deterministic_wallet(seed = 'velvet lymph giddy number token physics poetry unquoted nibs useful sabotage limits benches lifestyle eden nitrogen anvil fewest avoid batch vials washing fences goat unquoted')
        res = wallet.get_address()
        assert res.address == '42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm'
Exemple #5
0
    def store(self):
        print('Testing store')
        wallet = Wallet()

        # close the wallet if any, will throw if none is loaded
        try:
            wallet.close_wallet()
        except:
            pass

        self.remove_wallet_files('test1')

        seed = 'velvet lymph giddy number token physics poetry unquoted nibs useful sabotage limits benches lifestyle eden nitrogen anvil fewest avoid batch vials washing fences goat unquoted'
        res = wallet.restore_deterministic_wallet(seed=seed, filename='test1')
        assert res.address == '42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm'
        assert res.seed == seed

        self.remove_file('test1')
        assert self.file_exists('test1.keys')
        assert not self.file_exists('test1')
        wallet.store()
        assert self.file_exists('test1.keys')
        assert self.file_exists('test1')

        wallet.close_wallet()
        self.remove_wallet_files('test1')
Exemple #6
0
 def create(self):
     print('Creating wallet')
     wallet = Wallet()
     # close the wallet if any, will throw if none is loaded
     try: wallet.close_wallet()
     except: pass
     res = wallet.restore_deterministic_wallet(seed = 'velvet lymph giddy number token physics poetry unquoted nibs useful sabotage limits benches lifestyle eden nitrogen anvil fewest avoid batch vials washing fences goat unquoted')
Exemple #7
0
    def change_password(self):
        print('Testing password change')
        wallet = Wallet()

        # close the wallet if any, will throw if none is loaded
        try: wallet.close_wallet()
        except: pass

        self.remove_wallet_files('test1')

        seed = 'velvet lymph giddy number token physics poetry unquoted nibs useful sabotage limits benches lifestyle eden nitrogen anvil fewest avoid batch vials washing fences goat unquoted'
        res = wallet.restore_deterministic_wallet(seed = seed, filename = 'test1')
        assert res.address == '42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm'
        assert res.seed == seed

        wallet.close_wallet()
        res = wallet.open_wallet('test1', password = '')
        res = wallet.get_address()
        assert res.address == '42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm'

        res = wallet.change_wallet_password(old_password = '', new_password = '******')
        wallet.close_wallet()

        ok = False
        try: res = wallet.open_wallet('test1', password = '')
        except: ok = True
        assert ok

        res = wallet.open_wallet('test1', password = '******')
        res = wallet.get_address()
        assert res.address == '42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm'

        wallet.close_wallet()

        self.remove_wallet_files('test1')
Exemple #8
0
 def create(self):
     print('Creating wallet')
     wallet = Wallet()
     # close the wallet if any, will throw if none is loaded
     try: wallet.close_wallet()
     except: pass
     res = wallet.restore_deterministic_wallet(seed = 'velvet lymph giddy number token physics poetry unquoted nibs useful sabotage limits benches lifestyle eden nitrogen anvil fewest avoid batch vials washing fences goat unquoted')
Exemple #9
0
 def create(self):
     print 'Creating wallet'
     wallet = Wallet()
     # close the wallet if any, will throw if none is loaded
     try: wallet.close_wallet()
     except: pass
     seed = 'velvet lymph giddy number token physics poetry unquoted nibs useful sabotage limits benches lifestyle eden nitrogen anvil fewest avoid batch vials washing fences goat unquoted'
     res = wallet.restore_deterministic_wallet(seed = seed)
     assert res.address == '42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm'
     assert res.seed == seed
 def create(self):
     print('Creating wallet')
     wallet = Wallet()
     # close the wallet if any, will throw if none is loaded
     try: wallet.close_wallet()
     except: pass
     seed = 'velvet lymph giddy number token physics poetry unquoted nibs useful sabotage limits benches lifestyle eden nitrogen anvil fewest avoid batch vials washing fences goat unquoted'
     res = wallet.restore_deterministic_wallet(seed = seed)
     assert res.address == '42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm'
     assert res.seed == seed
Exemple #11
0
class AddressValidationTest():
    def run_test(self):
      self.create()
      self.check_bad_addresses()
      self.check_good_addresses()

    def create(self):
        print('Creating wallet')
        seed = 'velvet lymph giddy number token physics poetry unquoted nibs useful sabotage limits benches lifestyle eden nitrogen anvil fewest avoid batch vials washing fences goat unquoted'
        address = '42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm'
        self.wallet = Wallet()
        # close the wallet if any, will throw if none is loaded
        try: self.wallet.close_wallet()
        except: pass
        res = self.wallet.restore_deterministic_wallet(seed = seed)
        assert res.address == address
        assert res.seed == seed

    def check_bad_addresses(self):
        print('Validating bad addresses')
        bad_addresses = ['', 'a', '42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWD9', ' ', '@', '42ey']
        for address in bad_addresses:
            res = self.wallet.validate_address(address, any_net_type = False)
            assert not res.valid
            res = self.wallet.validate_address(address, any_net_type = True)
            assert not res.valid

    def check_good_addresses(self):
        print('Validating good addresses')
        addresses = [
            [ 'mainnet',  '', '42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm' ],
            [ 'mainnet',  '', '44Kbx4sJ7JDRDV5aAhLJzQCjDz2ViLRduE3ijDZu3osWKBjMGkV1XPk4pfDUMqt1Aiezvephdqm6YD19GKFD9ZcXVUTp6BW' ],
            [ 'testnet',  '', '9ujeXrjzf7bfeK3KZdCqnYaMwZVFuXemPU8Ubw335rj2FN1CdMiWNyFV3ksEfMFvRp9L9qum5UxkP5rN9aLcPxbH1au4WAB' ],
            [ 'stagenet', '', '53teqCAESLxeJ1REzGMAat1ZeHvuajvDiXqboEocPaDRRmqWoVPzy46GLo866qRFjbNhfkNckyhST3WEvBviDwpUDd7DSzB' ],
            [ 'mainnet', 'i', '4BxSHvcgTwu25WooY4BVmgdcKwZu5EksVZSZkDd6ooxSVVqQ4ubxXkhLF6hEqtw96i9cf3cVfLw8UWe95bdDKfRQeYtPwLm1Jiw7AKt2LY' ],
            [ 'mainnet', 's', '8AsN91rznfkBGTY8psSNkJBg9SZgxxGGRUhGwRptBhgr5XSQ1XzmA9m8QAnoxydecSh5aLJXdrgXwTDMMZ1AuXsN1EX5Mtm' ],
            [ 'mainnet', 's', '86kKnBKFqzCLxtK1Jmx2BkNBDBSMDEVaRYMMyVbeURYDWs8uNGDZURKCA5yRcyMxHzPcmCf1q2fSdhQVcaKsFrtGRsdGfNk' ],
            [ 'testnet', 'i', 'AApMA1VuhiCaHzr5X2KXi2Zc9oJ3VaGjkfChxxpRpxkyKf1NetvbRbQTbFMrGkr85DjnEH7JsBaoUFsgKwZnmtnVWnoB8MDotCsLb7eWwz' ],
            [ 'testnet', 's', 'BdKg9udkvckC5T58a8Nmtb6BNsgRAxs7uA2D49sWNNX5HPW5Us6Wxu8QMXrnSx3xPBQQ2iu9kwEcRGAoiz6EPmcZKbF62GS' ],
            [ 'testnet', 's', 'BcFvPa3fT4gVt5QyRDe5Vv7VtUFao9ci8NFEy3r254KF7R1N2cNB5FYhGvrHbMStv4D6VDzZ5xtxeKV8vgEPMnDcNFuwZb9' ],
            [ 'stagenet', 'i', '5K8mwfjumVseCcQEjNbf59Um6R9NfVUNkHTLhhPCmNvgDLVS88YW5tScnm83rw9mfgYtchtDDTW5jEfMhygi27j1QYphX38hg6m4VMtN29' ],
            [ 'stagenet', 's', '73LhUiix4DVFMcKhsPRG51QmCsv8dYYbL6GcQoLwEEFvPvkVvc7BhebfA4pnEFF9Lq66hwvLqBvpHjTcqvpJMHmmNjPPBqa' ],
            [ 'stagenet', 's', '7A1Hr63MfgUa8pkWxueD5xBqhQczkusYiCMYMnJGcGmuQxa7aDBxN1G7iCuLCNB3VPeb2TW7U9FdxB27xKkWKfJ8VhUZthF' ],
        ]
        for any_net_type in [True, False]:
            for address in addresses:
                res = self.wallet.validate_address(address[2], any_net_type = any_net_type)
                if any_net_type or address[0] == 'mainnet':
                    assert res.valid
                    assert res.integrated == (address[1] == 'i')
                    assert res.subaddress == (address[1] == 's')
                    assert res.nettype == address[0]
                else:
                    assert not res.valid
class GetOutputDistributionTest():
    def run_test(self):
        self.reset()
        self.create()
        self.test_get_output_distribution()

    def reset(self):
        print('Resetting blockchain')
        daemon = Daemon()
        res = daemon.get_height()
        daemon.pop_blocks(res.height - 1)
        daemon.flush_txpool()

    def create(self):
        self.wallet = Wallet()
        # close the wallet if any, will throw if none is loaded
        try:
            self.wallet.close_wallet()
        except:
            pass
        res = self.wallet.restore_deterministic_wallet(
            seed=
            'velvet lymph giddy number token physics poetry unquoted nibs useful sabotage limits benches lifestyle eden nitrogen anvil fewest avoid batch vials washing fences goat unquoted'
        )

    def test_get_output_distribution(self):
        print("Test get_output_distribution")

        daemon = Daemon()

        res = daemon.get_output_distribution([0], 0, 0)
        assert len(res.distributions) == 1
        d = res.distributions[0]
        assert d.amount == 0
        assert d.base == 0
        assert d.binary == False
        assert len(d.distribution) == 1
        assert d.distribution[0] == 0

        res = daemon.generateblocks(
            '42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm',
            1)

        res = daemon.get_output_distribution([0], 0, 0)
        assert len(res.distributions) == 1
        d = res.distributions[0]
        assert d.amount == 0
        assert d.base == 0
        assert d.binary == False
        assert len(d.distribution) == 2
        assert d.distribution[0] == 0
        assert d.distribution[1] == 1

        res = daemon.pop_blocks(1)

        res = daemon.get_output_distribution([0], 0, 0)
        assert len(res.distributions) == 1
        d = res.distributions[0]
        assert d.amount == 0
        assert d.base == 0
        assert d.binary == False
        assert len(d.distribution) == 1
        assert d.distribution[0] == 0

        res = daemon.generateblocks(
            '42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm',
            3)

        res = daemon.get_output_distribution([0], 0, 0, cumulative=True)
        assert len(res.distributions) == 1
        d = res.distributions[0]
        assert d.amount == 0
        assert d.base == 0
        assert d.binary == False
        assert len(d.distribution) == 4
        assert d.distribution[0] == 0
        assert d.distribution[1] == 1
        assert d.distribution[2] == 2
        assert d.distribution[3] == 3

        # extend
        res = daemon.generateblocks(
            '42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm',
            80)

        res = daemon.get_output_distribution([0], 0, 0, cumulative=True)
        assert len(res.distributions) == 1
        d = res.distributions[0]
        assert d.amount == 0
        assert d.base == 0
        assert d.binary == False
        assert len(d.distribution) == 84
        for h in range(len(d.distribution)):
            assert d.distribution[h] == h

        # pop and replace, this will do through the "trim and extend" path
        res = daemon.pop_blocks(2)
        self.wallet.refresh()
        dst = {
            'address':
            '42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm',
            'amount': 1000000000000
        }
        self.wallet.transfer([dst])
        res = daemon.generateblocks(
            '42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm',
            1)
        for step in range(
                3
        ):  # the second will be cached, the third will also be cached, but we get it in non-cumulative mode
            res = daemon.get_output_distribution([0],
                                                 0,
                                                 0,
                                                 cumulative=step < 3)
            assert len(res.distributions) == 1
            d = res.distributions[0]
            assert d.amount == 0
            assert d.base == 0
            assert d.binary == False
            assert len(d.distribution) == 83
            for h in range(len(d.distribution)):
                assert d.distribution[h] == (h if step < 3 else 1) + (
                    2 if h == len(d.distribution) - 1 else 0)

        # start at 0, end earlier
        res = daemon.get_output_distribution([0], 0, 40, cumulative=True)
        assert len(res.distributions) == 1
        d = res.distributions[0]
        assert d.amount == 0
        assert d.base == 0
        assert d.binary == False
        assert len(d.distribution) == 41
        for h in range(len(d.distribution)):
            assert d.distribution[h] == h

        # start after 0, end earlier
        res = daemon.get_output_distribution([0], 10, 20, cumulative=True)
        assert len(res.distributions) == 1
        d = res.distributions[0]
        assert d.amount == 0
        assert d.base == 9
        assert d.binary == False
        assert len(d.distribution) == 11
        for h in range(len(d.distribution)):
            assert d.distribution[h] == 10 + h

        # straddling up
        res = daemon.get_output_distribution([0], 15, 25, cumulative=True)
        assert len(res.distributions) == 1
        d = res.distributions[0]
        assert d.amount == 0
        assert d.base == 14
        assert d.binary == False
        assert len(d.distribution) == 11
        for h in range(len(d.distribution)):
            assert d.distribution[h] == 15 + h

        # straddling down
        res = daemon.get_output_distribution([0], 8, 18, cumulative=True)
        assert len(res.distributions) == 1
        d = res.distributions[0]
        assert d.amount == 0
        assert d.base == 7
        assert d.binary == False
        assert len(d.distribution) == 11
        for h in range(len(d.distribution)):
            assert d.distribution[h] == 8 + h

        # encompassing
        res = daemon.get_output_distribution([0], 5, 20, cumulative=True)
        assert len(res.distributions) == 1
        d = res.distributions[0]
        assert d.amount == 0
        assert d.base == 4
        assert d.binary == False
        assert len(d.distribution) == 16
        for h in range(len(d.distribution)):
            assert d.distribution[h] == 5 + h

        # single
        res = daemon.get_output_distribution([0], 2, 2, cumulative=True)
        assert len(res.distributions) == 1
        d = res.distributions[0]
        assert d.amount == 0
        assert d.base == 1
        assert d.binary == False
        assert len(d.distribution) == 1
        assert d.distribution[0] == 2

        # a non existent amount
        res = daemon.get_output_distribution([1], 0, 0)
        assert len(res.distributions) == 1
        d = res.distributions[0]
        assert d.amount == 1
        assert d.base == 0
        assert d.binary == False
        assert len(d.distribution) == 83
        for h in range(len(d.distribution)):
            assert d.distribution[h] == 0
Exemple #13
0
class P2PTest():
    def run_test(self):
        self.reset()
        self.create()
        self.mine(80)
        self.test_p2p_reorg()
        self.test_p2p_tx_propagation()

    def reset(self):
        print('Resetting blockchain')
        daemon = Daemon()
        res = daemon.get_height()
        daemon.pop_blocks(res.height - 1)
        daemon.flush_txpool()

    def create(self):
        print('Creating wallet')
        seed = 'velvet lymph giddy number token physics poetry unquoted nibs useful sabotage limits benches lifestyle eden nitrogen anvil fewest avoid batch vials washing fences goat unquoted'
        self.wallet = Wallet(idx=4)
        # close the wallet if any, will throw if none is loaded
        try:
            self.wallet.close_wallet()
        except:
            pass
        res = self.wallet.restore_deterministic_wallet(seed=seed)

    def mine(self, blocks):
        assert blocks >= 1

        print("Generating", blocks, 'blocks')

        daemon = Daemon(idx=2)

        # generate blocks
        res_generateblocks = daemon.generateblocks(
            '42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm',
            blocks)

    def test_p2p_reorg(self):
        print('Testing P2P reorg')
        daemon2 = Daemon(idx=2)
        daemon3 = Daemon(idx=3)

        # give sync some time
        time.sleep(1)

        res = daemon2.get_info()
        height = res.height
        assert height > 0
        top_block_hash = res.top_block_hash
        assert len(top_block_hash) == 64

        res = daemon3.get_info()
        assert res.height == height
        assert res.top_block_hash == top_block_hash

        # disconnect daemons and mine separately on both
        daemon2.out_peers(0)
        daemon3.out_peers(0)

        res = daemon2.generateblocks(
            '42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm',
            2)
        res = daemon3.generateblocks(
            '42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm',
            3)

        res = daemon2.get_info()
        assert res.height == height + 2
        daemon2_top_block_hash = res.top_block_hash
        assert daemon2_top_block_hash != top_block_hash
        res = daemon3.get_info()
        assert res.height == height + 3
        daemon3_top_block_hash = res.top_block_hash
        assert daemon3_top_block_hash != top_block_hash
        assert daemon3_top_block_hash != daemon2_top_block_hash

        # reconnect, daemon2 will now switch to daemon3's chain
        daemon2.out_peers(8)
        daemon3.out_peers(8)
        time.sleep(10)
        res = daemon2.get_info()
        assert res.height == height + 3
        assert res.top_block_hash == daemon3_top_block_hash

        # disconect, mine on daemon2 again more than daemon3
        daemon2.out_peers(0)
        daemon3.out_peers(0)

        res = daemon2.generateblocks(
            '42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm',
            3)
        res = daemon3.generateblocks(
            '42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm',
            2)

        res = daemon2.get_info()
        assert res.height == height + 6
        daemon2_top_block_hash = res.top_block_hash
        assert daemon2_top_block_hash != top_block_hash
        res = daemon3.get_info()
        assert res.height == height + 5
        daemon3_top_block_hash = res.top_block_hash
        assert daemon3_top_block_hash != top_block_hash
        assert daemon3_top_block_hash != daemon2_top_block_hash

        # reconnect, daemon3 will now switch to daemon2's chain
        daemon2.out_peers(8)
        daemon3.out_peers(8)
        time.sleep(5)
        res = daemon3.get_info()
        assert res.height == height + 6
        assert res.top_block_hash == daemon2_top_block_hash

        # disconnect and mine a lot on daemon3
        daemon2.out_peers(0)
        daemon3.out_peers(0)
        res = daemon3.generateblocks(
            '42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm',
            500)

        # reconnect and wait for sync
        daemon2.out_peers(8)
        daemon3.out_peers(8)
        loops = 100
        while True:
            res2 = daemon2.get_info()
            res3 = daemon3.get_info()
            if res2.top_block_hash == res3.top_block_hash:
                break
            time.sleep(10)
            loops -= 1
            assert loops >= 0

    def test_p2p_tx_propagation(self):
        print('Testing P2P tx propagation')
        daemon2 = Daemon(idx=2)
        daemon3 = Daemon(idx=3)

        for daemon in [daemon2, daemon3]:
            res = daemon.get_transaction_pool_hashes()
            assert not 'tx_hashes' in res or len(res.tx_hashes) == 0

        self.wallet.refresh()
        res = self.wallet.get_balance()

        dst = {
            'address':
            '42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm',
            'amount': 1000000000000
        }
        res = self.wallet.transfer([dst])
        assert len(res.tx_hash) == 32 * 2
        txid = res.tx_hash

        time.sleep(5)

        for daemon in [daemon2, daemon3]:
            res = daemon.get_transaction_pool_hashes()
            assert len(res.tx_hashes) == 1
            assert res.tx_hashes[0] == txid
class ColdSigningTest():
    def run_test(self):
        self.reset()
        self.create(0)
        self.mine()
        self.transfer()

    def reset(self):
        print('Resetting blockchain')
        daemon = Daemon()
        res = daemon.get_height()
        daemon.pop_blocks(res.height - 1)
        daemon.flush_txpool()

    def create(self, idx):
        print('Creating hot and cold wallet')

        self.hot_wallet = Wallet(idx=0)
        # close the wallet if any, will throw if none is loaded
        try:
            self.hot_wallet.close_wallet()
        except:
            pass

        self.cold_wallet = Wallet(idx=1)
        # close the wallet if any, will throw if none is loaded
        try:
            self.cold_wallet.close_wallet()
        except:
            pass

        seed = 'velvet lymph giddy number token physics poetry unquoted nibs useful sabotage limits benches lifestyle eden nitrogen anvil fewest avoid batch vials washing fences goat unquoted'
        res = self.cold_wallet.restore_deterministic_wallet(seed=seed)
        self.cold_wallet.set_daemon('127.0.0.1:11111', ssl_support="disabled")
        spend_key = self.cold_wallet.query_key("spend_key").key
        view_key = self.cold_wallet.query_key("view_key").key
        res = self.hot_wallet.generate_from_keys(
            viewkey=view_key,
            address=
            '42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm'
        )

        ok = False
        try:
            res = self.hot_wallet.query_key("spend_key")
        except:
            ok = True
        assert ok
        ok = False
        try:
            self.hot_wallet.query_key("mnemonic")
        except:
            ok = True
        assert ok
        assert self.cold_wallet.query_key("view_key").key == view_key
        assert self.cold_wallet.get_address(
        ).address == self.hot_wallet.get_address().address

    def mine(self):
        print("Mining some blocks")
        daemon = Daemon()
        wallet = Wallet()

        daemon.generateblocks(
            '42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm',
            80)
        wallet.refresh()

    def transfer(self):
        daemon = Daemon()

        print("Creating transaction in hot wallet")

        dst = {
            'address':
            '42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm',
            'amount': 1000000000000
        }

        self.hot_wallet.refresh()
        res = self.hot_wallet.export_outputs()
        self.cold_wallet.import_outputs(res.outputs_data_hex)
        res = self.cold_wallet.export_key_images(True)
        self.hot_wallet.import_key_images(res.signed_key_images,
                                          offset=res.offset)

        res = self.hot_wallet.transfer([dst], ring_size=11, get_tx_key=False)
        assert len(res.tx_hash) == 32 * 2
        txid = res.tx_hash
        assert len(res.tx_key) == 0
        assert res.amount > 0
        amount = res.amount
        assert res.fee > 0
        fee = res.fee
        assert len(res.tx_blob) == 0
        assert len(res.tx_metadata) == 0
        assert len(res.multisig_txset) == 0
        assert len(res.unsigned_txset) > 0
        unsigned_txset = res.unsigned_txset

        print('Signing transaction with cold wallet')
        res = self.cold_wallet.describe_transfer(unsigned_txset=unsigned_txset)
        assert len(res.desc) == 1
        desc = res.desc[0]
        assert desc.amount_in >= amount + fee
        assert desc.amount_out == desc.amount_in - fee
        assert desc.ring_size == 11
        assert desc.unlock_time == 0
        assert desc.payment_id in ['', '0000000000000000']
        assert desc.change_amount == desc.amount_in - 1000000000000 - fee
        assert desc.change_address == '42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm'
        assert desc.fee == fee
        assert len(desc.recipients) == 1
        rec = desc.recipients[0]
        assert rec.address == '42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm'
        assert rec.amount == 1000000000000

        res = self.cold_wallet.sign_transfer(unsigned_txset)
        assert len(res.signed_txset) > 0
        signed_txset = res.signed_txset
        assert len(res.tx_hash_list) == 1
        txid = res.tx_hash_list[0]
        assert len(txid) == 64

        print('Submitting transaction with hot wallet')
        res = self.hot_wallet.submit_transfer(signed_txset)
        assert len(res.tx_hash_list) > 0
        assert res.tx_hash_list[0] == txid

        res = self.hot_wallet.get_transfers()
        assert len([
            x for x in (res['pending'] if 'pending' in res else [])
            if x.txid == txid
        ]) == 1
        assert len([
            x for x in (res['out'] if 'out' in res else []) if x.txid == txid
        ]) == 0

        daemon.generateblocks(
            '42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm',
            1)
        self.hot_wallet.refresh()

        res = self.hot_wallet.get_transfers()
        assert len([
            x for x in (res['pending'] if 'pending' in res else [])
            if x.txid == txid
        ]) == 0
        assert len([
            x for x in (res['out'] if 'out' in res else []) if x.txid == txid
        ]) == 1

        res = self.hot_wallet.get_tx_key(txid)
        assert len(
            res.tx_key
        ) == 0 or res.tx_key == '01' + '0' * 62  # identity is used as placeholder
        res = self.cold_wallet.get_tx_key(txid)
        assert len(res.tx_key) == 64
class ColdSigningTest():
    def run_test(self):
        self.reset()
        self.create(0)
        self.mine()
        self.transfer()

    def reset(self):
        print('Resetting blockchain')
        daemon = Daemon()
        daemon.pop_blocks(1000)
        daemon.flush_txpool()

    def create(self, idx):
        print('Creating hot and cold wallet')

        self.hot_wallet = Wallet(idx = 0)
        # close the wallet if any, will throw if none is loaded
        try: self.hot_wallet.close_wallet()
        except: pass

        self.cold_wallet = Wallet(idx = 1)
        # close the wallet if any, will throw if none is loaded
        try: self.cold_wallet.close_wallet()
        except: pass

        seed = 'velvet lymph giddy number token physics poetry unquoted nibs useful sabotage limits benches lifestyle eden nitrogen anvil fewest avoid batch vials washing fences goat unquoted'
        res = self.cold_wallet.restore_deterministic_wallet(seed = seed)
        self.cold_wallet.set_daemon('127.0.0.1:11111', ssl_support = "disabled")
        spend_key = self.cold_wallet.query_key("spend_key").key
        view_key = self.cold_wallet.query_key("view_key").key
        res = self.hot_wallet.generate_from_keys(viewkey = view_key, address = '42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm')

        ok = False
        try: res = self.hot_wallet.query_key("spend_key")
        except: ok = True
        assert ok
        ok = False
        try: self.hot_wallet.query_key("mnemonic")
        except: ok = True
        assert ok
        assert self.cold_wallet.query_key("view_key").key == view_key
        assert self.cold_wallet.get_address().address == self.hot_wallet.get_address().address

    def mine(self):
        print("Mining some blocks")
        daemon = Daemon()
        wallet = Wallet()

        daemon.generateblocks('42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm', 80)
        wallet.refresh()

    def transfer(self):
        daemon = Daemon()

        print("Creating transaction in hot wallet")

        dst = {'address': '42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm', 'amount': 1000000000000}
        payment_id = '1234500000012345abcde00000abcdeff1234500000012345abcde00000abcde'

        self.hot_wallet.refresh()
        res = self.hot_wallet.export_outputs()
        self.cold_wallet.import_outputs(res.outputs_data_hex)
        res = self.cold_wallet.export_key_images(True)
        self.hot_wallet.import_key_images(res.signed_key_images, offset = res.offset)

        res = self.hot_wallet.transfer([dst], ring_size = 11, payment_id = payment_id, get_tx_key = False)
        assert len(res.tx_hash) == 32*2
        txid = res.tx_hash
        assert len(res.tx_key) == 0
        assert res.amount > 0
        amount = res.amount
        assert res.fee > 0
        fee = res.fee
        assert len(res.tx_blob) == 0
        assert len(res.tx_metadata) == 0
        assert len(res.multisig_txset) == 0
        assert len(res.unsigned_txset) > 0
        unsigned_txset = res.unsigned_txset

        print('Signing transaction with cold wallet')
        res = self.cold_wallet.describe_transfer(unsigned_txset = unsigned_txset)
        assert len(res.desc) == 1
        desc = res.desc[0]
        assert desc.amount_in >= amount + fee
        assert desc.amount_out == desc.amount_in - fee
        assert desc.ring_size == 11
        assert desc.unlock_time == 0
        assert desc.payment_id == payment_id
        assert desc.change_amount == desc.amount_in - 1000000000000 - fee
        assert desc.change_address == '42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm'
        assert desc.fee == fee
        assert len(desc.recipients) == 1
        rec = desc.recipients[0]
        assert rec.address == '42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm'
        assert rec.amount == 1000000000000

        res = self.cold_wallet.sign_transfer(unsigned_txset)
        assert len(res.signed_txset) > 0
        signed_txset = res.signed_txset
        assert len(res.tx_hash_list) == 1
        txid = res.tx_hash_list[0]
        assert len(txid) == 64

        print('Submitting transaction with hot wallet')
        res = self.hot_wallet.submit_transfer(signed_txset)
        assert len(res.tx_hash_list) > 0
        assert res.tx_hash_list[0] == txid

        res = self.hot_wallet.get_transfers()
        assert len([x for x in (res['pending'] if 'pending' in res else []) if x.txid == txid]) == 1
        assert len([x for x in (res['out'] if 'out' in res else []) if x.txid == txid]) == 0

        daemon.generateblocks('42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm', 1)
        self.hot_wallet.refresh()

        res = self.hot_wallet.get_transfers()
        assert len([x for x in (res['pending'] if 'pending' in res else []) if x.txid == txid]) == 0
        assert len([x for x in (res['out'] if 'out' in res else []) if x.txid == txid]) == 1

        res = self.hot_wallet.get_tx_key(txid)
        assert len(res.tx_key) == 0 or res.tx_key == '01' + '0' * 62 # identity is used as placeholder
        res = self.cold_wallet.get_tx_key(txid)
        assert len(res.tx_key) == 64
class GetOutputDistributionTest():
    def run_test(self):
        self.reset()
        self.create()
        self.test_get_output_distribution()

    def reset(self):
        print('Resetting blockchain')
        daemon = Daemon()
        daemon.pop_blocks(1000)
        daemon.flush_txpool()

    def create(self):
        self.wallet = Wallet()
        # close the wallet if any, will throw if none is loaded
        try: self.wallet.close_wallet()
        except: pass
        res = self.wallet.restore_deterministic_wallet(seed = 'velvet lymph giddy number token physics poetry unquoted nibs useful sabotage limits benches lifestyle eden nitrogen anvil fewest avoid batch vials washing fences goat unquoted')

    def test_get_output_distribution(self):
        print("Test get_output_distribution")

        daemon = Daemon()

        res = daemon.get_output_distribution([0], 0, 0)
        assert len(res.distributions) == 1
        d = res.distributions[0]
        assert d.amount == 0
        assert d.base == 0
        assert d.binary == False
        assert len(d.distribution) == 1
        assert d.distribution[0] == 0

        res = daemon.generateblocks('42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm', 1)

        res = daemon.get_output_distribution([0], 0, 0)
        assert len(res.distributions) == 1
        d = res.distributions[0]
        assert d.amount == 0
        assert d.base == 0
        assert d.binary == False
        assert len(d.distribution) == 2
        assert d.distribution[0] == 0
        assert d.distribution[1] == 1

        res = daemon.pop_blocks(1)

        res = daemon.get_output_distribution([0], 0, 0)
        assert len(res.distributions) == 1
        d = res.distributions[0]
        assert d.amount == 0
        assert d.base == 0
        assert d.binary == False
        assert len(d.distribution) == 1
        assert d.distribution[0] == 0

        res = daemon.generateblocks('42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm', 3)

        res = daemon.get_output_distribution([0], 0, 0, cumulative = True)
        assert len(res.distributions) == 1
        d = res.distributions[0]
        assert d.amount == 0
        assert d.base == 0
        assert d.binary == False
        assert len(d.distribution) == 4
        assert d.distribution[0] == 0
        assert d.distribution[1] == 1
        assert d.distribution[2] == 2
        assert d.distribution[3] == 3

        # extend
        res = daemon.generateblocks('42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm', 80)

        res = daemon.get_output_distribution([0], 0, 0, cumulative = True)
        assert len(res.distributions) == 1
        d = res.distributions[0]
        assert d.amount == 0
        assert d.base == 0
        assert d.binary == False
        assert len(d.distribution) == 84
        for h in range(len(d.distribution)):
            assert d.distribution[h] == h

        # pop and replace, this will do through the "trim and extend" path
        res = daemon.pop_blocks(2)
        self.wallet.refresh()
        dst = {'address': '42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm', 'amount': 1000000000000}
        self.wallet.transfer([dst])
        res = daemon.generateblocks('42ey1afDFnn4886T7196doS9GPMzexD9gXpsZJDwVjeRVdFCSoHnv7KPbBeGpzJBzHRCAs9UxqeoyFQMYbqSWYTfJJQAWDm', 1)
        for step in range(3): # the second will be cached, the third will also be cached, but we get it in non-cumulative mode
            res = daemon.get_output_distribution([0], 0, 0, cumulative = step < 3)
            assert len(res.distributions) == 1
            d = res.distributions[0]
            assert d.amount == 0
            assert d.base == 0
            assert d.binary == False
            assert len(d.distribution) == 83
            for h in range(len(d.distribution)):
                assert d.distribution[h] == (h if step < 3 else 1) + (2 if h == len(d.distribution) - 1 else 0)

        # start at 0, end earlier
        res = daemon.get_output_distribution([0], 0, 40, cumulative = True)
        assert len(res.distributions) == 1
        d = res.distributions[0]
        assert d.amount == 0
        assert d.base == 0
        assert d.binary == False
        assert len(d.distribution) == 41
        for h in range(len(d.distribution)):
            assert d.distribution[h] == h

        # start after 0, end earlier
        res = daemon.get_output_distribution([0], 10, 20, cumulative = True)
        assert len(res.distributions) == 1
        d = res.distributions[0]
        assert d.amount == 0
        assert d.base == 9
        assert d.binary == False
        assert len(d.distribution) == 11
        for h in range(len(d.distribution)):
            assert d.distribution[h] == 10 + h

        # straddling up
        res = daemon.get_output_distribution([0], 15, 25, cumulative = True)
        assert len(res.distributions) == 1
        d = res.distributions[0]
        assert d.amount == 0
        assert d.base == 14
        assert d.binary == False
        assert len(d.distribution) == 11
        for h in range(len(d.distribution)):
            assert d.distribution[h] == 15 + h

        # straddling down
        res = daemon.get_output_distribution([0], 8, 18, cumulative = True)
        assert len(res.distributions) == 1
        d = res.distributions[0]
        assert d.amount == 0
        assert d.base == 7
        assert d.binary == False
        assert len(d.distribution) == 11
        for h in range(len(d.distribution)):
            assert d.distribution[h] == 8 + h

        # encompassing
        res = daemon.get_output_distribution([0], 5, 20, cumulative = True)
        assert len(res.distributions) == 1
        d = res.distributions[0]
        assert d.amount == 0
        assert d.base == 4
        assert d.binary == False
        assert len(d.distribution) == 16
        for h in range(len(d.distribution)):
            assert d.distribution[h] == 5 + h

        # single
        res = daemon.get_output_distribution([0], 2, 2, cumulative = True)
        assert len(res.distributions) == 1
        d = res.distributions[0]
        assert d.amount == 0
        assert d.base == 1
        assert d.binary == False
        assert len(d.distribution) == 1
        assert d.distribution[0] == 2

        # a non existent amount
        res = daemon.get_output_distribution([1], 0, 0)
        assert len(res.distributions) == 1
        d = res.distributions[0]
        assert d.amount == 1
        assert d.base == 0
        assert d.binary == False
        assert len(d.distribution) == 83
        for h in range(len(d.distribution)):
            assert d.distribution[h] == 0