Skip to content

Commit

Permalink
include and forward encrypted secret in locked transfer message
Browse files Browse the repository at this point in the history
  • Loading branch information
Fernando Cezar Bernardelli committed Jul 29, 2021
1 parent 5099979 commit 32c55c7
Show file tree
Hide file tree
Showing 3 changed files with 112 additions and 67 deletions.
11 changes: 10 additions & 1 deletion raiden/message_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from gevent.pool import Pool

from raiden.constants import ABSENT_SECRET, BLOCK_ID_LATEST
from raiden.exceptions import ServiceRequestFailed
from raiden.exceptions import InvalidSecret, ServiceRequestFailed
from raiden.messages.abstract import Message
from raiden.messages.decode import balanceproof_from_envelope, lockedtransfersigned_from_message
from raiden.messages.synchronization import Delivered, Processed
Expand Down Expand Up @@ -40,6 +40,7 @@
ReceiveWithdrawExpired,
ReceiveWithdrawRequest,
)
from raiden.transfer.utils import decrypt_secret
from raiden.transfer.views import TransferRole
from raiden.utils.transfers import random_secret
from raiden.utils.typing import (
Expand Down Expand Up @@ -338,6 +339,14 @@ def handle_message_lockedtransfer(
sender = from_transfer.balance_proof.sender

if message.target == TargetAddress(raiden.address):
encrypted_secret = message.metadata.encrypted_secret
if encrypted_secret is not None:
try:
secret = decrypt_secret(encrypted_secret, raiden.rpc_client.privkey)
log.info(f"Using encrypted secret received from {sender.hex()}")
return [ReceiveSecretReveal(secret=secret, sender=message.sender)]
except InvalidSecret:
log.error(f"Ignoring invalid encrypted secret received from {sender.hex()}")
return [
ActionInitTarget(
from_hop=from_hop,
Expand Down
143 changes: 80 additions & 63 deletions raiden/transfer/channel.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@
ReceiveWithdrawExpired,
ReceiveWithdrawRequest,
)
from raiden.transfer.utils import hash_balance_data
from raiden.transfer.utils import FuncMap, hash_balance_data
from raiden.utils.formatting import to_checksum_address
from raiden.utils.packing import pack_balance_proof, pack_withdraw
from raiden.utils.signer import recover
Expand Down Expand Up @@ -2548,68 +2548,85 @@ def state_transition(
channel_state, events
)

if type(state_change) == Block:
assert isinstance(state_change, Block), MYPY_ANNOTATION
iteration = handle_block(
channel_state, state_change, block_number, pseudo_random_generator
)
elif type(state_change) == ActionChannelClose:
assert isinstance(state_change, ActionChannelClose), MYPY_ANNOTATION
iteration = handle_action_close(
channel_state=channel_state,
close=state_change,
block_number=block_number,
block_hash=block_hash,
)
elif type(state_change) == ActionChannelWithdraw:
assert isinstance(state_change, ActionChannelWithdraw), MYPY_ANNOTATION
iteration = handle_action_withdraw(
channel_state=channel_state,
action_withdraw=state_change,
pseudo_random_generator=pseudo_random_generator,
block_number=block_number,
)
elif type(state_change) == ActionChannelSetRevealTimeout:
assert isinstance(state_change, ActionChannelSetRevealTimeout), MYPY_ANNOTATION
iteration = handle_action_set_reveal_timeout(
channel_state=channel_state, state_change=state_change
)
elif type(state_change) == ContractReceiveChannelClosed:
assert isinstance(state_change, ContractReceiveChannelClosed), MYPY_ANNOTATION
iteration = handle_channel_closed(channel_state, state_change)
elif type(state_change) == ContractReceiveUpdateTransfer:
assert isinstance(state_change, ContractReceiveUpdateTransfer), MYPY_ANNOTATION
iteration = handle_channel_updated_transfer(channel_state, state_change, block_number)
elif type(state_change) == ContractReceiveChannelSettled:
assert isinstance(state_change, ContractReceiveChannelSettled), MYPY_ANNOTATION
iteration = handle_channel_settled(channel_state, state_change)
elif type(state_change) == ContractReceiveChannelDeposit:
assert isinstance(state_change, ContractReceiveChannelDeposit), MYPY_ANNOTATION
iteration = handle_channel_deposit(channel_state, state_change)
elif type(state_change) == ContractReceiveChannelBatchUnlock:
assert isinstance(state_change, ContractReceiveChannelBatchUnlock), MYPY_ANNOTATION
iteration = handle_channel_batch_unlock(channel_state, state_change)
elif type(state_change) == ContractReceiveChannelWithdraw:
assert isinstance(state_change, ContractReceiveChannelWithdraw), MYPY_ANNOTATION
iteration = handle_channel_withdraw(channel_state=channel_state, state_change=state_change)
elif type(state_change) == ReceiveWithdrawRequest:
assert isinstance(state_change, ReceiveWithdrawRequest), MYPY_ANNOTATION
iteration = handle_receive_withdraw_request(
channel_state=channel_state, withdraw_request=state_change
)
elif type(state_change) == ReceiveWithdrawConfirmation:
assert isinstance(state_change, ReceiveWithdrawConfirmation), MYPY_ANNOTATION
iteration = handle_receive_withdraw_confirmation(
channel_state=channel_state,
withdraw=state_change,
block_number=block_number,
block_hash=block_hash,
)
elif type(state_change) == ReceiveWithdrawExpired:
assert isinstance(state_change, ReceiveWithdrawExpired), MYPY_ANNOTATION
iteration = handle_receive_withdraw_expired(
channel_state=channel_state, withdraw_expired=state_change, block_number=block_number
)
transition_map: Dict[Any, FuncMap] = {
Block: FuncMap(
handle_block, (channel_state, state_change, block_number, pseudo_random_generator), {}
),
ActionChannelClose: FuncMap(
handle_action_close,
(),
dict(
channel_state=channel_state,
close=state_change,
block_number=block_number,
block_hash=block_hash,
),
),
ActionChannelWithdraw: FuncMap(
handle_action_withdraw,
(),
dict(
channel_state=channel_state,
action_withdraw=state_change,
pseudo_random_generator=pseudo_random_generator,
block_number=block_number,
),
),
ActionChannelSetRevealTimeout: FuncMap(
handle_action_set_reveal_timeout,
(),
dict(channel_state=channel_state, state_change=state_change),
),
ContractReceiveChannelClosed: FuncMap(
handle_channel_closed, (channel_state, state_change), {}
),
ContractReceiveUpdateTransfer: FuncMap(
handle_channel_updated_transfer, (channel_state, state_change, block_number), {}
),
ContractReceiveChannelSettled: FuncMap(
handle_channel_settled, (channel_state, state_change), {}
),
ContractReceiveChannelDeposit: FuncMap(
handle_channel_deposit, (channel_state, state_change), {}
),
ContractReceiveChannelBatchUnlock: FuncMap(
handle_channel_batch_unlock, (channel_state, state_change), {}
),
ContractReceiveChannelWithdraw: FuncMap(
handle_channel_withdraw,
(),
dict(channel_state=channel_state, state_change=state_change),
),
ReceiveWithdrawRequest: FuncMap(
handle_receive_withdraw_request,
(),
dict(channel_state=channel_state, withdraw_request=state_change),
),
ReceiveWithdrawConfirmation: FuncMap(
handle_receive_withdraw_confirmation,
(),
dict(
channel_state=channel_state,
withdraw=state_change,
block_number=block_number,
block_hash=block_hash,
),
),
ReceiveWithdrawExpired: FuncMap(
handle_receive_withdraw_expired,
(),
dict(
channel_state=channel_state,
withdraw_expired=state_change,
block_number=block_number,
),
),
}

t_state_change = type(state_change)
func_map = transition_map.get(t_state_change)
if func_map:
iteration = func_map.function(*func_map.args, **func_map.kwargs) # type: ignore

if iteration.new_state is not None:
sanity_check(iteration.new_state)
Expand Down
25 changes: 22 additions & 3 deletions raiden/transfer/utils.py
Original file line number Diff line number Diff line change
@@ -1,27 +1,31 @@
import random
from dataclasses import dataclass, field
from random import Random
from typing import TYPE_CHECKING

from ecies import encrypt
from ecies import decrypt, encrypt
from eth_hash.auto import keccak

from eth_utils import decode_hex

from raiden.constants import EMPTY_HASH, LOCKSROOT_OF_NO_LOCKS

from raiden.exceptions import InvalidSecret
from raiden.utils.signer import get_public_key
from raiden.utils.typing import (
AddressMetadata,
Any,
BalanceHash,
Callable,
Dict,
EncryptedSecret,
LockedAmount,
Locksroot,
Optional,
PrivateKey,
Secret,
SecretHash,
Signature,
TokenAmount,
Tuple,
Union,
)

Expand All @@ -31,6 +35,13 @@
from raiden.transfer.state_change import ContractReceiveSecretReveal # noqa: F401


@dataclass
class FuncMap:
function: Callable
args: Optional[Tuple] = field(default_factory=tuple)
kwargs: Optional[Dict[Any, Any]] = field(default_factory=dict)


def hash_balance_data(
transferred_amount: TokenAmount, locked_amount: LockedAmount, locksroot: Locksroot
) -> BalanceHash:
Expand Down Expand Up @@ -79,3 +90,11 @@ def encrypt_secret(
if public_key:
encrypted_secret = EncryptedSecret(encrypt(public_key.to_hex(), secret))
return encrypted_secret


def decrypt_secret(encrypted_secret: EncryptedSecret, private_key: PrivateKey) -> Secret:
try:
secret = Secret(decrypt(encrypted_secret, private_key))
except ValueError:
raise InvalidSecret
return secret

0 comments on commit 32c55c7

Please sign in to comment.