Open fredo opened 3 years ago
Some analysis to move this forward:
ActionInitMediator -> mediator.handle_init( ) -> MediatorTransferState |
event | receiver | address from? | associated state |
---|---|---|---|---|
SendProcessed |
Initiator / prev. Hop | ActionInitMediator |
/ | |
SendLockedTransfer (forward) |
Target / next Hop | ActionInitMediator |
MediationPairState |
|
SendLockedTransfer (backward) |
Initiator / prev. Hop | MediationPairState |
MediationPairState |
ReceiveSecretReveal -> mediator.handle_offchain_secret_reveal( ) -> MediatorTransferState |
event | receiver | address from? | associated state |
---|---|---|---|---|
SendSecretReveal |
Target / next Hop | MediationPairState |
MediationPairState |
|
SendUnlock |
Initiator / prev. Hop | MediationPairState |
MediationPairState |
ReceiveUnlock -> mediator.handle_unlock( ) -> MediatorTransferState |
event | receiver | address from? | associated state |
---|---|---|---|---|
SendProcessed |
Initiator / prev. Hop Hop | MediationPairState |
MediationPairState |
This suggests that the payer/payee address-metadata should be memorized with the MediationPairState
.
Note that the overall metadata received with the lockedtransfer message is also attached in the MediatorTransferState.routes
.
The MediatorTransferState is present in all top-level handler functions mentioned above, so the metadata could also be passed down the call-chain from there.
Therefore, another possibility would be to only store the address metadata there, and just pass a mapping of all address -> metadata
to the functions in the layers below, where a lookup for the metadata can be performed on creation of SendMessageEvents
.
To summarise some ideas and plan on how to move forward, I gathered some information / ideas below. Some of this is already implemented or was already discussed, but here might be a good place to collect this information for further discussion and later retrieval.
The initial metadata is only retrieved / fed to the state-machine once, depending on the node's role:
For the Initiator, it is retrieved from the PFS and fed to the state-machine with the ActionInitInitiator
.
For the mediator, it is retrieved from a neighbouring nodes' LockedTransfer message as additional route-metadata and fed to the state-machine with theActionInitMediator
.
For the target, it is retrieved from a neighbouring nodes' LockedTransfer message as additional route-metadata and fed to the state-machine with theActionInitTarget
.
Since the address-metadata is bound to a payment, it would generally make sense to store the relevant metadata somewhere in the state that is bound to payments, namely:
InitiatorPaymentState
MediatorTransferState
TargetTransferState
In which sub-states (attributes of the above states) the metadata should be stored is a tradeoff between
simplicity on the state-side and the number of handler/send functions that have to be modified with an additional argument on the other side.
Especially the handler functions in the channel
module all need to be passed the address-metadata information as arguments from the payment-based handlers, since metadata is not supposed to be channel-bound, and therefore not available in the states passed to those functions.
I suggest the following:
The route-state will be modified to keep all address-metadata as provided by the pfs/ locked-transfer messages. The hop-state will be modified to keep the address metadata of the neighbouring sender of locked-transfers.
@dataclass
class RouteState(State):
route: List[Address]
address_to_metadata: Dict[Address, AddressMetadata] = field(default_factory=dict)
...
@dataclass
class HopState(State):
node_address: Address
channel_identifier: ChannelID
address_metadata: Optional[AddressMetadata] = None
Therefore the address-metadata will be persisted for the initiator in the InitiatorPaymentState.routes: List[RouteState]
,
and for the mediator will be persisted in the MediatorTransferState.routes: List[RouteState]
.
For the target, TargetTransferState.from_hop.address_metadata
will keep track of the neighbouring sender of the transfer,
while TargetTransferState.initiator_address_metadata
will keep track of the metadata of the initiator of the payment.
Since there can be some duplication of addresses in the metadata (the same hop/target can be part of multiple routes), the retrieval of neighbouring address-metadata (for the nodes own message sending) will be done by iterating over all address-metadata dictionaries and using the first metadata that is a key for the retrieved address.
This was implemented (with a little bit different architecture than planned) in #6906.
Currently the aforementioned non-time-critical messages (SendWithdrawRequest) do not explicitly query the PFS for a user, but hand messages to the transport without metadata. This results in sending to all possible user-ids for that address.
@fredo - regarding that, can we close this issue nevertheless or should we leave it open until a definite decision on this is made?
Overview
The interface to the transport module has changed such that each message gets enqueued with an
AddressMetadata
object. This object is supposed to be passed along the state machine in the classSendMessageEvent
. It has now a field calledrecipient_metadata
.For each message event we can now start to find out, if it is necessary and if yes, where these metadata should come from. It is possible to leave it
None
and the transport will still be able to process the message event. The fallback is sending it to all possible user_ids.As we currently agreed, it should be noticed that AddressMetadata are typically bound to payments. Therefore we need to be cautious where to store the metadata in the state.
How to analyze the Message event
As a hint, I suggest the following mechanism. Each message event has also the field
recipient
. In general, it might make sense to have a look where the recipient address comes from upon instantiation. Maybe metadata should be stored in the state where the recipient address is stored. Note, that it might not make sense for every message event type!I see three options how to get metadata:
Here is an example how metadata are passed with the recipient address in the case of
LockedTransfer
Additional information
WithdrawRequest
gets the recipient address from theNettingChannelState
. This is an example where I think it does not make sense to store the metadata along the recipient address asNettingChannelState
describes the current state of the channel and should not be mixed with payment bound information. Here it could make sense to request metadata from the PFS before the state change is applied (or created) and passed with it into the state machine or it might also make sense to leave it empty if it were too much effort to implement the former.MessageEvents