def get_channel_state( token_address, token_network_address, reveal_timeout, payment_channel_proxy, opened_block_number, ): channel_details = payment_channel_proxy.detail() our_state = NettingChannelEndState( channel_details['our_address'], channel_details['our_deposit'], ) partner_state = NettingChannelEndState( channel_details['partner_address'], channel_details['partner_deposit'], ) identifier = payment_channel_proxy.channel_identifier settle_timeout = payment_channel_proxy.settle_timeout() closed_block_number = None # ignore bad open block numbers if opened_block_number <= 0: return None open_transaction = TransactionExecutionStatus( None, opened_block_number, TransactionExecutionStatus.SUCCESS, ) if closed_block_number: close_transaction = TransactionExecutionStatus( None, closed_block_number, TransactionExecutionStatus.SUCCESS, ) else: close_transaction = None # For the current implementation the channel is a smart contract that # will be killed on settle. settle_transaction = None channel = NettingChannelState( identifier, token_address, token_network_address, reveal_timeout, settle_timeout, our_state, partner_state, open_transaction, close_transaction, settle_transaction, ) return channel
def get_channel_state(token_address, reveal_timeout, netting_channel_proxy): channel_details = netting_channel_proxy.detail() our_state = NettingChannelEndState( channel_details['our_address'], channel_details['our_balance'], ) partner_state = NettingChannelEndState( channel_details['partner_address'], channel_details['partner_balance'], ) identifier = netting_channel_proxy.address reveal_timeout = reveal_timeout settle_timeout = channel_details['settle_timeout'] opened_block_number = netting_channel_proxy.opened() closed_block_number = netting_channel_proxy.closed() # ignore bad open block numbers if opened_block_number <= 0: return None # ignore negative closed block numbers if closed_block_number < 0: return None open_transaction = TransactionExecutionStatus( None, opened_block_number, TransactionExecutionStatus.SUCCESS, ) if closed_block_number: close_transaction = TransactionExecutionStatus( None, closed_block_number, TransactionExecutionStatus.SUCCESS, ) else: close_transaction = None # For the current implementation the channel is a smart contract that # will be killed on settle. settle_transaction = None channel = NettingChannelState( identifier, token_address, reveal_timeout, settle_timeout, our_state, partner_state, open_transaction, close_transaction, settle_transaction, ) return channel
def create(self) -> NettingChannelEndState: state = NettingChannelEndState(self.address or make_address(), self.balance) merkletree_leaves = (self.merkletree_leaves or make_merkletree_leaves(self.merkletree_width) or None) if merkletree_leaves: state.merkletree = MerkleTreeState( compute_layers(merkletree_leaves)) return state
def _(properties, defaults=None) -> NettingChannelEndState: args = _properties_to_kwargs( properties, defaults or NettingChannelEndStateProperties.DEFAULTS) state = NettingChannelEndState(args["address"] or make_address(), args["balance"]) merkletree_leaves = (args["merkletree_leaves"] or make_merkletree_leaves(args["merkletree_width"]) or None) if merkletree_leaves: state.merkletree = MerkleTreeState(compute_layers(merkletree_leaves)) return state
def _(properties, defaults=None) -> NettingChannelEndState: args = _properties_to_kwargs(properties, defaults or NETTING_CHANNEL_END_STATE_DEFAULTS) state = NettingChannelEndState(args['address'] or make_address(), args['balance']) merkletree_leaves = ( args['merkletree_leaves'] or make_merkletree_leaves(args['merkletree_width']) or None ) if merkletree_leaves: state.merkletree = MerkleTreeState(compute_layers(merkletree_leaves)) return state
def _(properties, defaults=None) -> NettingChannelEndState: args = _properties_to_kwargs( properties, defaults or NETTING_CHANNEL_END_STATE_DEFAULTS) state = NettingChannelEndState(args['address'] or make_address(), args['balance']) merkletree_leaves = (args['merkletree_leaves'] or make_merkletree_leaves(args['merkletree_width']) or None) if merkletree_leaves: state.merkletree = MerkleTreeState(compute_layers(merkletree_leaves)) return state
def create_channel_from_models(our_model, partner_model): """Utility to instantiate state objects used throughout the tests.""" our_state = NettingChannelEndState( our_model.participant_address, our_model.balance, ) partner_state = NettingChannelEndState( partner_model.participant_address, partner_model.balance, ) identifier = factories.make_channel_identifier() token_address = factories.make_address() token_network_identifier = factories.make_address() reveal_timeout = 10 settle_timeout = 100 opened_transaction = TransactionExecutionStatus( None, 1, TransactionExecutionStatus.SUCCESS, ) closed_transaction = None settled_transaction = None channel_state = NettingChannelState( identifier=identifier, chain_id=UNIT_CHAIN_ID, token_address=token_address, token_network_identifier=token_network_identifier, reveal_timeout=reveal_timeout, settle_timeout=settle_timeout, our_state=our_state, partner_state=partner_state, open_transaction=opened_transaction, close_transaction=closed_transaction, settle_transaction=settled_transaction, ) assert_partner_state( channel_state.our_state, channel_state.partner_state, our_model, ) assert_partner_state( channel_state.partner_state, channel_state.our_state, partner_model, ) return channel_state
def contractreceivechannelnew_from_event( new_channel_details: NewChannelDetails, channel_config: ChannelConfig, event: DecodedEvent) -> ContractReceiveChannelNew: data = event.event_data args = data["args"] settle_timeout = args["settle_timeout"] block_number = event.block_number identifier = args["channel_identifier"] token_network_address = TokenNetworkAddress(event.originating_contract) our_state = NettingChannelEndState(new_channel_details.our_address, Balance(0)) partner_state = NettingChannelEndState(new_channel_details.partner_address, Balance(0)) open_transaction = TransactionExecutionStatus( None, block_number, TransactionExecutionStatus.SUCCESS) # If the node was offline for a long period, the channel may have been # closed already, if that is the case during initialization the node will # process the other events and update the channel's state close_transaction: Optional[TransactionExecutionStatus] = None settle_transaction: Optional[TransactionExecutionStatus] = None channel_state = NettingChannelState( canonical_identifier=CanonicalIdentifier( chain_identifier=new_channel_details.chain_id, token_network_address=token_network_address, channel_identifier=identifier, ), token_address=new_channel_details.token_address, token_network_registry_address=new_channel_details. token_network_registry_address, reveal_timeout=channel_config.reveal_timeout, settle_timeout=settle_timeout, fee_schedule=channel_config.fee_schedule, our_state=our_state, partner_state=partner_state, open_transaction=open_transaction, close_transaction=close_transaction, settle_transaction=settle_transaction, ) return ContractReceiveChannelNew( channel_state=channel_state, transaction_hash=event.transaction_hash, block_number=block_number, block_hash=event.block_hash, )
def test_channelstate_get_unlock_proof(): number_of_transfers = 100 lock_amounts = cycle([1, 3, 5, 7, 11]) lock_secrets = [ make_secret(i) for i in range(number_of_transfers) ] block_number = 1000 locked_amount = 0 settle_timeout = 8 merkletree_leaves = [] locked_locks = {} unlocked_locks = {} for lock_amount, lock_secret in zip(lock_amounts, lock_secrets): block_number += 1 locked_amount += lock_amount lock_expiration = block_number + settle_timeout lock_secrethash = sha3(lock_secret) lock = HashTimeLockState( lock_amount, lock_expiration, lock_secrethash, ) merkletree_leaves.append(lock.lockhash) if random.randint(0, 1) == 0: locked_locks[lock_secrethash] = lock else: unlocked_locks[lock_secrethash] = UnlockPartialProofState(lock, lock_secret) end_state = NettingChannelEndState(HOP1, 300) end_state.secrethashes_to_lockedlocks = locked_locks end_state.secrethashes_to_unlockedlocks = unlocked_locks end_state.merkletree = MerkleTreeState(compute_layers(merkletree_leaves)) unlock_proof = channel.get_batch_unlock(end_state) assert len(unlock_proof) == len(end_state.merkletree.layers[LEAVES]) leaves_packed = b''.join(lock.encoded for lock in unlock_proof) recomputed_merkle_tree = MerkleTreeState(compute_layers( merkle_leaves_from_packed_data(leaves_packed), )) assert len(recomputed_merkle_tree.layers[LEAVES]) == len(end_state.merkletree.layers[LEAVES]) computed_merkleroot = merkleroot(recomputed_merkle_tree) assert merkleroot(end_state.merkletree) == computed_merkleroot
def make_channel_endstate( address: typing.Address = EMPTY, balance: typing.Balance = EMPTY, ) -> NettingChannelEndState: address = if_empty(address, make_address()) balance = if_empty(balance, 0) return NettingChannelEndState(address, balance)
def make_endstate(address, balance): end_state = NettingChannelEndState( address, balance, ) return end_state
def test_endstate_update_contract_balance(): """The balance must be monotonic.""" balance1 = 101 node_address = factories.make_address() end_state = NettingChannelEndState(node_address, balance1) assert end_state.contract_balance == balance1 channel.update_contract_balance(end_state, balance1 - 10) assert end_state.contract_balance == balance1 channel.update_contract_balance(end_state, balance1 + 10) assert end_state.contract_balance == balance1 + 10
def register_secret_endstate( end_state: NettingChannelEndState, secret: typing.Secret, secrethash: typing.SecretHash, ) -> None: if is_lock_locked(end_state, secrethash): pendinglock = end_state.secrethashes_to_lockedlocks[secrethash] del end_state.secrethashes_to_lockedlocks[secrethash] end_state.secrethashes_to_unlockedlocks[ secrethash] = UnlockPartialProofState( pendinglock, secret, )
def test_new_end_state(): """Test the defaults for an end state object.""" balance1 = 101 node_address = factories.make_address() end_state = NettingChannelEndState(node_address, balance1) lock_secret = sha3(b'test_end_state') lock_secrethash = sha3(lock_secret) assert channel.is_lock_pending(end_state, lock_secrethash) is False assert channel.is_lock_locked(end_state, lock_secrethash) is False assert channel.get_next_nonce(end_state) == 1 assert channel.get_amount_locked(end_state) == 0 assert not channel.get_known_unlocks(end_state) assert merkleroot(end_state.merkletree) == EMPTY_MERKLE_ROOT assert not end_state.secrethashes_to_lockedlocks assert not end_state.secrethashes_to_unlockedlocks
def test_detect_balance_proof_change(): prng = random.Random() block_hash = factories.make_block_hash() old = ChainState( pseudo_random_generator=prng, block_number=1, block_hash=block_hash, our_address=2, chain_id=3, ) new = ChainState( pseudo_random_generator=prng, block_number=1, block_hash=block_hash, our_address=2, chain_id=3, ) def diff(): return list(detect_balance_proof_change(old, new)) assert len(diff()) == 0 payment_network = PaymentNetworkState(b'x', []) payment_network_copy = deepcopy(payment_network) new.identifiers_to_paymentnetworks['a'] = payment_network assert len(diff()) == 0 token_network = TokenNetworkState(b'a', b'a') token_network_copy = deepcopy(token_network) payment_network.tokenidentifiers_to_tokennetworks['a'] = token_network assert len(diff()) == 0 channel = NettingChannelState( 1, 0, b'a', 1, 1, 1, 2, None, None, TransactionExecutionStatus(result='success'), ) channel_copy = deepcopy(channel) token_network.channelidentifiers_to_channels['a'] = channel partner_state = NettingChannelEndState(b'a', 0) partner_state_copy = deepcopy(partner_state) channel.partner_state = partner_state assert len(diff()) == 0 balance_proof = object() partner_state.balance_proof = balance_proof assert len(diff()) == 1 old.identifiers_to_paymentnetworks['a'] = payment_network_copy assert len(diff()) == 1 payment_network_copy.tokenidentifiers_to_tokennetworks[ 'a'] = token_network_copy assert len(diff()) == 1 token_network_copy.channelidentifiers_to_channels['a'] = channel_copy channel_copy.partner_state = partner_state_copy assert len(diff()) == 1 channel_copy.partner_state.balance_proof = balance_proof assert len(diff()) == 0 channel_copy.partner_state.balance_proof = object() assert len(diff()) == 1 assert diff() == [balance_proof]
def channel_from_nettingcontract(our_key, netting_contract, reveal_timeout): """ Create a `channel.Channel` for the `netting_contract`. Use this to make sure that both implementations (the smart contract and the python code) work in tandem.""" our_address = privatekey_to_address(our_key) token_address_hex = netting_contract.tokenAddress(sender=our_key) settle_timeout = netting_contract.settleTimeout(sender=our_key) address_balance = netting_contract.addressAndBalance(sender=our_key) address1_hex, balance1, address2_hex, balance2 = address_balance opened_block_number = netting_contract.opened(sender=our_key) closed_block_number = netting_contract.closed(sender=our_key) settled_block_number = None identifier = address_decoder(netting_contract.address) token_address = normalize_address(token_address_hex) address1 = normalize_address(address1_hex) address2 = normalize_address(address2_hex) if our_address == address1: our_balance = balance1 partner_address = address2 partner_balance = balance2 else: our_balance = balance2 partner_address = address1 partner_balance = balance1 our_state = NettingChannelEndState( our_address, our_balance, ) partner_state = NettingChannelEndState( partner_address, partner_balance, ) open_transaction = TransactionExecutionStatus( None, opened_block_number, TransactionExecutionStatus.SUCCESS, ) close_transaction = None if closed_block_number: close_transaction = TransactionExecutionStatus( None, closed_block_number, TransactionExecutionStatus.SUCCESS, ) settle_transaction = None if settled_block_number: settle_transaction = TransactionExecutionStatus( None, settled_block_number, TransactionExecutionStatus.SUCCESS, ) channel = NettingChannelState( identifier, token_address, reveal_timeout, settle_timeout, our_state, partner_state, open_transaction, close_transaction, settle_transaction, ) return channel
def test_invalid_timeouts(): token_address = factories.make_address() reveal_timeout = 5 settle_timeout = 10 identifier = factories.make_address() address1 = factories.make_address() address2 = factories.make_address() balance1 = 10 balance2 = 10 opened_transaction = TransactionExecutionStatus( None, 1, TransactionExecutionStatus.SUCCESS, ) closed_transaction = None settled_transaction = None our_state = NettingChannelEndState(address1, balance1) partner_state = NettingChannelEndState(address2, balance2) # do not allow a reveal timeout larger than the settle timeout with pytest.raises(ValueError): large_reveal_timeout = 50 small_settle_timeout = 49 NettingChannelState( identifier, token_address, large_reveal_timeout, small_settle_timeout, our_state, partner_state, opened_transaction, closed_transaction, settled_transaction, ) # TypeError: 'a', [], {} for invalid_value in (-1, 0, 1.1, 1.0): with pytest.raises(ValueError): NettingChannelState( identifier, token_address, invalid_value, settle_timeout, our_state, partner_state, opened_transaction, closed_transaction, settled_transaction, ) with pytest.raises(ValueError): NettingChannelState( identifier, token_address, reveal_timeout, invalid_value, our_state, partner_state, opened_transaction, closed_transaction, settled_transaction, )
def test_detect_balance_proof_change(): prng = random.Random() block_hash = make_block_hash() our_address = make_address() empty_chain = ChainState( pseudo_random_generator=prng, block_number=1, block_hash=block_hash, our_address=our_address, chain_id=3, ) assert empty(detect_balance_proof_change(empty_chain, empty_chain)), MSG_NO_CHANGE assert empty( detect_balance_proof_change(empty_chain, deepcopy(empty_chain))), MSG_NO_CHANGE token_network_registry_address = make_address() chain_with_registry_no_bp = deepcopy(empty_chain) chain_with_registry_no_bp.identifiers_to_tokennetworkregistries[ token_network_registry_address] = TokenNetworkRegistryState( token_network_registry_address, []) assert empty( detect_balance_proof_change(empty_chain, chain_with_registry_no_bp)), MSG_NO_CHANGE assert empty( detect_balance_proof_change( chain_with_registry_no_bp, deepcopy(chain_with_registry_no_bp))), MSG_NO_CHANGE token_network_address = make_address() token_address = make_address() chain_with_token_network_no_bp = deepcopy(chain_with_registry_no_bp) chain_with_token_network_no_bp.identifiers_to_tokennetworkregistries[ token_network_registry_address].tokennetworkaddresses_to_tokennetworks[ token_network_address] = TokenNetworkState( address=token_network_address, token_address=token_address, network_graph=TokenNetworkGraphState(token_network_address), ) assert empty( detect_balance_proof_change( empty_chain, chain_with_token_network_no_bp)), MSG_NO_CHANGE assert empty( detect_balance_proof_change( chain_with_registry_no_bp, chain_with_token_network_no_bp)), MSG_NO_CHANGE assert empty( detect_balance_proof_change( chain_with_token_network_no_bp, deepcopy(chain_with_token_network_no_bp))), MSG_NO_CHANGE partner_address = make_address() canonical_identifier = make_canonical_identifier() channel_no_bp = NettingChannelState( canonical_identifier=canonical_identifier, token_address=token_address, token_network_registry_address=token_network_registry_address, reveal_timeout=1, settle_timeout=2, our_state=NettingChannelEndState(address=our_address, contract_balance=1), partner_state=NettingChannelEndState(address=partner_address, contract_balance=0), open_transaction=TransactionExecutionStatus(result="success"), settle_transaction=None, update_transaction=None, close_transaction=None, fee_schedule=FeeScheduleState(), ) chain_with_channel_no_bp = deepcopy(chain_with_token_network_no_bp) chain_with_token_network_no_bp.identifiers_to_tokennetworkregistries[ token_network_registry_address].tokennetworkaddresses_to_tokennetworks[ token_network_address].channelidentifiers_to_channels[ canonical_identifier.channel_identifier] = channel_no_bp assert empty( detect_balance_proof_change(empty_chain, chain_with_channel_no_bp)), MSG_NO_CHANGE assert empty( detect_balance_proof_change(chain_with_registry_no_bp, chain_with_channel_no_bp)), MSG_NO_CHANGE assert empty( detect_balance_proof_change(chain_with_token_network_no_bp, chain_with_channel_no_bp)), MSG_NO_CHANGE assert empty( detect_balance_proof_change( chain_with_channel_no_bp, deepcopy(chain_with_channel_no_bp))), MSG_NO_CHANGE channel_with_sent_bp = deepcopy(channel_no_bp) channel_with_sent_bp.our_state.balance_proof = create( BalanceProofUnsignedState) chain_with_sent_bp = deepcopy(chain_with_token_network_no_bp) chain_with_sent_bp.identifiers_to_tokennetworkregistries[ token_network_registry_address].tokennetworkaddresses_to_tokennetworks[ token_network_address].channelidentifiers_to_channels[ canonical_identifier.channel_identifier] = channel_with_sent_bp assert not empty( detect_balance_proof_change( empty_chain, chain_with_sent_bp)), MSG_BALANCE_PROOF_SHOULD_BE_DETECTED assert not empty( detect_balance_proof_change( chain_with_registry_no_bp, chain_with_sent_bp)), MSG_BALANCE_PROOF_SHOULD_BE_DETECTED assert not empty( detect_balance_proof_change( chain_with_token_network_no_bp, chain_with_sent_bp)), MSG_BALANCE_PROOF_SHOULD_BE_DETECTED assert not empty( detect_balance_proof_change( chain_with_channel_no_bp, chain_with_sent_bp)), MSG_BALANCE_PROOF_SHOULD_BE_DETECTED assert empty( detect_balance_proof_change( chain_with_sent_bp, deepcopy(chain_with_sent_bp))), MSG_NO_CHANGE channel_with_received_bp = deepcopy(channel_no_bp) channel_with_received_bp.partner_state.balance_proof = create( BalanceProofUnsignedState) chain_with_received_bp = deepcopy(chain_with_token_network_no_bp) chain_with_received_bp.identifiers_to_tokennetworkregistries[ token_network_registry_address].tokennetworkaddresses_to_tokennetworks[ token_network_address].channelidentifiers_to_channels[ canonical_identifier.channel_identifier] = channel_with_sent_bp # asserting with `channel_with_received_bp` and `channel_with_sent_bp` # doesn't make sense, because one of the balance proofs would have to # disappear (which is a bug) assert not empty( detect_balance_proof_change( empty_chain, chain_with_received_bp)), MSG_BALANCE_PROOF_SHOULD_BE_DETECTED assert not empty( detect_balance_proof_change( chain_with_registry_no_bp, chain_with_received_bp)), MSG_BALANCE_PROOF_SHOULD_BE_DETECTED assert not empty( detect_balance_proof_change( chain_with_token_network_no_bp, chain_with_received_bp)), MSG_BALANCE_PROOF_SHOULD_BE_DETECTED assert not empty( detect_balance_proof_change( chain_with_channel_no_bp, chain_with_received_bp)), MSG_BALANCE_PROOF_SHOULD_BE_DETECTED assert empty( detect_balance_proof_change( chain_with_received_bp, deepcopy(chain_with_received_bp))), MSG_NO_CHANGE chain_with_sent_and_received_bp = deepcopy(chain_with_token_network_no_bp) ta_to_tn = chain_with_sent_and_received_bp.identifiers_to_tokennetworkregistries channel_with_sent_and_recived_bp = ( ta_to_tn[token_network_registry_address]. tokennetworkaddresses_to_tokennetworks[token_network_address]. channelidentifiers_to_channels[canonical_identifier.channel_identifier] ) channel_with_sent_and_recived_bp.partner_state.balance_proof = deepcopy( channel_with_received_bp.partner_state.balance_proof) channel_with_sent_and_recived_bp.our_state.balance_proof = deepcopy( channel_with_received_bp.our_state.balance_proof) assert not empty( detect_balance_proof_change(empty_chain, chain_with_sent_and_received_bp) ), MSG_BALANCE_PROOF_SHOULD_BE_DETECTED assert not empty( detect_balance_proof_change(chain_with_registry_no_bp, chain_with_sent_and_received_bp) ), MSG_BALANCE_PROOF_SHOULD_BE_DETECTED assert not empty( detect_balance_proof_change(chain_with_token_network_no_bp, chain_with_sent_and_received_bp) ), MSG_BALANCE_PROOF_SHOULD_BE_DETECTED assert not empty( detect_balance_proof_change(chain_with_channel_no_bp, chain_with_sent_and_received_bp) ), MSG_BALANCE_PROOF_SHOULD_BE_DETECTED assert not empty( detect_balance_proof_change(chain_with_received_bp, chain_with_sent_and_received_bp) ), MSG_BALANCE_PROOF_SHOULD_BE_DETECTED assert not empty( detect_balance_proof_change(chain_with_sent_bp, chain_with_sent_and_received_bp) ), MSG_BALANCE_PROOF_SHOULD_BE_DETECTED assert empty( detect_balance_proof_change( chain_with_sent_and_received_bp, deepcopy(chain_with_sent_and_received_bp))), MSG_NO_CHANGE
def get_channel_state( token_address: TokenAddress, payment_network_identifier: PaymentNetworkID, token_network_address: TokenNetworkAddress, reveal_timeout: BlockTimeout, payment_channel_proxy, opened_block_number: BlockNumber, ): # Here we have to query the latest state because if we query with an older block # state (e.g. opened_block_number) the state may have been pruned which will # lead to an error. latest_block_hash = payment_channel_proxy.client.blockhash_from_blocknumber( "latest") channel_details = payment_channel_proxy.detail(latest_block_hash) our_state = NettingChannelEndState( channel_details.participants_data.our_details.address, channel_details.participants_data.our_details.deposit, ) partner_state = NettingChannelEndState( channel_details.participants_data.partner_details.address, channel_details.participants_data.partner_details.deposit, ) identifier = payment_channel_proxy.channel_identifier settle_timeout = payment_channel_proxy.settle_timeout() closed_block_number = payment_channel_proxy.close_block_number() # ignore bad open block numbers if opened_block_number <= 0: return None open_transaction = TransactionExecutionStatus( None, opened_block_number, TransactionExecutionStatus.SUCCESS) close_transaction: Optional[TransactionExecutionStatus] = None if closed_block_number: close_transaction = TransactionExecutionStatus( None, closed_block_number, TransactionExecutionStatus.SUCCESS) # For the current implementation the channel is a smart contract that # will be killed on settle. settle_transaction = None channel = NettingChannelState( canonical_identifier=CanonicalIdentifier( chain_identifier=channel_details.chain_id, token_network_address=token_network_address, channel_identifier=identifier, ), token_address=token_address, payment_network_identifier=payment_network_identifier, reveal_timeout=reveal_timeout, settle_timeout=settle_timeout, mediation_fee=MEDIATION_FEE, our_state=our_state, partner_state=partner_state, open_transaction=open_transaction, close_transaction=close_transaction, settle_transaction=settle_transaction, ) return channel
def test_detect_balance_proof_change(): prng = random.Random() block_hash = factories.make_block_hash() old = ChainState( pseudo_random_generator=prng, block_number=1, block_hash=block_hash, our_address=2, chain_id=3, ) new = ChainState( pseudo_random_generator=prng, block_number=1, block_hash=block_hash, our_address=2, chain_id=3, ) def diff(): return list(detect_balance_proof_change(old, new)) assert len(diff()) == 0 payment_network = PaymentNetworkState(b'x', []) payment_network_copy = deepcopy(payment_network) new.identifiers_to_paymentnetworks['a'] = payment_network assert len(diff()) == 0 token_network = TokenNetworkState(b'a', b'a') token_network_copy = deepcopy(token_network) payment_network.tokenidentifiers_to_tokennetworks['a'] = token_network assert len(diff()) == 0 channel = NettingChannelState( canonical_identifier=factories.make_canonical_identifier(), token_address=b'a', payment_network_identifier=1, reveal_timeout=1, settle_timeout=2, mediation_fee=0, our_state=None, partner_state=None, open_transaction=TransactionExecutionStatus(result='success'), settle_transaction=None, update_transaction=None, close_transaction=None, ) channel_copy = deepcopy(channel) token_network.channelidentifiers_to_channels['a'] = channel our_state = NettingChannelEndState(address=b'b', balance=1) our_state_copy = deepcopy(our_state) partner_state = NettingChannelEndState(address=b'a', balance=0) partner_state_copy = deepcopy(partner_state) channel.our_state = our_state channel.partner_state = partner_state assert len(diff()) == 0 balance_proof = object() partner_state.balance_proof = balance_proof assert len(diff()) == 1 old.identifiers_to_paymentnetworks['a'] = payment_network_copy assert len(diff()) == 1 payment_network_copy.tokenidentifiers_to_tokennetworks[ 'a'] = token_network_copy assert len(diff()) == 1 token_network_copy.channelidentifiers_to_channels['a'] = channel_copy channel_copy.partner_state = partner_state_copy assert len(diff()) == 1 channel_copy.partner_state.balance_proof = balance_proof assert len(diff()) == 0 channel_copy.partner_state.balance_proof = object() assert len(diff()) == 1 assert diff() == [balance_proof] # check our_state BP changes channel_copy.partner_state.balance_proof = balance_proof assert len(diff()) == 0 channel.our_state.balance_proof = object() channel_copy.our_state = our_state_copy assert len(diff()) == 1 assert diff() == [channel.our_state.balance_proof] channel_copy.our_state.balance_proof = channel.our_state.balance_proof assert len(diff()) == 0
def get_channel_state( token_address, payment_network_identifier, token_network_address, reveal_timeout, payment_channel_proxy, opened_block_number, ): # LEFTODO: Supply a proper block id channel_details = payment_channel_proxy.detail('latest') our_state = NettingChannelEndState( channel_details.participants_data.our_details.address, channel_details.participants_data.our_details.deposit, ) partner_state = NettingChannelEndState( channel_details.participants_data.partner_details.address, channel_details.participants_data.partner_details.deposit, ) identifier = payment_channel_proxy.channel_identifier settle_timeout = payment_channel_proxy.settle_timeout() closed_block_number = payment_channel_proxy.close_block_number() # ignore bad open block numbers if opened_block_number <= 0: return None open_transaction = TransactionExecutionStatus( None, opened_block_number, TransactionExecutionStatus.SUCCESS, ) if closed_block_number: close_transaction = TransactionExecutionStatus( None, closed_block_number, TransactionExecutionStatus.SUCCESS, ) else: close_transaction = None # For the current implementation the channel is a smart contract that # will be killed on settle. settle_transaction = None channel = NettingChannelState( identifier=identifier, chain_id=channel_details.chain_id, token_address=token_address, payment_network_identifier=payment_network_identifier, token_network_identifier=token_network_address, reveal_timeout=reveal_timeout, settle_timeout=settle_timeout, our_state=our_state, partner_state=partner_state, open_transaction=open_transaction, close_transaction=close_transaction, settle_transaction=settle_transaction, ) return channel
def update_contract_balance( end_state: NettingChannelEndState, contract_balance: typing.Balance, ) -> None: if contract_balance > end_state.contract_balance: end_state.contract_balance = contract_balance
def test_payment_channel_proxy_basics( token_network_registry_address: TokenNetworkRegistryAddress, token_network_proxy: TokenNetwork, token_proxy: Token, chain_id: ChainID, private_keys: List[PrivateKey], web3: Web3, contract_manager: ContractManager, reveal_timeout: BlockTimeout, ) -> None: token_network_address = token_network_proxy.address partner = privatekey_to_address(private_keys[0]) rpc_client = JSONRPCClient(web3, private_keys[1]) proxy_manager = ProxyManager( rpc_client=rpc_client, contract_manager=contract_manager, metadata=ProxyManagerMetadata( token_network_registry_deployed_at=GENESIS_BLOCK_NUMBER, filters_start_at=GENESIS_BLOCK_NUMBER, ), ) token_network_proxy = proxy_manager.token_network( address=token_network_address, block_identifier=BLOCK_ID_LATEST ) start_block = web3.eth.blockNumber channel_details = token_network_proxy.new_netting_channel( partner=partner, settle_timeout=TEST_SETTLE_TIMEOUT_MIN, given_block_identifier=BLOCK_ID_LATEST, ) channel_identifier = channel_details.channel_identifier assert channel_identifier is not None channel_state = NettingChannelState( canonical_identifier=CanonicalIdentifier( chain_identifier=chain_id, token_network_address=token_network_address, channel_identifier=channel_identifier, ), token_address=token_network_proxy.token_address(), token_network_registry_address=token_network_registry_address, reveal_timeout=reveal_timeout, settle_timeout=BlockTimeout(TEST_SETTLE_TIMEOUT_MIN), fee_schedule=FeeScheduleState(), our_state=NettingChannelEndState( address=token_network_proxy.client.address, contract_balance=Balance(0) ), partner_state=NettingChannelEndState(address=partner, contract_balance=Balance(0)), open_transaction=SuccessfulTransactionState(finished_block_number=BlockNumber(0)), ) channel_proxy_1 = proxy_manager.payment_channel( channel_state=channel_state, block_identifier=BLOCK_ID_LATEST ) assert channel_proxy_1.channel_identifier == channel_identifier assert channel_proxy_1.opened(BLOCK_ID_LATEST) is True # Test deposit initial_token_balance = 100 token_proxy.transfer(rpc_client.address, TokenAmount(initial_token_balance)) assert token_proxy.balance_of(rpc_client.address) == initial_token_balance assert token_proxy.balance_of(partner) == 0 channel_proxy_1.approve_and_set_total_deposit( total_deposit=TokenAmount(10), block_identifier=BLOCK_ID_LATEST ) # ChannelOpened, ChannelNewDeposit channel_events = get_all_netting_channel_events( proxy_manager=proxy_manager, token_network_address=token_network_address, netting_channel_identifier=channel_proxy_1.channel_identifier, contract_manager=contract_manager, from_block=start_block, to_block=web3.eth.blockNumber, ) assert len(channel_events) == 2 block_before_close = web3.eth.blockNumber empty_balance_proof = BalanceProof( channel_identifier=channel_proxy_1.channel_identifier, token_network_address=token_network_address, balance_hash=EMPTY_BALANCE_HASH, nonce=0, chain_id=chain_id, transferred_amount=TokenAmount(0), ) closing_data = ( empty_balance_proof.serialize_bin(msg_type=MessageTypeId.BALANCE_PROOF) + EMPTY_SIGNATURE ) channel_proxy_1.close( nonce=Nonce(0), balance_hash=EMPTY_BALANCE_HASH, additional_hash=EMPTY_MESSAGE_HASH, non_closing_signature=EMPTY_SIGNATURE, closing_signature=LocalSigner(private_keys[1]).sign(data=closing_data), block_identifier=BLOCK_ID_LATEST, ) assert channel_proxy_1.closed(BLOCK_ID_LATEST) is True # ChannelOpened, ChannelNewDeposit, ChannelClosed channel_events = get_all_netting_channel_events( proxy_manager=proxy_manager, token_network_address=token_network_address, netting_channel_identifier=channel_proxy_1.channel_identifier, contract_manager=contract_manager, from_block=start_block, to_block=web3.eth.blockNumber, ) assert len(channel_events) == 3 # check the settlement timeouts again assert channel_proxy_1.settle_timeout() == TEST_SETTLE_TIMEOUT_MIN # update transfer -- we need to wait on +1 since we use the latest block on parity for # estimate gas and at the time the latest block is the settle timeout block. # More info: https://github.com/raiden-network/raiden/pull/3699#discussion_r270477227 rpc_client.wait_until_block( target_block_number=BlockNumber(rpc_client.block_number() + TEST_SETTLE_TIMEOUT_MIN + 1) ) transaction_hash = channel_proxy_1.settle( transferred_amount=TokenAmount(0), locked_amount=LockedAmount(0), locksroot=LOCKSROOT_OF_NO_LOCKS, partner_transferred_amount=TokenAmount(0), partner_locked_amount=LockedAmount(0), partner_locksroot=LOCKSROOT_OF_NO_LOCKS, block_identifier=BLOCK_ID_LATEST, ) assert is_tx_hash_bytes(transaction_hash) assert channel_proxy_1.settled(BLOCK_ID_LATEST) is True # ChannelOpened, ChannelNewDeposit, ChannelClosed, ChannelSettled channel_events = get_all_netting_channel_events( proxy_manager=proxy_manager, token_network_address=token_network_address, netting_channel_identifier=channel_proxy_1.channel_identifier, contract_manager=contract_manager, from_block=start_block, to_block=web3.eth.blockNumber, ) assert len(channel_events) == 4 channel_details = token_network_proxy.new_netting_channel( partner=partner, settle_timeout=TEST_SETTLE_TIMEOUT_MIN, given_block_identifier=BLOCK_ID_LATEST, ) new_channel_identifier = channel_details.channel_identifier assert new_channel_identifier is not None channel_state = NettingChannelState( canonical_identifier=CanonicalIdentifier( chain_identifier=chain_id, token_network_address=token_network_address, channel_identifier=new_channel_identifier, ), token_address=token_network_proxy.token_address(), token_network_registry_address=token_network_registry_address, reveal_timeout=reveal_timeout, settle_timeout=BlockTimeout(TEST_SETTLE_TIMEOUT_MIN), fee_schedule=FeeScheduleState(), our_state=NettingChannelEndState( address=token_network_proxy.client.address, contract_balance=Balance(0) ), partner_state=NettingChannelEndState(address=partner, contract_balance=Balance(0)), open_transaction=SuccessfulTransactionState(finished_block_number=BlockNumber(0)), ) channel_proxy_2 = proxy_manager.payment_channel( channel_state=channel_state, block_identifier=BLOCK_ID_LATEST ) assert channel_proxy_2.channel_identifier == new_channel_identifier assert channel_proxy_2.opened(BLOCK_ID_LATEST) is True msg = "The channel was already closed, the second call must fail" with pytest.raises(RaidenRecoverableError): channel_proxy_1.close( nonce=Nonce(0), balance_hash=EMPTY_BALANCE_HASH, additional_hash=EMPTY_MESSAGE_HASH, non_closing_signature=EMPTY_SIGNATURE, closing_signature=LocalSigner(private_keys[1]).sign(data=closing_data), block_identifier=block_before_close, ) pytest.fail(msg) msg = "The channel is not open at latest, this must raise" with pytest.raises(RaidenUnrecoverableError): channel_proxy_1.close( nonce=Nonce(0), balance_hash=EMPTY_BALANCE_HASH, additional_hash=EMPTY_MESSAGE_HASH, non_closing_signature=EMPTY_SIGNATURE, closing_signature=LocalSigner(private_keys[1]).sign(data=closing_data), block_identifier=BLOCK_ID_LATEST, ) pytest.fail(msg) msg = ( "The channel was not opened at the provided block (latest). " "This call should never have been attempted." ) with pytest.raises(BrokenPreconditionError): channel_proxy_1.approve_and_set_total_deposit( total_deposit=TokenAmount(20), block_identifier=BLOCK_ID_LATEST ) pytest.fail(msg)