def test_handle_block_closed_channel(): channel_state = factories.create( factories.NettingChannelStateProperties( close_transaction=TransactionExecutionStatus( finished_block_number=50, result=TransactionExecutionStatus.SUCCESS), settle_timeout=50, )) pseudo_random_generator = random.Random() block = Block(block_number=90, gas_limit=100000, block_hash=factories.make_block_hash()) before_settle = handle_block( channel_state=channel_state, state_change=block, block_number=block.block_number, pseudo_random_generator=pseudo_random_generator, ) assert get_status(before_settle.new_state) == ChannelState.STATE_CLOSED assert not before_settle.events block = Block(block_number=102, gas_limit=100000, block_hash=factories.make_block_hash()) after_settle = handle_block( channel_state=before_settle.new_state, state_change=block, block_number=block.block_number, pseudo_random_generator=pseudo_random_generator, ) assert get_status(after_settle.new_state) == ChannelState.STATE_SETTLING assert after_settle.events
def test_handle_onchain_secretreveal(): """ The target node must update the lock state when the secret is registered in the blockchain. """ setup = make_target_state(block_number=1, expiration=1 + factories.UNIT_REVEAL_TIMEOUT) assert factories.UNIT_SECRETHASH in setup.channel.partner_state.secrethashes_to_lockedlocks offchain_secret_reveal_iteration = target.state_transition( target_state=setup.new_state, state_change=ReceiveSecretReveal(UNIT_SECRET, setup.initiator), channel_state=setup.channel, pseudo_random_generator=setup.pseudo_random_generator, block_number=setup.block_number, ) assert UNIT_SECRETHASH in setup.channel.partner_state.secrethashes_to_unlockedlocks assert UNIT_SECRETHASH not in setup.channel.partner_state.secrethashes_to_lockedlocks # Make sure that an emptyhash on chain reveal is rejected. block_number_prior_the_expiration = setup.expiration - 2 onchain_reveal = ContractReceiveSecretReveal( transaction_hash=factories.make_address(), secret_registry_address=factories.make_address(), secrethash=EMPTY_HASH_KECCAK, secret=EMPTY_HASH, block_number=block_number_prior_the_expiration, block_hash=factories.make_block_hash(), ) onchain_secret_reveal_iteration = target.state_transition( target_state=offchain_secret_reveal_iteration.new_state, state_change=onchain_reveal, channel_state=setup.channel, pseudo_random_generator=setup.pseudo_random_generator, block_number=block_number_prior_the_expiration, ) unlocked_onchain = setup.channel.partner_state.secrethashes_to_onchain_unlockedlocks assert EMPTY_HASH_KECCAK not in unlocked_onchain # now let's go for the actual secret onchain_reveal.secret = UNIT_SECRET onchain_reveal.secrethash = UNIT_SECRETHASH onchain_secret_reveal_iteration = target.state_transition( target_state=offchain_secret_reveal_iteration.new_state, state_change=onchain_reveal, channel_state=setup.channel, pseudo_random_generator=setup.pseudo_random_generator, block_number=block_number_prior_the_expiration, ) unlocked_onchain = setup.channel.partner_state.secrethashes_to_onchain_unlockedlocks assert UNIT_SECRETHASH in unlocked_onchain # Check that after we register a lock on-chain handling the block again will # not cause us to attempt an onchain re-register extra_block_handle_transition = target.handle_block( target_state=onchain_secret_reveal_iteration.new_state, channel_state=setup.channel, block_number=block_number_prior_the_expiration + 1, block_hash=factories.make_block_hash(), ) assert len(extra_block_handle_transition.events) == 0
def test_contract_receive_channelnew_must_be_idempotent(): block_number = 10 block_hash = factories.make_block_hash() pseudo_random_generator = random.Random() token_network_id = factories.make_address() token_id = factories.make_address() token_network_state = TokenNetworkState(token_network_id, token_id) payment_network_identifier = factories.make_payment_network_identifier() amount = 30 our_balance = amount + 50 channel_state1 = factories.make_channel(our_balance=our_balance) channel_state2 = copy.deepcopy(channel_state1) state_change1 = ContractReceiveChannelNew( transaction_hash=factories.make_transaction_hash(), token_network_identifier=token_network_id, channel_state=channel_state1, block_number=block_number, block_hash=block_hash, ) token_network.state_transition( payment_network_identifier=payment_network_identifier, token_network_state=token_network_state, state_change=state_change1, pseudo_random_generator=pseudo_random_generator, block_number=block_number, block_hash=block_hash, ) state_change2 = ContractReceiveChannelNew( transaction_hash=factories.make_transaction_hash(), token_network_identifier=token_network_id, channel_state=channel_state2, block_number=block_number + 1, block_hash=factories.make_block_hash(), ) # replay the ContractReceiveChannelNew state change iteration = token_network.state_transition( payment_network_identifier=payment_network_identifier, token_network_state=token_network_state, state_change=state_change2, pseudo_random_generator=pseudo_random_generator, block_number=block_number, block_hash=block_hash, ) msg = 'the channel must not have been overwritten' channelmap_by_id = iteration.new_state.channelidentifiers_to_channels assert channelmap_by_id[channel_state1.identifier] == channel_state1, msg channelmap_by_address = iteration.new_state.partneraddresses_to_channelidentifiers partner_channels_ids = channelmap_by_address[ channel_state1.partner_state.address] assert channel_state1.identifier in partner_channels_ids, msg
def test_regression_mediator_send_lock_expired_with_new_block(): """The mediator must send the lock expired, but it must **not** clear itself if it has not **received** the corresponding message. """ pseudo_random_generator = random.Random() channels = factories.mediator_make_channel_pair() payer_transfer = factories.make_signed_transfer_for( channels[0], LONG_EXPIRATION) init_iteration = mediator.state_transition( mediator_state=None, state_change=factories.mediator_make_init_action( channels, payer_transfer), channelidentifiers_to_channels=channels.channel_map, addresses_to_channel=channels.addresses_to_channel(), nodeaddresses_to_networkstates=channels.nodeaddresses_to_networkstates, pseudo_random_generator=pseudo_random_generator, block_number=5, block_hash=factories.make_block_hash(), ) assert init_iteration.new_state is not None send_transfer = search_for_item(init_iteration.events, SendLockedTransfer, {}) assert send_transfer transfer = send_transfer.transfer block_expiration_number = channel.get_sender_expiration_threshold( transfer.lock.expiration) block = Block( block_number=block_expiration_number, gas_limit=1, block_hash=factories.make_transaction_hash(), ) iteration = mediator.state_transition( mediator_state=init_iteration.new_state, state_change=block, channelidentifiers_to_channels=channels.channel_map, addresses_to_channel=channels.addresses_to_channel(), nodeaddresses_to_networkstates=channels.nodeaddresses_to_networkstates, pseudo_random_generator=pseudo_random_generator, block_number=block_expiration_number, block_hash=factories.make_block_hash(), ) msg = ("The payer's lock has also expired, " "but it must not be removed locally (without an Expired lock)") assert transfer.lock.secrethash in channels[ 0].partner_state.secrethashes_to_lockedlocks, msg msg = "The payer has not yet sent an expired lock, the task can not be cleared yet" assert iteration.new_state is not None, msg assert search_for_item(iteration.events, SendLockExpired, {"secrethash": transfer.lock.secrethash}) assert transfer.lock.secrethash not in channels[ 1].our_state.secrethashes_to_lockedlocks
def test_contract_receive_channelnew_must_be_idempotent(channel_properties): block_number = 10 block_hash = factories.make_block_hash() token_network_address = factories.make_address() token_id = factories.make_address() token_network_state = TokenNetworkState( address=token_network_address, token_address=token_id, network_graph=TokenNetworkGraphState(token_network_address), ) pseudo_random_generator = random.Random() properties, _ = channel_properties channel_state1 = factories.create(properties) channel_state2 = deepcopy(channel_state1) state_change1 = ContractReceiveChannelNew( transaction_hash=factories.make_transaction_hash(), channel_state=channel_state1, block_number=block_number, block_hash=block_hash, ) token_network.state_transition( token_network_state=token_network_state, state_change=state_change1, block_number=block_number, block_hash=block_hash, pseudo_random_generator=pseudo_random_generator, ) state_change2 = ContractReceiveChannelNew( transaction_hash=factories.make_transaction_hash(), channel_state=channel_state2, block_number=block_number + 1, block_hash=factories.make_block_hash(), ) # replay the ContractReceiveChannelNew state change iteration = token_network.state_transition( token_network_state=token_network_state, state_change=state_change2, block_number=block_number, block_hash=block_hash, pseudo_random_generator=pseudo_random_generator, ) msg = "the channel must not have been overwritten" channelmap_by_id = iteration.new_state.channelidentifiers_to_channels assert channelmap_by_id[channel_state1.identifier] == channel_state1, msg channelmap_by_address = iteration.new_state.partneraddresses_to_channelidentifiers partner_channels_ids = channelmap_by_address[ channel_state1.partner_state.address] assert channel_state1.identifier in partner_channels_ids, msg
def test_channel_cleared_after_our_unlock(): pseudo_random_generator = random.Random() our_model, _ = create_model(balance=700, num_pending_locks=1) partner_model, partner_key1 = create_model(balance=700, num_pending_locks=0) channel_state = create_channel_from_models(our_model, partner_model, partner_key1) block_number = 1 block_hash = make_block_hash() def make_unlock(unlock_end, partner_end): batch_unlock = ContractReceiveChannelBatchUnlock( transaction_hash=make_transaction_hash(), canonical_identifier=channel_state.canonical_identifier, receiver=partner_end.address, sender=unlock_end.address, locksroot=unlock_end.balance_proof.locksroot, unlocked_amount=10, returned_tokens=0, block_number=block_number, block_hash=block_hash, ) return batch_unlock settle_channel = ContractReceiveChannelSettled( transaction_hash=make_transaction_hash(), canonical_identifier=channel_state.canonical_identifier, our_onchain_locksroot=compute_locksroot( channel_state.our_state.pending_locks), partner_onchain_locksroot=compute_locksroot( channel_state.partner_state.pending_locks), block_number=1, block_hash=make_block_hash(), ) assert settle_channel.our_onchain_locksroot != LOCKSROOT_OF_NO_LOCKS assert settle_channel.partner_onchain_locksroot == LOCKSROOT_OF_NO_LOCKS iteration = channel.state_transition( channel_state=channel_state, state_change=settle_channel, block_number=block_number, block_hash=block_hash, pseudo_random_generator=pseudo_random_generator, ) batch_unlock = make_unlock(channel_state.our_state, channel_state.partner_state) iteration = channel.state_transition( channel_state=iteration.new_state, state_change=batch_unlock, block_number=block_number, block_hash=block_hash, pseudo_random_generator=pseudo_random_generator, ) msg = "partner did not have any locks in the pending locks, channel should have been cleaned" assert iteration.new_state is None, msg
def test_events_loaded_from_storage_should_deserialize(tmp_path): filename = Path(f"{tmp_path}/v{RAIDEN_DB_VERSION}_log.db") storage = SerializedSQLiteStorage(filename, serializer=JSONSerializer()) # Satisfy the foreign-key constraint for state change ID ids = storage.write_state_changes([ Block( block_number=BlockNumber(1), gas_limit=BlockGasLimit(1), block_hash=factories.make_block_hash(), ) ]) canonical_identifier = factories.make_canonical_identifier() recipient = factories.make_address() participant = factories.make_address() event = SendWithdrawRequest( recipient=recipient, canonical_identifier=canonical_identifier, message_identifier=factories.make_message_identifier(), total_withdraw=WithdrawAmount(1), participant=participant, expiration=BlockExpiration(10), nonce=Nonce(15), ) storage.write_events([(ids[0], event)]) stored_events = storage.get_events() assert stored_events[0] == event
def test_serialize_contract_send_subclass(chain_state): """Serializing must preserve class Regression test for https://github.com/raiden-network/raiden/issues/6075 """ canonical_identifier = CanonicalIdentifier( chain_identifier=ChainID(1), token_network_address=TokenNetworkAddress(factories.make_address()), channel_identifier=factories.make_channel_identifier(), ) chain_state.pending_transactions = [ ContractSendChannelClose( canonical_identifier=canonical_identifier, triggered_by_block_hash=factories.make_block_hash(), balance_proof=None, ) ] serialized_chain_state = JSONSerializer.serialize(chain_state) deserialized_chain_state = JSONSerializer.deserialize( serialized_chain_state) assert ( chain_state.pending_transactions[0].__class__.__name__ == deserialized_chain_state.pending_transactions[0].__class__.__name__) assert chain_state == deserialized_chain_state
def initialize(self, block_number, random, random_seed): self.random_seed = random_seed self.block_number = block_number self.block_hash = factories.make_block_hash() self.random = random self.private_key, self.address = factories.make_privkey_address() self.chain_state = ChainState( pseudo_random_generator=self.random, block_number=self.block_number, block_hash=self.block_hash, our_address=self.address, chain_id=factories.UNIT_CHAIN_ID, ) self.token_network_id = factories.UNIT_TOKEN_NETWORK_ADDRESS self.token_id = factories.UNIT_TOKEN_ADDRESS self.token_network_state = TokenNetworkState(self.token_network_id, self.token_id) self.payment_network_id = factories.make_payment_network_identifier() self.payment_network_state = PaymentNetworkState( self.payment_network_id, [self.token_network_state]) self.chain_state.identifiers_to_paymentnetworks[ self.payment_network_id] = self.payment_network_state self.chain_state.tokennetworkaddresses_to_paymentnetworkaddresses[ self.token_network_id] = self.payment_network_id channels = [ self.new_channel_with_transaction() for _ in range(self.initial_number_of_channels) ] return multiple(*channels)
def __init__(self, message_handler=None, state_transition=None, private_key=None): if private_key is None: self.private_key, self.address = factories.make_privkey_address() else: self.private_key = private_key self.address = privatekey_to_address(private_key) self.chain = MockChain(network_id=17, node_address=self.address) self.signer = LocalSigner(self.private_key) self.message_handler = message_handler self.user_deposit = Mock() if state_transition is None: state_transition = node.state_transition serializer = JSONSerializer state_manager = StateManager(state_transition, None) storage = SerializedSQLiteStorage(":memory:", serializer) self.wal = WriteAheadLog(state_manager, storage) state_change = ActionInitChain( pseudo_random_generator=random.Random(), block_number=0, block_hash=factories.make_block_hash(), our_address=self.chain.node_address, chain_id=self.chain.network_id, ) self.wal.log_and_dispatch(state_change)
def test_regression_unavailable_nodes_must_be_properly_filtered(): """The list of available routes provided must be filtered based on the network status of the partner node. Regression test for: https://github.com/raiden-network/raiden/issues/3567 """ block_number = 5 pseudo_random_generator = random.Random() channels = factories.mediator_make_channel_pair() payer_transfer = factories.make_signed_transfer_for( channels[0], LONG_EXPIRATION) all_nodes_offline = { channel.partner_state.address: NODE_NETWORK_UNREACHABLE for channel in channels.channels } initial_iteration = mediator.state_transition( mediator_state=None, state_change=factories.mediator_make_init_action( channels, payer_transfer), channelidentifiers_to_channels=channels.channel_map, nodeaddresses_to_networkstates=all_nodes_offline, pseudo_random_generator=pseudo_random_generator, block_number=block_number, block_hash=factories.make_block_hash(), ) send_transfer = search_for_item(initial_iteration.events, SendLockedTransfer, {}) msg = ( 'All available routes are with unavailable nodes, therefore no send ' 'should be produced') assert send_transfer is None, msg
def test_channel_closed_must_clear_ordered_messages(chain_state, token_network_state, netting_channel_state): recipient = netting_channel_state.partner_state.address message_identifier = random.randint(0, 2**16) amount = 10 queue_identifier = QueueIdentifier( recipient=recipient, canonical_identifier=netting_channel_state.canonical_identifier) # Regression test: # The code delivered_message handler worked only with a queue of one # element message = factories.create( factories.LockedTransferProperties( message_identifier=message_identifier, token=token_network_state.token_address, canonical_identifier=netting_channel_state.canonical_identifier, transferred_amount=amount, recipient=recipient, )) chain_state.queueids_to_queues[queue_identifier] = [message] closed = state_change.ContractReceiveChannelClosed( transaction_hash=EMPTY_HASH, transaction_from=recipient, canonical_identifier=netting_channel_state.canonical_identifier, block_number=1, block_hash=factories.make_block_hash(), ) iteration = node.handle_state_change(chain_state, closed) assert queue_identifier not in iteration.new_state.queueids_to_queues
def test_actioninitchain_restore(): """ ActionInitChain *must* restore the previous pseudo random generator state. Message identifiers are used for confirmation messages, e.g. delivered and processed messages, therefore it's important for each message identifier to not collide with a previous identifier, for this reason the PRNG is used. Additionally, during restarts the state changes are reapplied, and it's really important for the re-execution of the state changes to be deterministic, otherwise undefined behavior may happen. For this reason the state of the PRNG must be restored. If the above is not respected, the message ids generated during restart will not match the previous IDs and the message queues won't be properly cleared up. """ pseudo_random_generator = random.Random() block_number = 577 our_address = factories.make_address() chain_id = 777 original_obj = state_change.ActionInitChain( pseudo_random_generator=pseudo_random_generator, block_number=block_number, block_hash=factories.make_block_hash(), our_address=our_address, chain_id=chain_id, ) decoded_obj = JSONSerializer.deserialize( JSONSerializer.serialize(original_obj)) assert original_obj == decoded_obj
def setup_storage(db_path): storage = SerializedSQLiteStorage(str(db_path), JSONSerializer()) chain_state_data = Path(__file__).parent / 'data/v16_chainstate.json' chain_state = chain_state_data.read_text() storage.write_state_change( ActionInitChain( pseudo_random_generator=random.Random(), block_number=1, block_hash=factories.make_block_hash(), our_address=factories.make_address(), chain_id=1, ), datetime.utcnow().isoformat(timespec='milliseconds'), ) cursor = storage.conn.cursor() cursor.execute( """ INSERT INTO state_snapshot(identifier, statechange_id, data) VALUES(1, 1, ?) """, (chain_state, ), ) storage.conn.commit() return storage
def initialize(self, block_number, random, random_seed): self.random_seed = random_seed self.block_number = block_number self.block_hash = factories.make_block_hash() self.random = random self.private_key, self.address = factories.make_privkey_address() self.chain_state = ChainState( pseudo_random_generator=self.random, block_number=self.block_number, block_hash=self.block_hash, our_address=self.address, chain_id=factories.UNIT_CHAIN_ID, ) self.token_network_id = factories.make_address() self.token_id = factories.make_address() self.token_network_state = TokenNetworkState(self.token_network_id, self.token_id) self.payment_network_id = factories.make_payment_network_identifier() self.payment_network_state = PaymentNetworkState( self.payment_network_id, [self.token_network_state], ) self.chain_state.identifiers_to_paymentnetworks[ self.payment_network_id] = self.payment_network_state return self.new_channel_with_transaction()
def test_handle_new_token_network(chain_state, token_network_address): token_address = factories.make_address() token_network = TokenNetworkState( address=token_network_address, token_address=token_address, network_graph=TokenNetworkGraphState(token_network_address=token_network_address), ) token_network_registry_address = factories.make_address() state_change = ContractReceiveNewTokenNetwork( token_network_registry_address=token_network_registry_address, token_network=token_network, transaction_hash=factories.make_transaction_hash(), block_hash=factories.make_block_hash(), block_number=factories.make_block_number(), ) transition_result = handle_contract_receive_new_token_network( chain_state=chain_state, state_change=state_change ) new_chain_state = transition_result.new_state token_network_registry = new_chain_state.identifiers_to_tokennetworkregistries[ token_network_registry_address ] assert token_network_registry.address == token_network_registry_address assert not transition_result.events assert get_networks( chain_state=chain_state, token_network_registry_address=token_network_registry_address, token_address=token_address, ) == (token_network_registry, token_network)
def test_write_read_log() -> None: wal = new_wal(state_transition_noop) block_number = BlockNumber(1337) block_hash = make_block_hash() block = Block(block_number=block_number, gas_limit=BlockGasLimit(1), block_hash=block_hash) unlocked_amount = TokenAmount(10) returned_amount = TokenAmount(5) participant = make_address() partner = make_address() locksroot = make_locksroot() contract_receive_unlock = ContractReceiveChannelBatchUnlock( transaction_hash=make_transaction_hash(), canonical_identifier=make_canonical_identifier( token_network_address=make_address()), receiver=participant, sender=partner, locksroot=locksroot, unlocked_amount=unlocked_amount, returned_tokens=returned_amount, block_number=block_number, block_hash=block_hash, ) state_changes1 = wal.storage.get_statechanges_by_range( RANGE_ALL_STATE_CHANGES) count1 = len(state_changes1) dispatch(wal, [block]) state_changes2 = wal.storage.get_statechanges_by_range( RANGE_ALL_STATE_CHANGES) count2 = len(state_changes2) assert count1 + 1 == count2 dispatch(wal, [contract_receive_unlock]) state_changes3 = wal.storage.get_statechanges_by_range( RANGE_ALL_STATE_CHANGES) count3 = len(state_changes3) assert count2 + 1 == count3 result1, result2 = state_changes3[-2:] assert isinstance(result1, Block) assert result1.block_number == block_number assert isinstance(result2, ContractReceiveChannelBatchUnlock) assert result2.receiver == participant assert result2.sender == partner assert result2.locksroot == locksroot assert result2.unlocked_amount == unlocked_amount assert result2.returned_tokens == returned_amount # Make sure state snapshot can only go for corresponding state change ids with pytest.raises(sqlite3.IntegrityError): wal.storage.write_state_snapshot(State(), StateChangeID(make_ulid()), 1)
def create_fake_web3_for_block_hash(number_of_blocks: int = 0) -> Tuple[FakeWeb3, Dict[int, Any]]: block_to_blockhash = {} for block in range(0, number_of_blocks): block_to_blockhash[block] = HexBytes(make_block_hash()) fake_web3 = FakeWeb3(block_to_blockhash) return fake_web3, block_to_blockhash
def test_is_transaction_effect_satisfied(chain_state, token_network_id, netting_channel_state): canonical_identifier = netting_channel_state.canonical_identifier assert token_network_id == canonical_identifier.token_network_address transaction = ContractSendChannelBatchUnlock( canonical_identifier=canonical_identifier, participant=netting_channel_state.partner_state.address, triggered_by_block_hash=make_block_hash(), ) state_change = ContractReceiveChannelBatchUnlock( transaction_hash=UNIT_SECRETHASH, canonical_identifier=canonical_identifier, participant=HOP1, partner=HOP2, locksroot=EMPTY_MERKLE_ROOT, unlocked_amount=0, returned_tokens=0, block_number=1, block_hash=make_block_hash(), ) # unlock for a channel in which this node is not a participant must return False assert not is_transaction_effect_satisfied(chain_state, transaction, state_change) # now call normally with us being the partner and not the participant state_change.partner = netting_channel_state.partner_state.address state_change.participant = netting_channel_state.our_state.address assert not is_transaction_effect_satisfied(chain_state, transaction, state_change) # finally call with us being the participant and not the partner which should check out state_change.participant = netting_channel_state.partner_state.address state_change.partner = netting_channel_state.our_state.address # ContractSendChannelBatchUnlock would only be satisfied if both sides are unlocked # and if the channel was cleared assert not is_transaction_effect_satisfied(chain_state, transaction, state_change) channel_settled = ContractReceiveChannelSettled( transaction_hash=bytes(32), canonical_identifier=canonical_identifier, our_onchain_locksroot=EMPTY_MERKLE_ROOT, partner_onchain_locksroot=EMPTY_MERKLE_ROOT, block_number=1, block_hash=make_block_hash(), ) iteration = state_transition(chain_state=chain_state, state_change=channel_settled) assert is_transaction_effect_satisfied(iteration.new_state, transaction, state_change)
def test_handle_contract_send_channelunlock_already_unlocked(): """This is a test for the scenario where the onchain unlock has already happened when we get to handle our own send unlock transaction. Regression test for https://github.com/raiden-network/raiden/issues/3152 """ channel_identifier = 1 token_network_identifier = make_address() token_address = make_address() participant = make_address() raiden = MockRaidenService() def detail_participants(participant1, participant2, block_identifier, channel_identifier): transferred_amount = 1 locked_amount = 1 locksroot = make_32bytes() balance_hash = hash_balance_data(transferred_amount, locked_amount, locksroot) our_details = ParticipantDetails( address=raiden.address, deposit=5, withdrawn=0, is_closer=False, balance_hash=balance_hash, nonce=1, locksroot=locksroot, locked_amount=locked_amount, ) transferred_amount = 1 locked_amount = 1 # Let's mock here that partner locksroot is 0x0 locksroot = EMPTY_HASH balance_hash = hash_balance_data(transferred_amount, locked_amount, locksroot) partner_details = ParticipantDetails( address=participant, deposit=5, withdrawn=0, is_closer=True, balance_hash=balance_hash, nonce=1, locksroot=locksroot, locked_amount=locked_amount, ) return ParticipantsDetails(our_details, partner_details) # make sure detail_participants returns partner data with a locksroot of 0x0 raiden.chain.token_network.detail_participants = detail_participants event = ContractSendChannelBatchUnlock( token_address=token_address, token_network_identifier=token_network_identifier, channel_identifier=channel_identifier, participant=participant, triggered_by_block_hash=make_block_hash(), ) # This should not throw an unrecoverable error RaidenEventHandler().on_raiden_event(raiden=raiden, event=event)
def test_events_for_onchain_secretreveal(): """ Secret must be registered on-chain when the unsafe region is reached and the secret is known. """ block_number = 10 expiration = block_number + 30 channels = make_channel_set([channel_properties]) from_transfer = make_target_transfer(channels[0], expiration=expiration) channel.handle_receive_lockedtransfer(channels[0], from_transfer) channel.register_offchain_secret(channels[0], UNIT_SECRET, UNIT_SECRETHASH) safe_to_wait = expiration - channels[0].reveal_timeout - 1 unsafe_to_wait = expiration - channels[0].reveal_timeout state = TargetTransferState(channels.get_route(0), from_transfer) events = target.events_for_onchain_secretreveal( target_state=state, channel_state=channels[0], block_number=safe_to_wait, block_hash=factories.make_block_hash(), ) assert not events events = target.events_for_onchain_secretreveal( target_state=state, channel_state=channels[0], block_number=unsafe_to_wait, block_hash=factories.make_block_hash(), ) msg = "when its not safe to wait, the contract send must be emitted" assert search_for_item(events, ContractSendSecretReveal, {"secret": UNIT_SECRET}), msg msg = "second call must not emit ContractSendSecretReveal again" assert not target.events_for_onchain_secretreveal( target_state=state, channel_state=channels[0], block_number=unsafe_to_wait, block_hash=factories.make_block_hash(), ), msg
def test_channel_cleared_after_our_unlock(): our_model, _ = create_model(balance=700, merkletree_width=1) partner_model, partner_key1 = create_model(balance=700, merkletree_width=0) channel_state = create_channel_from_models(our_model, partner_model, partner_key1) block_number = 1 block_hash = make_block_hash() def make_unlock(unlock_end, partner_end): batch_unlock = ContractReceiveChannelBatchUnlock( transaction_hash=make_transaction_hash(), canonical_identifier=channel_state.canonical_identifier, participant=partner_end.address, partner=unlock_end.address, locksroot=unlock_end.balance_proof.locksroot, unlocked_amount=10, returned_tokens=0, block_number=block_number, block_hash=block_hash, ) return batch_unlock settle_channel = ContractReceiveChannelSettled( transaction_hash=make_transaction_hash(), canonical_identifier=channel_state.canonical_identifier, our_onchain_locksroot=merkleroot(channel_state.our_state.merkletree), partner_onchain_locksroot=merkleroot( channel_state.partner_state.merkletree), block_number=1, block_hash=make_block_hash(), ) assert settle_channel.our_onchain_locksroot is not EMPTY_MERKLE_ROOT assert settle_channel.partner_onchain_locksroot is EMPTY_MERKLE_ROOT iteration = channel.state_transition(channel_state, settle_channel, block_number, block_hash) batch_unlock = make_unlock(channel_state.our_state, channel_state.partner_state) iteration = channel.state_transition(iteration.new_state, batch_unlock, block_number, block_hash) msg = "partner did not have any locks in the merkletree, channel should have been cleaned" assert iteration.new_state is None, msg
def chain_state(our_address): block_number = BlockNumber(1) return ChainState( pseudo_random_generator=random.Random(), block_number=block_number, block_hash=factories.make_block_hash(), our_address=our_address, chain_id=UNIT_CHAIN_ID, )
def settle_channel(self, partner): channel = self.address_to_channel[partner] channel_settled_state_change = ContractReceiveChannelSettled( transaction_hash=factories.make_transaction_hash(), token_network_identifier=channel.token_network_identifier, channel_identifier=channel.identifier, block_number=self.block_number + 1, block_hash=factories.make_block_hash(), ) node.state_transition(self.chain_state, channel_settled_state_change)
def new_channel_with_transaction(self): partner_address = self.new_channel() channel_new_state_change = ContractReceiveChannelNew( transaction_hash=factories.make_transaction_hash(), channel_state=self.address_to_channel[partner_address], block_number=self.block_number, block_hash=factories.make_block_hash(), ) node.state_transition(self.chain_state, channel_new_state_change) return partner_address
def test_is_transaction_expired(): expiration = 24 block_number = expiration + 1 transaction = ContractSendChannelUpdateTransfer( expiration=expiration, balance_proof=None, triggered_by_block_hash=factories.make_block_hash(), ) assert is_transaction_expired(transaction, block_number) transaction = ContractSendSecretReveal( expiration=expiration, secret=factories.UNIT_SECRET, triggered_by_block_hash=factories.make_block_hash(), ) assert is_transaction_expired(transaction, block_number) transaction = ContractSendSecretReveal( expiration=block_number, secret=factories.UNIT_SECRET, triggered_by_block_hash=factories.make_block_hash(), ) assert not is_transaction_expired(transaction, block_number)
def setup_storage(db_path): storage = SerializedSQLiteStorage(str(db_path), JSONSerializer()) storage.write_state_change( ActionInitChain( pseudo_random_generator=random.Random(), block_number=1, block_hash=factories.make_block_hash(), our_address=factories.make_address(), chain_id=1, ), datetime.utcnow().isoformat(timespec='milliseconds'), ) return storage
def test_is_transaction_effect_satisfied( chain_state, token_network_state, token_network_id, netting_channel_state, ): transaction = ContractSendChannelBatchUnlock( token_address=token_network_state.token_address, token_network_identifier=token_network_id, channel_identifier=netting_channel_state.identifier, participant=HOP2, triggered_by_block_hash=make_block_hash(), ) state_change = ContractReceiveChannelBatchUnlock( transaction_hash=UNIT_SECRETHASH, token_network_identifier=token_network_id, participant=HOP1, partner=HOP2, locksroot=EMPTY_MERKLE_ROOT, unlocked_amount=0, returned_tokens=0, block_number=1, block_hash=make_block_hash(), ) # unlock for a channel in which this node is not a participant must return False assert not is_transaction_effect_satisfied(chain_state, transaction, state_change) # now call normally with us being the partner and not the participant state_change.partner = netting_channel_state.our_state.address state_change.participant = netting_channel_state.partner_state.address assert not is_transaction_effect_satisfied(chain_state, transaction, state_change) # finally call with us being the participant and not the partner which should check out state_change.participant = netting_channel_state.our_state.address state_change.partner = netting_channel_state.partner_state.address assert is_transaction_effect_satisfied(chain_state, transaction, state_change)
def test_update_channel_reveal_timeout(): pseudo_random_generator = random.Random() channel_state = factories.create( factories.NettingChannelStateProperties(settle_timeout=500, reveal_timeout=50)) invalid_reveal_timeout = 260 valid_reveal_timeout = 250 set_reveal_timeout = ActionChannelSetRevealTimeout( canonical_identifier=channel_state.canonical_identifier, reveal_timeout=invalid_reveal_timeout, ) iteration = channel.state_transition( channel_state=channel_state, state_change=set_reveal_timeout, block_number=1, block_hash=make_block_hash(), pseudo_random_generator=pseudo_random_generator, ) assert iteration.new_state == channel_state assert isinstance(iteration.events[0], EventInvalidActionSetRevealTimeout) set_reveal_timeout = ActionChannelSetRevealTimeout( canonical_identifier=channel_state.canonical_identifier, reveal_timeout=250) iteration = channel.state_transition( channel_state=channel_state, state_change=set_reveal_timeout, block_number=1, block_hash=make_block_hash(), pseudo_random_generator=pseudo_random_generator, ) assert iteration.new_state.reveal_timeout == valid_reveal_timeout
def new_channel_with_transaction(self): partner_address = self.new_channel() channel_new_state_change = ContractReceiveChannelNew( transaction_hash=factories.make_transaction_hash(), channel_state=self.address_to_channel[partner_address], block_number=self.block_number, block_hash=factories.make_block_hash(), ) node.state_transition(self.chain_state, channel_new_state_change, None) self.chain_state.nodeaddresses_to_networkstates[ partner_address] = NODE_NETWORK_REACHABLE return partner_address