def test_topup( channel_manager: ChannelManager, confirmed_open_channel: Channel, wait_for_blocks ): blockchain = channel_manager.blockchain channel_manager.wait_sync() channel_id = (confirmed_open_channel.sender, confirmed_open_channel.block) confirmed_open_channel.topup(5) wait_for_blocks(1) gevent.sleep(blockchain.poll_interval) channel_rec = channel_manager.channels[channel_id] topup_txs = channel_rec.unconfirmed_topups assert len(topup_txs) == 1 and list(topup_txs.values())[0] == 5 wait_for_blocks(channel_manager.blockchain.n_confirmations) gevent.sleep(blockchain.poll_interval) channel_rec = channel_manager.channels[channel_id] topup_txs = channel_rec.unconfirmed_topups assert len(topup_txs) == 0 assert channel_rec.deposit == 15
def test_cooperative( channel_manager: ChannelManager, confirmed_open_channel: Channel, receiver_address: str, web3: Web3, token_contract: Contract, wait_for_blocks, sender_address: str ): blockchain = channel_manager.blockchain channel_id = (confirmed_open_channel.sender, confirmed_open_channel.block) sig1 = encode_hex(confirmed_open_channel.create_transfer(5)) channel_manager.register_payment(sender_address, confirmed_open_channel.block, 5, sig1) receiver_sig = channel_manager.sign_close(sender_address, confirmed_open_channel.block, 5) channel_rec = channel_manager.channels[channel_id] assert channel_rec.is_closed is True block_before = web3.eth.blockNumber confirmed_open_channel.close_cooperatively(receiver_sig) wait_for_blocks(blockchain.n_confirmations) gevent.sleep(blockchain.poll_interval) logs = get_logs(token_contract, 'Transfer', from_block=block_before - 1) assert len([l for l in logs if is_same_address(l['args']['_to'], receiver_address) and l['args']['_value'] == 5]) == 1 assert len([l for l in logs if is_same_address(l['args']['_to'], sender_address) and l['args']['_value'] == 5]) == 1 wait_for_blocks(blockchain.n_confirmations) gevent.sleep(blockchain.poll_interval) assert channel_id not in channel_manager.channels
def test_channel_settled_event( channel_manager: ChannelManager, confirmed_open_channel: Channel, wait_for_blocks, web3: Web3, use_tester: bool ): if not use_tester: pytest.skip('This test takes several hours on real blockchains.') blockchain = channel_manager.blockchain channel_manager.wait_sync() channel_id = (confirmed_open_channel.sender, confirmed_open_channel.block) confirmed_open_channel.close() wait_for_blocks(blockchain.n_confirmations) gevent.sleep(blockchain.poll_interval) channel_rec = channel_manager.channels[channel_id] wait_for_blocks(channel_rec.settle_timeout - web3.eth.blockNumber) gevent.sleep(blockchain.poll_interval) assert web3.eth.blockNumber >= channel_rec.settle_timeout assert channel_id in channel_manager.channels confirmed_open_channel.settle() wait_for_blocks(blockchain.n_confirmations) gevent.sleep(blockchain.poll_interval) assert channel_id not in channel_manager.channels
def test_balances( channel_manager: ChannelManager, confirmed_open_channel: Channel, wait_for_blocks, sender_address: str, use_tester: bool ): blockchain = channel_manager.blockchain initial_liquid_balance = channel_manager.get_liquid_balance() initial_locked_balance = channel_manager.get_locked_balance() if use_tester: assert initial_liquid_balance == 0 assert initial_locked_balance == 0 sig = encode_hex(confirmed_open_channel.create_transfer(5)) channel_manager.register_payment(sender_address, confirmed_open_channel.block, 5, sig) assert channel_manager.get_liquid_balance() == initial_liquid_balance assert channel_manager.get_locked_balance() == 5 receiver_sig = channel_manager.sign_close(sender_address, confirmed_open_channel.block, 5) confirmed_open_channel.close_cooperatively(receiver_sig) wait_for_blocks(blockchain.n_confirmations) gevent.sleep(blockchain.poll_interval) assert channel_manager.get_liquid_balance() == initial_liquid_balance + 5 assert channel_manager.get_locked_balance() == initial_locked_balance
def test_reorg( web3: Web3, channel_manager: ChannelManager, client: Client, receiver_address: str, wait_for_blocks, use_tester: bool ): if not use_tester: pytest.skip('Chain reorg tests only work in tester chain') wait_for_blocks(10) # create unconfirmed channel channel_manager.wait_sync() snapshot_id = web3.testing.snapshot() channel = client.open_channel(receiver_address, 10) wait_for_blocks(0) assert (channel.sender, channel.block) in channel_manager.unconfirmed_channels # remove unconfirmed channel opening with reorg web3.testing.revert(snapshot_id) snapshot_id = web3.testing.snapshot() wait_for_blocks(0) assert (channel.sender, channel.block) not in channel_manager.unconfirmed_channels web3.testing.mine(channel_manager.n_confirmations) assert (channel.sender, channel.block) not in channel_manager.channels # leave confirmed channel opening web3.testing.revert(snapshot_id) channel = client.open_channel(receiver_address, 10) wait_for_blocks(channel_manager.n_confirmations) assert (channel.sender, channel.block) in channel_manager.channels confirmed_snapshot_id = web3.testing.snapshot() wait_for_blocks(3) web3.testing.revert(confirmed_snapshot_id) assert (channel.sender, channel.block) in channel_manager.channels # remove unconfirmed topup channel = client.open_channel(receiver_address, 10) wait_for_blocks(channel_manager.n_confirmations) assert (channel.sender, channel.block) in channel_manager.channels topup_snapshot_id = web3.testing.snapshot() channel.topup(5) wait_for_blocks(0) channel_rec = channel_manager.channels[channel.sender, channel.block] assert len(channel_rec.unconfirmed_topups) == 1 web3.testing.revert(topup_snapshot_id) wait_for_blocks(0) assert (channel.sender, channel.block) in channel_manager.channels channel_rec = channel_manager.channels[channel.sender, channel.block] assert len(channel_rec.unconfirmed_topups) == 0
def test_cooperative_wrong_balance_proof( channel_manager: ChannelManager, confirmed_open_channel: Channel, sender_address: str ): channel_id = (confirmed_open_channel.sender, confirmed_open_channel.block) channel_rec = channel_manager.channels[channel_id] sig1 = encode_hex(confirmed_open_channel.create_transfer(5)) channel_manager.register_payment(sender_address, confirmed_open_channel.block, 5, sig1) sig2 = encode_hex(confirmed_open_channel.create_transfer(1)) with pytest.raises(InvalidBalanceProof): channel_manager.sign_close(sender_address, confirmed_open_channel.block, sig2) assert channel_rec.is_closed is False
def test_challenge( channel_manager: ChannelManager, confirmed_open_channel: Channel, receiver_address: str, sender_address: str, wait_for_blocks, web3: Web3, client: Client ): blockchain = channel_manager.blockchain channel_id = (confirmed_open_channel.sender, confirmed_open_channel.block) sig = encode_hex(confirmed_open_channel.create_transfer(5)) channel_manager.register_payment(sender_address, confirmed_open_channel.block, 5, sig) # hack channel to decrease balance confirmed_open_channel.update_balance(0) sig = confirmed_open_channel.create_transfer(3) block_before = web3.eth.blockNumber confirmed_open_channel.close() # should challenge and immediately settle for waited_blocks in count(): logs = get_logs(client.context.token, 'Transfer', from_block=block_before - 1) if logs: break wait_for_blocks(1) assert waited_blocks < 10 assert len([l for l in logs if is_same_address(l['args']['_to'], receiver_address) and l['args']['_value'] == 5]) == 1 assert len([l for l in logs if is_same_address(l['args']['_to'], sender_address) and l['args']['_value'] == 5]) == 1 wait_for_blocks(blockchain.n_confirmations) gevent.sleep(blockchain.poll_interval) assert channel_id not in channel_manager.channels # update channel state so that it will not be closed twice client.sync_channels() new_state = None for channel in client.channels: if all(channel.sender == confirmed_open_channel.sender, channel.receiver == confirmed_open_channel.receiver, channel.block == confirmed_open_channel.block): new_state = channel.state if new_state is None: confirmed_open_channel.state = confirmed_open_channel.State.closed else: confirmed_open_channel.state = new_state
def test_unconfirmed_topup( channel_manager: ChannelManager, client: Client, receiver_address: str, wait_for_blocks ): blockchain = channel_manager.blockchain channel_manager.wait_sync() channel = client.open_channel(receiver_address, 10) wait_for_blocks(1) gevent.sleep(blockchain.poll_interval) assert (channel.sender, channel.block) in channel_manager.unconfirmed_channels channel.topup(5) wait_for_blocks(channel_manager.blockchain.n_confirmations) gevent.sleep(blockchain.poll_interval) assert (channel.sender, channel.block) in channel_manager.channels channel_rec = channel_manager.channels[channel.sender, channel.block] assert channel_rec.deposit == 15
def test_close_confirmed_event( channel_manager: ChannelManager, confirmed_open_channel: Channel, wait_for_blocks ): blockchain = channel_manager.blockchain channel_manager.wait_sync() confirmed_open_channel.close() wait_for_blocks(blockchain.n_confirmations) gevent.sleep(blockchain.poll_interval) channel_id = (confirmed_open_channel.sender, confirmed_open_channel.block) channel_rec = channel_manager.channels[channel_id] assert channel_rec.is_closed is True settle_block = channel_manager.channel_manager_contract.call().getChannelInfo( channel_rec.sender, channel_rec.receiver, channel_rec.open_block_number )[2] assert channel_rec.settle_timeout == settle_block
def channel_manager( web3, receiver_privkey, channel_manager_contract, token_contract, use_tester, mine_sync_event, state_db_path, patched_contract, revert_chain ): manager = ChannelManager( web3, channel_manager_contract, token_contract, receiver_privkey, n_confirmations=5, state_filename=state_db_path ) start_channel_manager(manager, use_tester, mine_sync_event) yield manager manager.stop()
def test_settlement( channel_manager: ChannelManager, confirmed_open_channel: Channel, receiver_address: str, wait_for_blocks, web3: Web3, token_contract: Contract, sender_address: str, use_tester: bool ): if not use_tester: pytest.skip('This test takes several hours on real blockchains.') blockchain = channel_manager.blockchain channel_id = (confirmed_open_channel.sender, confirmed_open_channel.block) sig = encode_hex(confirmed_open_channel.create_transfer(2)) channel_manager.register_payment(sender_address, confirmed_open_channel.block, 2, sig) confirmed_open_channel.close() wait_for_blocks(blockchain.n_confirmations) gevent.sleep(blockchain.poll_interval) block_before = web3.eth.blockNumber channel_rec = channel_manager.channels[channel_id] wait_for_blocks(channel_rec.settle_timeout - block_before) confirmed_open_channel.settle() logs = get_logs(token_contract, 'Transfer', from_block=block_before - 1) assert len([l for l in logs if is_same_address(l['args']['_to'], receiver_address) and l['args']['_value'] == 2]) == 1 assert len([l for l in logs if is_same_address(l['args']['_to'], sender_address) and l['args']['_value'] == 8]) == 1 wait_for_blocks(blockchain.n_confirmations) gevent.sleep(blockchain.poll_interval) assert channel_id not in channel_manager.channels
def test_close_unconfirmed_event( channel_manager: ChannelManager, client: Client, receiver_address: str, wait_for_blocks ): channel_manager.wait_sync() blockchain = channel_manager.blockchain # if unconfirmed channel is closed it should simply be forgotten channel = client.open_channel(receiver_address, 10) wait_for_blocks(1) gevent.sleep(blockchain.poll_interval) assert (channel.sender, channel.block) in channel_manager.unconfirmed_channels assert (channel.sender, channel.block) not in channel_manager.channels channel.close() wait_for_blocks(channel_manager.blockchain.n_confirmations) # opening confirmed gevent.sleep(blockchain.poll_interval) assert (channel.sender, channel.block) not in channel_manager.unconfirmed_channels assert (channel.sender, channel.block) in channel_manager.channels wait_for_blocks(1) # closing confirmed gevent.sleep(blockchain.poll_interval) assert (channel.sender, channel.block) not in channel_manager.unconfirmed_channels assert (channel.sender, channel.block) in channel_manager.channels
def test_close_confirmed_event( channel_manager: ChannelManager, confirmed_open_channel: Channel, web3: Web3, wait_for_blocks ): blockchain = channel_manager.blockchain channel_manager.wait_sync() confirmed_open_channel.close() wait_for_blocks(blockchain.n_confirmations) gevent.sleep(blockchain.poll_interval) channel_id = (confirmed_open_channel.sender, confirmed_open_channel.block) channel_rec = channel_manager.channels[channel_id] assert channel_rec.is_closed is True settle_block = channel_manager.channel_manager_contract.call().getChannelInfo( channel_rec.sender, channel_rec.receiver, channel_rec.open_block_number )[2] assert channel_rec.settle_timeout == settle_block
def test_version( web3: Web3, channel_manager_contract: Contract, token_contract: Contract, make_account, private_keys: List[str] ): """Test if proxy refuses to run if it deployed contract version is different from the one it expects""" receiver1_privkey = make_account( RECEIVER_ETH_ALLOWANCE, RECEIVER_TOKEN_ALLOWANCE, private_keys[2] ) # this one should not raise cm = ChannelManager( web3, channel_manager_contract, token_contract, receiver1_privkey, state_filename=":memory:" ) cm.stop() # now we patch it channel_manager_contract = FakeChannelManagerContract(receiver1_privkey) # check of version string should fail here with pytest.raises(InvalidContractVersion): ChannelManager( web3, channel_manager_contract, token_contract, receiver1_privkey, state_filename=":memory:" )
def test_version(web3: Web3, channel_manager_contract: Contract, token_contract: Contract, make_account): """Test if proxy refuses to run if it deployed contract version is different from the one it expects""" receiver1_privkey = make_account(RECEIVER_ETH_ALLOWANCE, RECEIVER_TOKEN_ALLOWANCE) # this one should not raise cm = ChannelManager(web3, channel_manager_contract, token_contract, receiver1_privkey, state_filename=":memory:") cm.stop() # now we patch it channel_manager_contract = FakeChannelManagerContract(receiver1_privkey) # check of version string should fail here with pytest.raises(InvalidContractVersion): ChannelManager(web3, channel_manager_contract, token_contract, receiver1_privkey, state_filename=":memory:")
def make_channel_manager( private_key: str, channel_manager_address: str, state_filename: str, web3: Web3 ) -> ChannelManager: """ Args: private_key (str): receiver's private key channel_manager_address (str): channel manager contract to use state_filename (str): path to the channel manager state database web3 (Web3): web3 provider Returns: ChannelManager: intialized and synced channel manager """ channel_manager_address = to_checksum_address(channel_manager_address) channel_manager_contract = make_channel_manager_contract(web3, channel_manager_address) token_address = channel_manager_contract.call().token() token_abi = constants.CONTRACT_METADATA[constants.TOKEN_ABI_NAME]['abi'] token_contract = web3.eth.contract(abi=token_abi, address=token_address) try: return ChannelManager( web3, channel_manager_contract, token_contract, private_key, state_filename=state_filename ) except StateReceiverAddrMismatch as e: log.error( 'Receiver address does not match address stored in a saved state. ' 'Use a different file, or backup and remove %s. (%s)' % (state_filename, e) ) sys.exit(1) except StateContractAddrMismatch as e: log.error( 'Channel contract address mismatch. ' 'Saved state file is %s. Backup it, remove, then start proxy again (%s)' % (state_filename, e) ) sys.exit(1)
def make_channel_manager( receiver: str, private_key: str, channel_manager_address: str, state_filename: str, web3: Web3 ) -> ChannelManager: """ Args: private_key (str): receiver's private key channel_manager_address (str): channel manager contract to use state_filename (str): path to the channel manager state database web3 (Web3): web3 provider Returns: ChannelManager: intialized and synced channel manager """ channel_manager_address = Web3.toChecksumAddress(channel_manager_address) channel_manager_contract = make_channel_manager_contract(web3, channel_manager_address) receiver_address = Web3.toChecksumAddress(receiver) try: return ChannelManager( web3, channel_manager_contract, receiver, private_key, state_filename=state_filename ) except StateReceiverAddrMismatch as e: log.error( 'Receiver address does not match address stored in a saved state. ' 'Use a different file, or backup and remove %s. (%s)' % (state_filename, e) ) sys.exit(1) except StateContractAddrMismatch as e: log.error( 'Channel contract address mismatch. ' 'Saved state file is %s. Backup it, remove, then start proxy again (%s)' % (state_filename, e) ) sys.exit(1)
def channel_manager(web3, receiver_privkey, make_channel_manager_proxy, token_contract, use_tester, mine_sync_event, state_db_path): if use_tester: snapshot_id = web3.testing.snapshot() contract_proxy = make_channel_manager_proxy(receiver_privkey) manager = ChannelManager(web3, contract_proxy, token_contract, receiver_privkey, n_confirmations=5, state_filename=state_db_path) start_channel_manager(manager, use_tester, mine_sync_event) yield manager manager.stop() if use_tester: web3.testing.revert(snapshot_id) manager.stop()
def make_channel_manager(private_key: str, state_filename: str, web3): contracts_abi_path = os.path.join(os.path.dirname(__file__), 'data/contracts.json') abi = json.load(open(contracts_abi_path))['ERC223Token']['abi'] token_contract = web3.eth.contract(abi=abi, address=config.TOKEN_ADDRESS) try: return ChannelManager( web3, make_contract_proxy(web3, private_key, config.CHANNEL_MANAGER_ADDRESS), token_contract, private_key, state_filename=state_filename ) except StateReceiverAddrMismatch as e: log.error('Receiver address does not match address stored in a saved state. ' 'Use a different file, or backup and remove %s. (%s)' % (state_filename, e)) sys.exit(1) except StateContractAddrMismatch as e: log.error('channel contract address mismatch. ' 'Saved state file is %s. Backup it, remove, then' 'start proxy again (%s)' % (state_filename, e)) sys.exit(1)
def test_different_receivers(web3, make_account, make_channel_manager_proxy, token_contract, mine_sync_event, client, sender_address, wait_for_blocks, use_tester, state_db_path): receiver1_privkey = make_account(RECEIVER_ETH_ALLOWANCE, RECEIVER_TOKEN_ALLOWANCE) receiver2_privkey = make_account(RECEIVER_ETH_ALLOWANCE, RECEIVER_TOKEN_ALLOWANCE) receiver1_address = privkey_to_addr(receiver1_privkey) channel_manager1 = ChannelManager( web3, make_channel_manager_proxy(receiver1_privkey), token_contract, receiver1_privkey, n_confirmations=5, state_filename=state_db_path) start_channel_manager(channel_manager1, use_tester, mine_sync_event) channel_manager2 = ChannelManager( web3, make_channel_manager_proxy(receiver2_privkey), token_contract, receiver2_privkey, n_confirmations=5, state_filename=state_db_path) start_channel_manager(channel_manager2, use_tester, mine_sync_event) channel_manager1.wait_sync() channel_manager2.wait_sync() blockchain = channel_manager1.blockchain assert channel_manager2.blockchain.n_confirmations == blockchain.n_confirmations assert channel_manager2.blockchain.poll_interval == blockchain.poll_interval # unconfirmed open channel = client.open_channel(receiver1_address, 10) wait_for_blocks(1) gevent.sleep(blockchain.poll_interval) assert (sender_address, channel.block) in channel_manager1.unconfirmed_channels assert (sender_address, channel.block) not in channel_manager2.unconfirmed_channels # confirmed open wait_for_blocks(blockchain.n_confirmations) gevent.sleep(blockchain.poll_interval) assert (sender_address, channel.block) in channel_manager1.channels assert (sender_address, channel.block) not in channel_manager2.channels # unconfirmed topup channel.topup(5) wait_for_blocks(1) gevent.sleep(blockchain.poll_interval) channel_rec = channel_manager1.channels[sender_address, channel.block] assert len(channel_rec.unconfirmed_topups) == 1 assert channel_rec.deposit == 10 # confirmed topup wait_for_blocks(blockchain.n_confirmations) gevent.sleep(blockchain.poll_interval) channel_rec = channel_manager1.channels[sender_address, channel.block] assert len(channel_rec.unconfirmed_topups) == 0 assert channel_rec.deposit == 15 # closing channel.close() wait_for_blocks(blockchain.n_confirmations) gevent.sleep(blockchain.poll_interval) channel_rec = channel_manager1.channels[sender_address, channel.block] assert channel_rec.is_closed is True # settlement block_before = web3.eth.blockNumber wait_for_blocks(channel_rec.settle_timeout - block_before) channel.settle() wait_for_blocks(blockchain.n_confirmations) gevent.sleep(blockchain.poll_interval) assert (sender_address, channel.block) not in channel_manager1.channels channel_manager1.stop() channel_manager2.stop()
def test_channel_opening(client, web3, make_account, make_channel_manager_proxy, token_contract, mine_sync_event, wait_for_blocks, use_tester, state_db_path): receiver1_privkey = make_account(RECEIVER_ETH_ALLOWANCE, RECEIVER_TOKEN_ALLOWANCE) receiver2_privkey = make_account(RECEIVER_ETH_ALLOWANCE, RECEIVER_TOKEN_ALLOWANCE) receiver_address = privkey_to_addr(receiver1_privkey) # make sure channel_manager1 is terminated properly, otherwise Blockchain will be running # in the background, ruining other tests' results channel_manager1 = ChannelManager( web3, make_channel_manager_proxy(receiver1_privkey), token_contract, receiver1_privkey, n_confirmations=5, state_filename=state_db_path) start_channel_manager(channel_manager1, use_tester, mine_sync_event) channel_manager2 = ChannelManager( web3, make_channel_manager_proxy(receiver2_privkey), token_contract, receiver2_privkey, n_confirmations=5, state_filename=state_db_path) start_channel_manager(channel_manager2, use_tester, mine_sync_event) channel_manager1.wait_sync() channel_manager2.wait_sync() blockchain = channel_manager1.blockchain channel = client.open_channel(receiver_address, 10) # should be in unconfirmed channels wait_for_blocks(1) gevent.sleep(blockchain.poll_interval) assert (channel.sender, channel.block) not in channel_manager1.channels assert (channel.sender, channel.block) in channel_manager1.unconfirmed_channels channel_rec = channel_manager1.unconfirmed_channels[channel.sender, channel.block] assert is_same_address(channel_rec.receiver, receiver_address) assert is_same_address(channel_rec.sender, channel.sender) assert channel_rec.mtime == channel_rec.ctime # should be confirmed after n blocks wait_for_blocks(blockchain.n_confirmations) gevent.sleep(blockchain.poll_interval) assert (channel.sender, channel.block) in channel_manager1.channels channel_rec = channel_manager1.channels[channel.sender, channel.block] assert is_same_address(channel_rec.receiver, receiver_address) assert is_same_address(channel_rec.sender, channel.sender) assert channel_rec.balance == 0 assert channel_rec.last_signature is None assert channel_rec.is_closed is False assert channel_rec.settle_timeout == -1 # should not appear in other channel manager assert (channel.sender, channel.block) not in channel_manager2.channels assert (channel.sender, channel.block) not in channel_manager2.unconfirmed_channels channel_manager1.stop() channel_manager2.stop()
def stop_patched(self: ChannelManager): mine_sync_event.set() ChannelManager.stop(self)
def stop_patched(self: ChannelManager): mine_sync_event.set() ChannelManager.stop(self) self.stop = types.MethodType(ChannelManager.stop, self)
def test_payment(channel_manager: ChannelManager, confirmed_open_channel, receiver_address: str, receiver_privkey: str, sender_privkey: str, sender_address: str, block_num): #channel_manager.wait_sync() #confirmed_open_channel.sender = "0x09226F56C5699E2d87700179507cf25FA2F79F6b" #confirmed_open_channel.block = 2000508 #channel_id = (confirmed_open_channel.sender, confirmed_open_channel.block) channel_id = ('0xA7Ac54048B81041dbD527B603175C17473CE2d95', block_num) print("channels: ", channel_manager.channels) channel_rec = channel_manager.channels[channel_id] print("last_sig: ", channel_rec.last_signature) print("old_sig: ", channel_rec.old_signature) print("balance: ", channel_rec.balance) print("old_balance: ", channel_rec.old_balance) print("sender_address: ", sender_address) print("receiver_address: ", receiver_address) print("contract_address: ", channel_manager.channel_manager_contract.address) #assert channel_rec.last_signature is None #assert channel_rec.balance == 0 # valid transfer #sig1 = encode_hex(confirmed_open_channel.create_transfer(2)) sig1 = encode_hex( sign_balance_proof( sender_privkey, # should be sender's privkey #'0xA7Ac54048B81041dbD527B603175C17473CE2d95', '0x09226F56C5699E2d87700179507cf25FA2F79F6b', block_num, #channel_rec.receiver, #channel_rec.open_block_number, coins(2), channel_manager.channel_manager_contract.address)) sig2 = encode_hex( sign_balance_proof( sender_privkey, # should be sender's privkey '0x09226F56C5699E2d87700179507cf25FA2F79F6b', block_num, coins(5), channel_manager.channel_manager_contract.address)) channel_manager.register_payment(sender_address, block_num, coins(2), sig1) channel_manager.register_payment(sender_address, block_num, coins(5), sig2) channel_manager.unregister_payment(sender_address, block_num) #channel_manager.register_payment(receiver_address, channel_rec.open_block_number, 2, sig1) channel_rec = channel_manager.channels[channel_id] print("last_sig2: ", channel_rec.last_signature) #assert channel_rec.balance == 2 #assert channel_rec.last_signature == sig1 return # transfer signed with wrong private key invalid_sig = encode_hex( sign_balance_proof( receiver_privkey, # should be sender's privkey channel_rec.receiver, channel_rec.open_block_number, 4, channel_manager.channel_manager_contract.address)) with pytest.raises(InvalidBalanceProof): channel_manager.register_payment(sender_address, channel_rec.open_block_number, 4, invalid_sig) channel_rec = channel_manager.channels[channel_id] assert channel_rec.balance == 2 assert channel_rec.last_signature == sig1 # transfer to different receiver invalid_sig = encode_hex( sign_balance_proof( sender_privkey, sender_address, # should be receiver's address channel_rec.open_block_number, 4, channel_manager.channel_manager_contract.address)) with pytest.raises(InvalidBalanceProof): channel_manager.register_payment(sender_address, channel_rec.open_block_number, 4, invalid_sig) channel_rec = channel_manager.channels[channel_id] assert channel_rec.balance == 2 assert channel_rec.last_signature == sig1 # transfer negative amount invalid_sig = encode_hex( sign_balance_proof( sender_privkey, receiver_address, channel_rec.open_block_number, 1, # should be greater than 2 channel_manager.channel_manager_contract.address)) with pytest.raises(InvalidBalanceAmount): channel_manager.register_payment(sender_address, channel_rec.open_block_number, 1, invalid_sig) channel_rec = channel_manager.channels[channel_id] assert channel_rec.balance == 2 assert channel_rec.last_signature == sig1 # parameters should match balance proof sig2 = encode_hex(confirmed_open_channel.create_transfer(2)) with pytest.raises(NoOpenChannel): channel_manager.register_payment(receiver_address, channel_rec.open_block_number, 4, sig2) with pytest.raises(NoOpenChannel): channel_manager.register_payment(sender_address, channel_rec.open_block_number + 1, 4, sig2) with pytest.raises(InvalidBalanceProof): channel_manager.register_payment(sender_address, channel_rec.open_block_number, 5, sig2) channel_rec = channel_manager.channels[channel_id] assert channel_rec.balance == 2 assert channel_rec.last_signature == sig1 channel_manager.register_payment(sender_address, channel_rec.open_block_number, 4, sig2) channel_rec = channel_manager.channels[channel_id] assert channel_rec.balance == 4 assert channel_rec.last_signature == sig2 # should transfer up to deposit sig3 = encode_hex(confirmed_open_channel.create_transfer(6)) channel_manager.register_payment(sender_address, channel_rec.open_block_number, 10, sig3) channel_rec = channel_manager.channels[channel_id] assert channel_rec.balance == 10 assert channel_rec.last_signature == sig3 # transfer too much invalid_sig = encode_hex( sign_balance_proof( sender_privkey, receiver_address, channel_rec.open_block_number, 12, # should not be greater than 10 channel_manager.channel_manager_contract.address)) with pytest.raises(InvalidBalanceProof): channel_manager.register_payment(sender_address, channel_rec.open_block_number, 12, invalid_sig) assert channel_rec.balance == 10 assert channel_rec.last_signature == sig3
def test_different_receivers( web3: Web3, make_account, private_keys: List[str], channel_manager_contract: Contract, token_contract: Contract, mine_sync_event, client: Client, sender_address: str, wait_for_blocks, use_tester: bool, state_db_path: str ): if not use_tester: pytest.skip('This test takes several hours on real blockchains.') receiver1_privkey = make_account( RECEIVER_ETH_ALLOWANCE, RECEIVER_TOKEN_ALLOWANCE, private_keys[2] ) receiver2_privkey = make_account( RECEIVER_ETH_ALLOWANCE, RECEIVER_TOKEN_ALLOWANCE, private_keys[3] ) receiver1_address = privkey_to_addr(receiver1_privkey) channel_manager1 = ChannelManager( web3, channel_manager_contract, token_contract, receiver1_privkey, n_confirmations=5, state_filename=state_db_path ) start_channel_manager(channel_manager1, use_tester, mine_sync_event) channel_manager2 = ChannelManager( web3, channel_manager_contract, token_contract, receiver2_privkey, n_confirmations=5, state_filename=state_db_path ) start_channel_manager(channel_manager2, use_tester, mine_sync_event) channel_manager1.wait_sync() channel_manager2.wait_sync() blockchain = channel_manager1.blockchain assert channel_manager2.blockchain.n_confirmations == blockchain.n_confirmations assert channel_manager2.blockchain.poll_interval == blockchain.poll_interval # unconfirmed open channel = client.open_channel(receiver1_address, 10) wait_for_blocks(1) gevent.sleep(blockchain.poll_interval) assert (sender_address, channel.block) in channel_manager1.unconfirmed_channels assert (sender_address, channel.block) not in channel_manager2.unconfirmed_channels # confirmed open wait_for_blocks(blockchain.n_confirmations) gevent.sleep(blockchain.poll_interval) assert (sender_address, channel.block) in channel_manager1.channels assert (sender_address, channel.block) not in channel_manager2.channels # unconfirmed topup channel.topup(5) wait_for_blocks(1) gevent.sleep(blockchain.poll_interval) channel_rec = channel_manager1.channels[sender_address, channel.block] assert len(channel_rec.unconfirmed_topups) == 1 assert channel_rec.deposit == 10 # confirmed topup wait_for_blocks(blockchain.n_confirmations) gevent.sleep(blockchain.poll_interval) channel_rec = channel_manager1.channels[sender_address, channel.block] assert len(channel_rec.unconfirmed_topups) == 0 assert channel_rec.deposit == 15 # closing channel.close() wait_for_blocks(blockchain.n_confirmations) gevent.sleep(blockchain.poll_interval) channel_rec = channel_manager1.channels[sender_address, channel.block] assert channel_rec.is_closed is True # settlement block_before = web3.eth.blockNumber wait_for_blocks(channel_rec.settle_timeout - block_before) channel.settle() wait_for_blocks(blockchain.n_confirmations) gevent.sleep(blockchain.poll_interval) assert (sender_address, channel.block) not in channel_manager1.channels channel_manager1.stop() channel_manager2.stop()
def test_payment( channel_manager: ChannelManager, confirmed_open_channel, receiver_address: str, receiver_privkey: str, sender_privkey: str, sender_address: str ): channel_manager.wait_sync() channel_id = (confirmed_open_channel.sender, confirmed_open_channel.block) channel_rec = channel_manager.channels[channel_id] assert channel_rec.last_signature is None assert channel_rec.balance == 0 # valid transfer sig1 = encode_hex(confirmed_open_channel.create_transfer(2)) channel_manager.register_payment(sender_address, channel_rec.open_block_number, 2, sig1) channel_rec = channel_manager.channels[channel_id] assert channel_rec.balance == 2 assert channel_rec.last_signature == sig1 # transfer signed with wrong private key invalid_sig = encode_hex(sign_balance_proof( receiver_privkey, # should be sender's privkey channel_rec.receiver, channel_rec.open_block_number, 4, channel_manager.channel_manager_contract.address )) with pytest.raises(InvalidBalanceProof): channel_manager.register_payment(sender_address, channel_rec.open_block_number, 4, invalid_sig) channel_rec = channel_manager.channels[channel_id] assert channel_rec.balance == 2 assert channel_rec.last_signature == sig1 # transfer to different receiver invalid_sig = encode_hex(sign_balance_proof( sender_privkey, sender_address, # should be receiver's address channel_rec.open_block_number, 4, channel_manager.channel_manager_contract.address )) with pytest.raises(InvalidBalanceProof): channel_manager.register_payment(sender_address, channel_rec.open_block_number, 4, invalid_sig) channel_rec = channel_manager.channels[channel_id] assert channel_rec.balance == 2 assert channel_rec.last_signature == sig1 # transfer negative amount invalid_sig = encode_hex(sign_balance_proof( sender_privkey, receiver_address, channel_rec.open_block_number, 1, # should be greater than 2 channel_manager.channel_manager_contract.address )) with pytest.raises(InvalidBalanceAmount): channel_manager.register_payment(sender_address, channel_rec.open_block_number, 1, invalid_sig) channel_rec = channel_manager.channels[channel_id] assert channel_rec.balance == 2 assert channel_rec.last_signature == sig1 # parameters should match balance proof sig2 = encode_hex(confirmed_open_channel.create_transfer(2)) with pytest.raises(NoOpenChannel): channel_manager.register_payment(receiver_address, channel_rec.open_block_number, 4, sig2) with pytest.raises(NoOpenChannel): channel_manager.register_payment(sender_address, channel_rec.open_block_number + 1, 4, sig2) with pytest.raises(InvalidBalanceProof): channel_manager.register_payment(sender_address, channel_rec.open_block_number, 5, sig2) channel_rec = channel_manager.channels[channel_id] assert channel_rec.balance == 2 assert channel_rec.last_signature == sig1 channel_manager.register_payment(sender_address, channel_rec.open_block_number, 4, sig2) channel_rec = channel_manager.channels[channel_id] assert channel_rec.balance == 4 assert channel_rec.last_signature == sig2 # should transfer up to deposit sig3 = encode_hex(confirmed_open_channel.create_transfer(6)) channel_manager.register_payment(sender_address, channel_rec.open_block_number, 10, sig3) channel_rec = channel_manager.channels[channel_id] assert channel_rec.balance == 10 assert channel_rec.last_signature == sig3 # transfer too much invalid_sig = encode_hex(sign_balance_proof( sender_privkey, receiver_address, channel_rec.open_block_number, 12, # should not be greater than 10 channel_manager.channel_manager_contract.address )) with pytest.raises(InvalidBalanceProof): channel_manager.register_payment(sender_address, channel_rec.open_block_number, 12, invalid_sig) assert channel_rec.balance == 10 assert channel_rec.last_signature == sig3
def test_channel_opening( client: Client, web3: Web3, make_account, private_keys: List[str], channel_manager_contract, token_contract, mine_sync_event, wait_for_blocks, use_tester, state_db_path ): receiver1_privkey = make_account( RECEIVER_ETH_ALLOWANCE, RECEIVER_TOKEN_ALLOWANCE, private_keys[2] ) receiver2_privkey = make_account( RECEIVER_ETH_ALLOWANCE, RECEIVER_TOKEN_ALLOWANCE, private_keys[3] ) receiver_address = privkey_to_addr(receiver1_privkey) # make sure channel_manager1 is terminated properly, otherwise Blockchain will be running # in the background, ruining other tests' results channel_manager1 = ChannelManager( web3, channel_manager_contract, token_contract, receiver1_privkey, n_confirmations=5, state_filename=state_db_path ) start_channel_manager(channel_manager1, use_tester, mine_sync_event) channel_manager2 = ChannelManager( web3, channel_manager_contract, token_contract, receiver2_privkey, n_confirmations=5, state_filename=state_db_path ) start_channel_manager(channel_manager2, use_tester, mine_sync_event) channel_manager1.wait_sync() channel_manager2.wait_sync() blockchain = channel_manager1.blockchain channel = client.open_channel(receiver_address, 10) # should be in unconfirmed channels wait_for_blocks(1) gevent.sleep(blockchain.poll_interval) assert (channel.sender, channel.block) not in channel_manager1.channels assert (channel.sender, channel.block) in channel_manager1.unconfirmed_channels channel_rec = channel_manager1.unconfirmed_channels[channel.sender, channel.block] assert is_same_address(channel_rec.receiver, receiver_address) assert is_same_address(channel_rec.sender, channel.sender) assert channel_rec.mtime == channel_rec.ctime # should be confirmed after n blocks wait_for_blocks(blockchain.n_confirmations) gevent.sleep(blockchain.poll_interval) assert (channel.sender, channel.block) in channel_manager1.channels channel_rec = channel_manager1.channels[channel.sender, channel.block] assert is_same_address(channel_rec.receiver, receiver_address) assert is_same_address(channel_rec.sender, channel.sender) assert channel_rec.balance == 0 assert channel_rec.last_signature is None assert channel_rec.is_closed is False assert channel_rec.settle_timeout == -1 # should not appear in other channel manager assert (channel.sender, channel.block) not in channel_manager2.channels assert (channel.sender, channel.block) not in channel_manager2.unconfirmed_channels channel_manager1.stop() channel_manager2.stop()