def get_latest_block_height(driver: ContractDriver): h = driver.get(BLOCK_NUM_HEIGHT, mark=False) if h is None: return 0 return h
def test_masternode_delegate_single_loop_updates_block_num(self): ips = ['tcp://127.0.0.1:18001', 'tcp://127.0.0.1:18002'] dw = Wallet() mw = Wallet() self.authenticator.add_verifying_key(mw.verifying_key) self.authenticator.add_verifying_key(dw.verifying_key) self.authenticator.configure() mnd = ContractDriver(driver=InMemDriver()) mn = masternode.Masternode(socket_base=ips[0], ctx=self.ctx, wallet=mw, constitution={ 'masternodes': [mw.verifying_key], 'delegates': [dw.verifying_key] }, driver=mnd) sender = Wallet() mnd.set_var(contract='currency', variable='balances', arguments=[sender.verifying_key], value=1_000_000) dld = ContractDriver(driver=InMemDriver()) dld.set_var(contract='currency', variable='balances', arguments=[sender.verifying_key], value=1_000_000) dl = delegate.Delegate(socket_base=ips[1], ctx=self.ctx, wallet=dw, constitution={ 'masternodes': [mw.verifying_key], 'delegates': [dw.verifying_key] }, driver=dld) tx = transaction.build_transaction(wallet=sender, contract='currency', function='transfer', kwargs={ 'amount': 1338, 'to': 'jeff' }, stamps=5000, nonce=0, processor=mw.verifying_key) tx_decoded = decode(tx) mn.tx_batcher.queue.append(tx_decoded) peers = {mw.verifying_key: ips[0], dw.verifying_key: ips[1]} mn.network.peers = peers dl.network.peers = peers tasks = asyncio.gather( mn.router.serve(), dl.router.serve(), mn.loop(), dl.loop(), stop_server(mn.router, 1), stop_server(dl.router, 1), ) self.loop.run_until_complete(tasks) dh = storage.get_latest_block_height(dld) mh = storage.get_latest_block_height(mnd) self.assertEqual(dh, 1) self.assertEqual(mh, 1)
def get_latest_block_hash(driver: ContractDriver): latest_hash = driver.get(BLOCK_HASH_KEY, mark=False) if latest_hash is None: return '0' * 64 return latest_hash
class TestDelegate(TestCase): def setUp(self): self.ctx = zmq.asyncio.Context() self.loop = asyncio.new_event_loop() self.driver = ContractDriver(driver=InMemDriver()) self.client = ContractingClient(driver=self.driver) self.client.flush() asyncio.set_event_loop(self.loop) self.authenticator = authentication.SocketAuthenticator( client=self.client, ctx=self.ctx) def tearDown(self): self.client.flush() self.driver.flush() self.authenticator.authenticator.stop() self.ctx.destroy() self.loop.close() def test_execute_tx_returns_successful_output(self): test_contract = ''' v = Variable() @construct def seed(): v.set('hello') @export def set(var: str): v.set(var) @export def get(): return v.get() ''' self.client.submit(test_contract, name='testing') self.client.raw_driver.commit() self.client.raw_driver.clear_pending_state() stu = Wallet() tx = transaction.build_transaction(wallet=stu, contract='testing', function='set', kwargs={'var': 'jeff'}, stamps=100_000, processor='0' * 64, nonce=0) e = execution.SerialExecutor(executor=self.client.executor) result = e.execute_tx(decode(tx), stamp_cost=20_000) self.assertEqual(result['status'], 0) self.assertEqual(result['state'][0]['key'], 'testing.v') self.assertEqual(result['state'][0]['value'], 'jeff') self.assertEqual(result['stamps_used'], 1) def test_stamp_deduction_on_fail(self): test_contract = ''' @export def eat_stamps(): while True: pass ''' self.client.submit(test_contract, name='testing') self.client.raw_driver.commit() self.client.raw_driver.clear_pending_state() stu = Wallet() self.client.raw_driver.set(f'currency.balances:{stu.verifying_key}', 100000) tx = transaction.build_transaction(wallet=stu, contract='testing', function='eat_stamps', kwargs={}, stamps=10000, processor='0' * 64, nonce=0) e = execution.SerialExecutor(executor=self.client.executor) self.client.executor.metering = True result = e.execute_tx(decode(tx), stamp_cost=200) self.assertEqual(result['status'], 1) self.assertEqual(result['state'][0]['key'], f'currency.balances:{stu.verifying_key}') self.assertEqual(result['state'][0]['value'], Decimal('99950.0')) self.assertEqual(result['stamps_used'], 10000) def test_bad_tx_returns_properly(self): class BadTX: def __init__(self, tx, err): self.tx = tx self.err = err stu = Wallet() tx = transaction.build_transaction(wallet=stu, contract='testing', function='eat_stamps', kwargs={}, stamps=10000, processor='0' * 64, nonce=0) exe = execution.SerialExecutor(executor=self.client.executor) result = exe.execute_tx_batch( batch={'transactions': [BadTX(decode(tx), Exception)]}, stamp_cost=200, timestamp=int(time.time()), input_hash='A' * 32, driver=self.client.raw_driver) self.assertEqual(result[0]['status'], 1) self.assertEqual(result[0]['result'], safe_repr(str(Exception))) self.assertEqual(result[0]['stamps_used'], 0) def test_generate_environment_creates_datetime_wrapped_object(self): timestamp = int(time.time()) exe = execution.SerialExecutor(executor=self.client.executor) e = exe.generate_environment(self.client.raw_driver, timestamp, 'A' * 64) t = datetime.utcfromtimestamp(timestamp) #self.assertEqual(type(e['now']), Datetime) self.assertEqual(e['now'].year, t.year) self.assertEqual(e['now'].month, t.month) self.assertEqual(e['now'].day, t.day) self.assertEqual(e['now'].hour, t.hour) self.assertEqual(e['now'].minute, t.minute) self.assertEqual(e['now'].second, t.second) def test_generate_environment_creates_input_hash(self): timestamp = time.time() exe = execution.SerialExecutor(executor=self.client.executor) e = exe.generate_environment(self.client.raw_driver, timestamp, 'A' * 64) self.assertEqual(e['__input_hash'], 'A' * 64) def test_generate_environment_creates_block_hash(self): timestamp = time.time() exe = execution.SerialExecutor(executor=self.client.executor) e = exe.generate_environment(self.client.raw_driver, timestamp, 'A' * 64) self.assertEqual(e['block_hash'], storage.get_latest_block_hash(self.client.raw_driver)) def test_generate_environment_creates_block_num(self): timestamp = time.time() exe = execution.SerialExecutor(executor=self.client.executor) e = exe.generate_environment(self.client.raw_driver, timestamp, 'A' * 64) self.assertEqual( e['block_num'], storage.get_latest_block_height(self.client.raw_driver) + 1) def test_execute_tx_batch_returns_all_transactions(self): test_contract = ''' v = Variable() @construct def seed(): v.set('hello') @export def set(var: str): v.set(var) @export def get(): return v.get() ''' self.client.submit(test_contract, name='testing') self.client.raw_driver.commit() self.client.raw_driver.clear_pending_state() stu = Wallet() tx = transaction.build_transaction(wallet=stu, contract='testing', function='set', kwargs={'var': 'howdy'}, stamps=100_000, processor='0' * 64, nonce=0) tx = decode(tx) tx2 = transaction.build_transaction(wallet=stu, contract='testing', function='get', kwargs={}, stamps=100_000, processor='0' * 64, nonce=0) tx2 = decode(tx2) tx_batch = {'transactions': [tx, tx2]} e = execution.SerialExecutor(executor=self.client.executor) results = e.execute_tx_batch(driver=self.client.raw_driver, batch=tx_batch, timestamp=time.time(), input_hash='A' * 64, stamp_cost=20_000) td1, td2 = results self.assertEqual(td1['status'], 0) self.assertEqual(td1['state'][0]['key'], 'testing.v') self.assertEqual(td1['state'][0]['value'], 'howdy') self.assertEqual(td1['stamps_used'], 1) self.assertEqual(td2['status'], 0) self.assertEqual(len(td2['state']), 0) self.assertEqual(td2['stamps_used'], 1) def test_execute_tx_batch_returns_all_transactions_4_in_order(self): test_contract = ''' v = Variable() @construct def seed(): v.set('hello') @export def set(var: str): v.set(var) @export def get(): return v.get() ''' self.client.submit(test_contract, name='testing') self.client.raw_driver.commit() self.client.raw_driver.clear_pending_state() stu = Wallet() tx = transaction.build_transaction(wallet=stu, contract='testing', function='set', kwargs={'var': 'howdy'}, stamps=100_000, processor='0' * 64, nonce=0) tx = decode(tx) tx2 = transaction.build_transaction(wallet=stu, contract='testing', function='get', kwargs={}, stamps=100_000, processor='0' * 64, nonce=0) tx2 = decode(tx2) tx3 = transaction.build_transaction(wallet=stu, contract='testing', function='set', kwargs={'var': 'something'}, stamps=100_000, processor='0' * 64, nonce=0) tx3 = decode(tx3) tx4 = transaction.build_transaction(wallet=stu, contract='testing', function='set', kwargs={'var': 'something2'}, stamps=100_000, processor='0' * 64, nonce=0) tx4 = decode(tx4) tx_batch = {'transactions': [tx, tx2, tx3, tx4]} e = execution.SerialExecutor(executor=self.client.executor) results = e.execute_tx_batch(driver=self.client.raw_driver, batch=tx_batch, timestamp=time.time(), input_hash='A' * 64, stamp_cost=20_000) td1, td2, td3, td4 = results self.assertEqual(td1['status'], 0) self.assertEqual(td1['state'][0]['key'], 'testing.v') self.assertEqual(td1['state'][0]['value'], 'howdy') self.assertEqual(td1['stamps_used'], 1) self.assertEqual(td2['status'], 0) self.assertEqual(len(td2['state']), 0) self.assertEqual(td2['stamps_used'], 1) self.assertEqual(td3['status'], 0) self.assertEqual(td3['state'][0]['key'], 'testing.v') self.assertEqual(td3['state'][0]['value'], 'something') self.assertEqual(td3['stamps_used'], 1) self.assertEqual(td4['status'], 0) self.assertEqual(td4['state'][0]['key'], 'testing.v') self.assertEqual(td4['state'][0]['value'], 'something2') self.assertEqual(td4['stamps_used'], 1) def test_execute_work_multiple_transaction_batches_works(self): test_contract = ''' v = Variable() @construct def seed(): v.set('hello') @export def set(var: str): v.set(var) @export def get(): return v.get() ''' self.client.submit(test_contract, name='testing') self.client.raw_driver.commit() self.client.raw_driver.clear_pending_state() stu = Wallet() tx1_1 = transaction.build_transaction(wallet=stu, contract='testing', function='set', kwargs={'var': 'howdy'}, stamps=100_000, processor='0' * 64, nonce=0) tx1_1 = decode(tx1_1) tx1_2 = transaction.build_transaction(wallet=stu, contract='testing', function='get', kwargs={}, stamps=100_000, processor='0' * 64, nonce=0) tx1_2 = decode(tx1_2) tx_batch_1 = { 'transactions': [tx1_1, tx1_2], 'timestamp': time.time(), 'input_hash': 'C' * 64 } tx2_1 = transaction.build_transaction(wallet=stu, contract='testing', function='set', kwargs={'var': '123'}, stamps=100_000, processor='0' * 64, nonce=0) tx2_1 = decode(tx2_1) jeff = Wallet() tx2_2 = transaction.build_transaction(wallet=jeff, contract='testing', function='set', kwargs={'var': 'poo'}, stamps=100_000, processor='0' * 64, nonce=0) tx2_2 = decode(tx2_2) tx_batch_2 = { 'transactions': [tx2_1, tx2_2], 'timestamp': time.time(), 'input_hash': 'A' * 64 } work = [tx_batch_1, tx_batch_2] exe = execution.SerialExecutor(executor=self.client.executor) results = exe.execute_work(driver=self.client.raw_driver, work=work, previous_block_hash='B' * 64, wallet=Wallet(), stamp_cost=20_000) sb1, sb2 = results td1, td2 = sb1['transactions'] self.assertEqual(td1['status'], 0) self.assertEqual(td1['state'][0]['key'], 'testing.v') self.assertEqual(td1['state'][0]['value'], 'howdy') self.assertEqual(td1['stamps_used'], 1) self.assertEqual(td2['status'], 0) self.assertEqual(len(td2['state']), 0) self.assertEqual(td2['stamps_used'], 1) self.assertEqual(sb1['input_hash'], tx_batch_1['input_hash']) self.assertEqual(sb1['subblock'], 0) self.assertEqual(sb1['previous'], 'B' * 64) td1, td2 = sb2['transactions'] self.assertEqual(td1['status'], 0) self.assertEqual(td1['state'][0]['key'], 'testing.v') self.assertEqual(td1['state'][0]['value'], '123') self.assertEqual(td1['stamps_used'], 1) self.assertEqual(td2['status'], 0) self.assertEqual(td2['state'][0]['key'], 'testing.v') self.assertEqual(td2['state'][0]['value'], 'poo') self.assertEqual(td2['stamps_used'], 1) self.assertEqual(sb2['input_hash'], tx_batch_2['input_hash']) self.assertEqual(sb2['subblock'], 1) self.assertEqual(sb2['previous'], 'B' * 64) def test_no_txs_merklizes_and_signs_input_hash(self): tx_batch_1 = { 'transactions': [], 'timestamp': time.time(), 'input_hash': 'A' * 64 } work = [tx_batch_1] w = Wallet() exe = execution.SerialExecutor(executor=self.client.executor) results = exe.execute_work(driver=self.client.raw_driver, work=work, previous_block_hash='B' * 64, wallet=w, stamp_cost=20_000) self.assertTrue( verify(w.verifying_key, results[0]['input_hash'], results[0]['merkle_tree']['signature'])) h = hashlib.sha3_256() h.update(bytes.fromhex(results[0]['input_hash'])) self.assertEqual(h.hexdigest(), results[0]['merkle_tree']['leaves'][0]) def test_acquire_work_1_master_gathers_tx_batches(self): ips = ['tcp://127.0.0.1:18001', 'tcp://127.0.0.1:18002'] dw = Wallet() mw = Wallet() self.authenticator.add_verifying_key(mw.verifying_key) self.authenticator.add_verifying_key(dw.verifying_key) self.authenticator.configure() mn = masternode.Masternode(socket_base=ips[0], ctx=self.ctx, wallet=mw, constitution={ 'masternodes': [mw.verifying_key], 'delegates': [dw.verifying_key] }, driver=ContractDriver(driver=InMemDriver())) dl = delegate.Delegate(socket_base=ips[1], ctx=self.ctx, wallet=dw, constitution={ 'masternodes': [mw.verifying_key], 'delegates': [dw.verifying_key] }, driver=ContractDriver(driver=InMemDriver())) peers = {mw.verifying_key: ips[0], dw.verifying_key: ips[1]} mn.network.peers = peers dl.network.peers = peers tasks = asyncio.gather( mn.router.serve(), dl.router.serve(), mn.send_work(), dl.acquire_work(), stop_server(mn.router, 1), stop_server(dl.router, 1), ) _, _, _, w, _, _ = self.loop.run_until_complete(tasks) self.assertEqual(len(w), 1) self.assertEqual(w[0]['sender'], mw.verifying_key) def test_acquire_work_2_masters_gathers_tx_batches_pads_work_and_waits_if_missing( self): ips = ['tcp://127.0.0.1:18001', 'tcp://127.0.0.1:18002'] dw = Wallet() mw = Wallet() mw2 = Wallet() self.authenticator.add_verifying_key(mw.verifying_key) self.authenticator.add_verifying_key(dw.verifying_key) self.authenticator.configure() mn = masternode.Masternode(socket_base=ips[0], ctx=self.ctx, wallet=mw, constitution={ 'masternodes': [mw.verifying_key, mw2.verifying_key], 'delegates': [dw.verifying_key] }, driver=ContractDriver(driver=InMemDriver())) dl = delegate.Delegate(socket_base=ips[1], ctx=self.ctx, wallet=dw, constitution={ 'masternodes': [mw.verifying_key, mw2.verifying_key], 'delegates': [dw.verifying_key] }, driver=ContractDriver(driver=InMemDriver())) peers = { mw.verifying_key: ips[0], dw.verifying_key: ips[1], mw2.verifying_key: 'tpc://127.0.0.1:18003' } mn.network.peers = peers dl.network.peers = peers tasks = asyncio.gather( mn.router.serve(), dl.router.serve(), mn.send_work(), dl.acquire_work(), stop_server(mn.router, 1), stop_server(dl.router, 1), ) _, _, _, w, _, _ = self.loop.run_until_complete(tasks) self.assertEqual(len(w), 2) self.assertEqual(w[0]['sender'], mw.verifying_key) self.assertEqual(w[1]['sender'], mw2.verifying_key) self.assertEqual(w[1]['input_hash'], mw2.verifying_key) self.assertEqual(w[1]['signature'], '0' * 128) def test_process_new_work_processes_tx_batch(self): ips = ['tcp://127.0.0.1:18001', 'tcp://127.0.0.1:18002'] dw = Wallet() mw = Wallet() self.authenticator.add_verifying_key(mw.verifying_key) self.authenticator.add_verifying_key(dw.verifying_key) self.authenticator.configure() mn = masternode.Masternode(socket_base=ips[0], ctx=self.ctx, wallet=mw, constitution={ 'masternodes': [mw.verifying_key], 'delegates': [dw.verifying_key] }, driver=ContractDriver(driver=InMemDriver())) mnq = router.QueueProcessor() mn.router.add_service(base.CONTENDER_SERVICE, mnq) dl = delegate.Delegate(socket_base=ips[1], ctx=self.ctx, wallet=dw, constitution={ 'masternodes': [mw.verifying_key], 'delegates': [dw.verifying_key] }, driver=ContractDriver(driver=InMemDriver())) peers = {mw.verifying_key: ips[0], dw.verifying_key: ips[1]} mn.network.peers = peers dl.network.peers = peers tasks = asyncio.gather( mn.router.serve(), dl.router.serve(), mn.send_work(), dl.process_new_work(), stop_server(mn.router, 1), stop_server(dl.router, 1), ) self.loop.run_until_complete(tasks) sbc = mnq.q.pop(0) self.assertEqual(len(sbc), 1) self.assertEqual(sbc[0]['previous'], '0' * 64) self.assertEqual(sbc[0]['signer'], dw.verifying_key) def test_masternode_delegate_single_loop_works(self): ips = ['tcp://127.0.0.1:18001', 'tcp://127.0.0.1:18002'] dw = Wallet() mw = Wallet() self.authenticator.add_verifying_key(mw.verifying_key) self.authenticator.add_verifying_key(dw.verifying_key) self.authenticator.configure() mn = masternode.Masternode(socket_base=ips[0], ctx=self.ctx, wallet=mw, constitution={ 'masternodes': [mw.verifying_key], 'delegates': [dw.verifying_key] }, driver=ContractDriver(driver=InMemDriver())) dl = delegate.Delegate(socket_base=ips[1], ctx=self.ctx, wallet=dw, constitution={ 'masternodes': [mw.verifying_key], 'delegates': [dw.verifying_key] }, driver=ContractDriver(driver=InMemDriver())) peers = {mw.verifying_key: ips[0], dw.verifying_key: ips[1]} mn.network.peers = peers dl.network.peers = peers tasks = asyncio.gather( mn.router.serve(), dl.router.serve(), mn.loop(), dl.loop(), stop_server(mn.router, 1), stop_server(dl.router, 1), ) self.loop.run_until_complete(tasks) # sbc = mnq.q.pop(0) # # self.assertEqual(len(sbc), 1) # self.assertEqual(sbc[0]['previous'], '0' * 64) # self.assertEqual(sbc[0]['signer'], dw.verifying_key) # def test_masternode_delegate_single_loop_commits_state_changes(self): # ips = [ # 'tcp://127.0.0.1:18001', # 'tcp://127.0.0.1:18002' # ] # # dw = Wallet() # mw = Wallet() # # self.authenticator.add_verifying_key(mw.verifying_key) # self.authenticator.add_verifying_key(dw.verifying_key) # self.authenticator.configure() # # mnd = ContractDriver(driver=InMemDriver()) # mn = masternode.Masternode( # socket_base=ips[0], # ctx=self.ctx, # wallet=mw, # constitution={ # 'masternodes': [mw.verifying_key], # 'delegates': [dw.verifying_key] # }, # driver=mnd # ) # sender = Wallet() # mnd.set_var(contract='currency', variable='balances', arguments=[sender.verifying_key], value=1_000_000) # # dld = ContractDriver(driver=InMemDriver()) # dld.set_var(contract='currency', variable='balances', arguments=[sender.verifying_key], value=1_000_000) # dl = delegate.Delegate( # socket_base=ips[1], # ctx=self.ctx, # wallet=dw, # constitution={ # 'masternodes': [mw.verifying_key], # 'delegates': [dw.verifying_key] # }, # driver=dld # ) # # tx = transaction.build_transaction( # wallet=sender, # contract='currency', # function='transfer', # kwargs={ # 'amount': 1338, # 'to': 'jeff' # }, # stamps=5000, # nonce=0, # processor=mw.verifying_key # ) # # tx_decoded = decode(tx) # mn.tx_batcher.queue.append(tx_decoded) # # peers = { # mw.verifying_key: ips[0], # dw.verifying_key: ips[1] # } # # mn.network.peers = peers # dl.network.peers = peers # # tasks = asyncio.gather( # mn.router.serve(), # dl.router.serve(), # mn.loop(), # dl.loop(), # stop_server(mn.router, 1), # stop_server(dl.router, 1), # ) # # self.loop.run_until_complete(tasks) # # dbal = dld.get_var(contract='currency', variable='balances', arguments=['jeff']) # mbal = mnd.get_var(contract='currency', variable='balances', arguments=['jeff']) # # self.assertEqual(dbal, 1338) # self.assertEqual(mbal, 1338) def test_masternode_delegate_single_loop_updates_block_num(self): ips = ['tcp://127.0.0.1:18001', 'tcp://127.0.0.1:18002'] dw = Wallet() mw = Wallet() self.authenticator.add_verifying_key(mw.verifying_key) self.authenticator.add_verifying_key(dw.verifying_key) self.authenticator.configure() mnd = ContractDriver(driver=InMemDriver()) mn = masternode.Masternode(socket_base=ips[0], ctx=self.ctx, wallet=mw, constitution={ 'masternodes': [mw.verifying_key], 'delegates': [dw.verifying_key] }, driver=mnd) sender = Wallet() mnd.set_var(contract='currency', variable='balances', arguments=[sender.verifying_key], value=1_000_000) dld = ContractDriver(driver=InMemDriver()) dld.set_var(contract='currency', variable='balances', arguments=[sender.verifying_key], value=1_000_000) dl = delegate.Delegate(socket_base=ips[1], ctx=self.ctx, wallet=dw, constitution={ 'masternodes': [mw.verifying_key], 'delegates': [dw.verifying_key] }, driver=dld) tx = transaction.build_transaction(wallet=sender, contract='currency', function='transfer', kwargs={ 'amount': 1338, 'to': 'jeff' }, stamps=5000, nonce=0, processor=mw.verifying_key) tx_decoded = decode(tx) mn.tx_batcher.queue.append(tx_decoded) peers = {mw.verifying_key: ips[0], dw.verifying_key: ips[1]} mn.network.peers = peers dl.network.peers = peers tasks = asyncio.gather( mn.router.serve(), dl.router.serve(), mn.loop(), dl.loop(), stop_server(mn.router, 1), stop_server(dl.router, 1), ) self.loop.run_until_complete(tasks) dh = storage.get_latest_block_height(dld) mh = storage.get_latest_block_height(mnd) self.assertEqual(dh, 1) self.assertEqual(mh, 1)
def owner_of(m: ModuleType): _driver = rt.env.get('__Driver') or ContractDriver() owner = _driver.get_var(m.__name__, OWNER_KEY) return owner
from unittest import TestCase from lamden.nodes.masternode.webserver import WebServer from lamden.crypto.wallet import Wallet from contracting.client import ContractingClient from contracting.db.driver import ContractDriver, decode, encode from lamden.storage import BlockStorage from lamden.crypto.transaction import build_transaction from lamden import storage n = ContractDriver() class TestClassWebserver(TestCase): def setUp(self): self.w = Wallet() self.blocks = BlockStorage() self.driver = ContractDriver() self.ws = WebServer(wallet=self.w, contracting_client=ContractingClient(), blocks=self.blocks, driver=n) self.ws.client.flush() self.ws.blocks.drop_collections() def tearDown(self): self.ws.client.flush() self.ws.blocks.drop_collections()
class TestNode(TestCase): def setUp(self): self.ctx = zmq.asyncio.Context() self.loop = asyncio.new_event_loop() asyncio.set_event_loop(self.loop) self.blocks = storage.BlockStorage() self.driver = ContractDriver(driver=InMemDriver()) self.b = masternode.BlockService(blocks=self.blocks, driver=self.driver) self.blocks.drop_collections() self.driver.flush() self.authenticator = authentication.SocketAuthenticator( client=ContractingClient(), ctx=self.ctx) def tearDown(self): self.authenticator.authenticator.stop() self.ctx.destroy() self.loop.close() self.b.blocks.drop_collections() self.b.driver.flush() def test_catchup(self): driver = ContractDriver(driver=InMemDriver()) dl_vk = Wallet().verifying_key mn_bootnode = 'tcp://127.0.0.1:18001' mn_wallet = Wallet() mn_router = router.Router(socket_id=mn_bootnode, ctx=self.ctx, secure=True, wallet=mn_wallet) mn_router.add_service(base.BLOCK_SERVICE, self.b) nw = Wallet() node = base.Node(socket_base='tcp://127.0.0.1:18002', ctx=self.ctx, wallet=nw, constitution={ 'masternodes': [mn_wallet.verifying_key], 'delegates': [dl_vk] }, driver=driver) self.authenticator.add_verifying_key(mn_wallet.verifying_key) self.authenticator.add_verifying_key(nw.verifying_key) self.authenticator.add_verifying_key(dl_vk) self.authenticator.configure() blocks = generate_blocks(3) self.blocks.store_block(blocks[0]) self.blocks.store_block(blocks[1]) self.blocks.store_block(blocks[2]) storage.set_latest_block_height(3, self.driver) tasks = asyncio.gather( mn_router.serve(), node.catchup('tcp://127.0.0.1:18001', mn_wallet.verifying_key), stop_server(mn_router, 2)) self.loop.run_until_complete(tasks) self.assertEqual(storage.get_latest_block_height(node.driver), 3) def test_catchup_with_nbn_added(self): driver = ContractDriver(driver=InMemDriver()) mn_bootnode = 'tcp://127.0.0.1:18001' mn_wallet = Wallet() mn_router = router.Router(socket_id=mn_bootnode, ctx=self.ctx, secure=True, wallet=mn_wallet) mn_router.add_service(base.BLOCK_SERVICE, self.b) nw = Wallet() dlw = Wallet() node = base.Node(socket_base='tcp://127.0.0.1:18002', ctx=self.ctx, wallet=nw, constitution={ 'masternodes': [mn_wallet.verifying_key], 'delegates': [dlw.verifying_key] }, driver=driver) self.authenticator.add_verifying_key(mn_wallet.verifying_key) self.authenticator.add_verifying_key(nw.verifying_key) self.authenticator.add_verifying_key(dlw.verifying_key) self.authenticator.configure() blocks = generate_blocks(4) self.blocks.store_block(blocks[0]) self.blocks.store_block(blocks[1]) self.blocks.store_block(blocks[2]) storage.set_latest_block_height(3, self.driver) node.new_block_processor.q.append(blocks[3]) tasks = asyncio.gather( mn_router.serve(), node.catchup('tcp://127.0.0.1:18001', mn_wallet.verifying_key), stop_server(mn_router, 1)) self.loop.run_until_complete(tasks) self.assertEqual(storage.get_latest_block_height(node.driver), 4) def test_should_process_block_false_if_failed_block(self): block = { 'hash': 'f' * 64, 'number': 1, 'previous': '0' * 64, 'subblocks': [] } driver = ContractDriver(driver=InMemDriver()) node = base.Node(socket_base='tcp://127.0.0.1:18002', ctx=self.ctx, wallet=Wallet(), constitution={ 'masternodes': [Wallet().verifying_key], 'delegates': [Wallet().verifying_key] }, driver=driver) self.assertFalse(node.should_process(block)) def test_should_process_block_false_if_current_height_not_increment(self): block = { 'hash': 'a' * 64, 'number': 2, 'previous': '0' * 64, 'subblocks': [] } driver = ContractDriver(driver=InMemDriver()) node = base.Node(socket_base='tcp://127.0.0.1:18002', ctx=self.ctx, wallet=Wallet(), constitution={ 'masternodes': [Wallet().verifying_key], 'delegates': [Wallet().verifying_key] }, driver=driver) self.assertFalse(node.should_process(block)) def test_should_process_block_false_if_previous_if_not_current_hash(self): block = { 'hash': 'a' * 64, 'number': 1, 'previous': 'b' * 64, 'subblocks': [] } driver = ContractDriver(driver=InMemDriver()) node = base.Node(socket_base='tcp://127.0.0.1:18002', ctx=self.ctx, wallet=Wallet(), constitution={ 'masternodes': [Wallet().verifying_key], 'delegates': [Wallet().verifying_key] }, driver=driver) self.assertFalse(node.should_process(block)) def test_should_process_block_false_if_expected_block_not_equal_to_provided_block( self): block = { 'hash': 'a' * 64, 'number': 1, 'previous': '0' * 64, 'subblocks': [] } driver = ContractDriver(driver=InMemDriver()) node = base.Node(socket_base='tcp://127.0.0.1:18002', ctx=self.ctx, wallet=Wallet(), constitution={ 'masternodes': [Wallet().verifying_key], 'delegates': [Wallet().verifying_key] }, driver=driver) self.assertFalse(node.should_process(block)) def test_should_process_block_true_if_expected_block_equal_to_block(self): block = canonical.block_from_subblocks(subblocks=[], previous_hash='0' * 64, block_num=1) driver = ContractDriver(driver=InMemDriver()) node = base.Node(socket_base='tcp://127.0.0.1:18002', ctx=self.ctx, wallet=Wallet(), constitution={ 'masternodes': [Wallet().verifying_key], 'delegates': [Wallet().verifying_key] }, driver=driver) self.assertTrue(node.should_process(block)) def test_process_new_block_updates_state(self): block = canonical.block_from_subblocks(subblocks=[], previous_hash='0' * 64, block_num=1) driver = ContractDriver(driver=InMemDriver()) node = base.Node(socket_base='tcp://127.0.0.1:18002', ctx=self.ctx, wallet=Wallet(), constitution={ 'masternodes': [Wallet().verifying_key], 'delegates': [Wallet().verifying_key] }, driver=driver) node.process_new_block(block) self.assertEqual(storage.get_latest_block_height(node.driver), 1) self.assertEqual(storage.get_latest_block_hash(node.driver), block['hash']) def test_process_new_block_stores_block_if_should_store(self): block = canonical.block_from_subblocks(subblocks=[], previous_hash='0' * 64, block_num=1) driver = ContractDriver(driver=InMemDriver()) node = base.Node( socket_base='tcp://127.0.0.1:18002', ctx=self.ctx, wallet=Wallet(), constitution={ 'masternodes': [Wallet().verifying_key], 'delegates': [Wallet().verifying_key] }, driver=driver, store=True, blocks=self.blocks, ) node.process_new_block(block) b = node.blocks.get_block(1) self.assertEqual(b, block) def test_process_new_block_clears_cache(self): block = canonical.block_from_subblocks(subblocks=[], previous_hash='0' * 64, block_num=1) driver = ContractDriver(driver=InMemDriver()) node = base.Node( socket_base='tcp://127.0.0.1:18002', ctx=self.ctx, wallet=Wallet(), constitution={ 'masternodes': [Wallet().verifying_key], 'delegates': [Wallet().verifying_key] }, driver=driver, store=True, blocks=self.blocks, ) node.driver.cache['test'] = 123 node.process_new_block(block) self.assertIsNone(node.driver.cache.get('test')) def test_process_new_block_cleans_nbn(self): blocks = generate_blocks(2) driver = ContractDriver(driver=InMemDriver()) node = base.Node( socket_base='tcp://127.0.0.1:18002', ctx=self.ctx, wallet=Wallet(), constitution={ 'masternodes': [Wallet().verifying_key], 'delegates': [Wallet().verifying_key] }, driver=driver, store=True, blocks=self.blocks, ) # Add one old and one new block. # Function should only delete the old one node.new_block_processor.q.append(blocks[0]) node.new_block_processor.q.append(blocks[1]) node.process_new_block(blocks[0]) block = node.new_block_processor.q[0] self.assertEqual(block, blocks[1]) self.assertEqual(len(node.new_block_processor.q), 1) def test_start_boots_up_normally(self): # This MN will also provide 'catch up' services mn_bootnode = 'tcp://127.0.0.1:18001' mn_wallet = Wallet() mn_router = router.Router(socket_id=mn_bootnode, ctx=self.ctx, secure=True, wallet=mn_wallet) mn_network = network.Network(wallet=mn_wallet, ip_string=mn_bootnode, ctx=self.ctx, router=mn_router) blocks = generate_blocks(4) self.blocks.store_block(blocks[0]) self.blocks.store_block(blocks[1]) self.blocks.store_block(blocks[2]) storage.set_latest_block_height(3, self.driver) mn_router.add_service( base.BLOCK_SERVICE, masternode.BlockService(self.blocks, self.driver)) dl_bootnode = 'tcp://127.0.0.1:18002' dl_wallet = Wallet() dl_router = router.Router(socket_id=dl_bootnode, ctx=self.ctx, secure=True, wallet=dl_wallet) dl_network = network.Network(wallet=dl_wallet, ip_string=dl_bootnode, ctx=self.ctx, router=dl_router) constitution = { 'masternodes': [mn_wallet.verifying_key], 'delegates': [dl_wallet.verifying_key] } bootnodes = { mn_wallet.verifying_key: mn_bootnode, dl_wallet.verifying_key: dl_bootnode } node_w = Wallet() driver = ContractDriver(driver=InMemDriver()) node = base.Node(socket_base='tcp://127.0.0.1:18003', ctx=self.ctx, wallet=node_w, constitution=constitution, driver=driver, store=False, bootnodes=bootnodes) self.authenticator.add_verifying_key(mn_wallet.verifying_key) self.authenticator.add_verifying_key(dl_wallet.verifying_key) self.authenticator.add_verifying_key(node_w.verifying_key) self.authenticator.configure() vks = [mn_wallet.verifying_key, dl_wallet.verifying_key] tasks = asyncio.gather( mn_router.serve(), dl_router.serve(), mn_network.start(bootnodes, vks), dl_network.start(bootnodes, vks), stop_server(mn_router, 0.2), stop_server(dl_router, 0.2), ) self.loop.run_until_complete(tasks) tasks = asyncio.gather(mn_router.serve(), dl_router.serve(), node.start(), stop_server(mn_router, 1), stop_server(dl_router, 1), stop_server(node.router, 1)) self.loop.run_until_complete(tasks) self.assertEqual(storage.get_latest_block_height(node.driver), 3) self.assertEqual(storage.get_latest_block_hash(node.driver), blocks[2]['hash']) def test_new_block_service_appends_to_q_to_process_msg(self): nb = base.NewBlock(driver=ContractDriver()) msg = 'test' self.loop.run_until_complete(nb.process_message(msg)) self.assertEqual(nb.q, [msg]) def test_wait_for_next_holds_until_q_len_greater_than_0(self): nb = base.NewBlock(driver=ContractDriver()) msg = 'test' async def slow_add(): await asyncio.sleep(0.5) await nb.process_message(msg) self.loop.run_until_complete(slow_add()) self.assertEqual(nb.q, [msg]) def test_wait_for_next_pops_first_in_q(self): nb = base.NewBlock(driver=ContractDriver()) msg = 'test' nb.q.append('first') tasks = asyncio.gather(nb.process_message(msg), nb.wait_for_next_nbn()) _, r = self.loop.run_until_complete(tasks) self.assertEqual(r, 'first') def test_wait_for_next_clears_q(self): nb = base.NewBlock(driver=ContractDriver()) nb.q.append('first') nb.q.append('second') nb.q.append('third') tasks = asyncio.gather(nb.wait_for_next_nbn()) self.loop.run_until_complete(tasks) self.assertEqual(nb.q, []) def test_get_member_peers_returns_vk_ip_pairs(self): mn_wallet = Wallet() dl_wallet = Wallet() mn_bootnode = 'tcp://127.0.0.1:18001' dl_bootnode = 'tcp://127.0.0.1:18002' constitution = { 'masternodes': [mn_wallet.verifying_key], 'delegates': [dl_wallet.verifying_key] } bootnodes = { mn_wallet.verifying_key: mn_bootnode, dl_wallet.verifying_key: dl_bootnode } node_w = Wallet() driver = ContractDriver(driver=InMemDriver()) node = base.Node(socket_base='tcp://127.0.0.1:18003', ctx=self.ctx, wallet=node_w, constitution=constitution, driver=driver, store=False, bootnodes=bootnodes) # Assume caught up state node.network.peers = bootnodes m = node._get_member_peers('masternodes') d = node._get_member_peers('delegates') self.assertEqual(m, {mn_wallet.verifying_key: mn_bootnode}) self.assertEqual(d, {dl_wallet.verifying_key: dl_bootnode}) def test_get_delegate_peers_returns_deletates(self): mn_wallet = Wallet() dl_wallet = Wallet() mn_bootnode = 'tcp://127.0.0.1:18001' dl_bootnode = 'tcp://127.0.0.1:18002' constitution = { 'masternodes': [mn_wallet.verifying_key], 'delegates': [dl_wallet.verifying_key] } bootnodes = { mn_wallet.verifying_key: mn_bootnode, dl_wallet.verifying_key: dl_bootnode } node_w = Wallet() driver = ContractDriver(driver=InMemDriver()) node = base.Node(socket_base='tcp://127.0.0.1:18003', ctx=self.ctx, wallet=node_w, constitution=constitution, driver=driver, store=False, bootnodes=bootnodes) # Assume caught up state node.network.peers = bootnodes d = node.get_delegate_peers() self.assertEqual(d, {dl_wallet.verifying_key: dl_bootnode}) def test_get_masternode_peers_gets_masternodes(self): mn_wallet = Wallet() dl_wallet = Wallet() mn_bootnode = 'tcp://127.0.0.1:18001' dl_bootnode = 'tcp://127.0.0.1:18002' constitution = { 'masternodes': [mn_wallet.verifying_key], 'delegates': [dl_wallet.verifying_key] } bootnodes = { mn_wallet.verifying_key: mn_bootnode, dl_wallet.verifying_key: dl_bootnode } node_w = Wallet() driver = ContractDriver(driver=InMemDriver()) node = base.Node(socket_base='tcp://127.0.0.1:18003', ctx=self.ctx, wallet=node_w, constitution=constitution, driver=driver, store=False, bootnodes=bootnodes) # Assume caught up state node.network.peers = bootnodes m = node.get_masternode_peers() self.assertEqual(m, {mn_wallet.verifying_key: mn_bootnode})
def test_start_boots_up_normally(self): # This MN will also provide 'catch up' services mn_bootnode = 'tcp://127.0.0.1:18001' mn_wallet = Wallet() mn_router = router.Router(socket_id=mn_bootnode, ctx=self.ctx, secure=True, wallet=mn_wallet) mn_network = network.Network(wallet=mn_wallet, ip_string=mn_bootnode, ctx=self.ctx, router=mn_router) blocks = generate_blocks(4) self.blocks.store_block(blocks[0]) self.blocks.store_block(blocks[1]) self.blocks.store_block(blocks[2]) storage.set_latest_block_height(3, self.driver) mn_router.add_service( base.BLOCK_SERVICE, masternode.BlockService(self.blocks, self.driver)) dl_bootnode = 'tcp://127.0.0.1:18002' dl_wallet = Wallet() dl_router = router.Router(socket_id=dl_bootnode, ctx=self.ctx, secure=True, wallet=dl_wallet) dl_network = network.Network(wallet=dl_wallet, ip_string=dl_bootnode, ctx=self.ctx, router=dl_router) constitution = { 'masternodes': [mn_wallet.verifying_key], 'delegates': [dl_wallet.verifying_key] } bootnodes = { mn_wallet.verifying_key: mn_bootnode, dl_wallet.verifying_key: dl_bootnode } node_w = Wallet() driver = ContractDriver(driver=InMemDriver()) node = base.Node(socket_base='tcp://127.0.0.1:18003', ctx=self.ctx, wallet=node_w, constitution=constitution, driver=driver, store=False, bootnodes=bootnodes) self.authenticator.add_verifying_key(mn_wallet.verifying_key) self.authenticator.add_verifying_key(dl_wallet.verifying_key) self.authenticator.add_verifying_key(node_w.verifying_key) self.authenticator.configure() vks = [mn_wallet.verifying_key, dl_wallet.verifying_key] tasks = asyncio.gather( mn_router.serve(), dl_router.serve(), mn_network.start(bootnodes, vks), dl_network.start(bootnodes, vks), stop_server(mn_router, 0.2), stop_server(dl_router, 0.2), ) self.loop.run_until_complete(tasks) tasks = asyncio.gather(mn_router.serve(), dl_router.serve(), node.start(), stop_server(mn_router, 1), stop_server(dl_router, 1), stop_server(node.router, 1)) self.loop.run_until_complete(tasks) self.assertEqual(storage.get_latest_block_height(node.driver), 3) self.assertEqual(storage.get_latest_block_hash(node.driver), blocks[2]['hash'])