monorepo
monorepo copied to clipboard
[node] Investigate an optimal structure for the Node's plugin system
To be able to support more complicated types of state channel applications than just those which have a pure
EVM-compatible state transition function, the Node software must be able to be "extended" on a per-app basis to make decisions about whether it is valid to sign a new state or not.
This issue is to evaluate the current state of the Node software and to create an architectural diagram and written plan of attack for how we will extend the Node to support this required functionality.
Note: as the discussion around this feature progresses, this issue will be updated to reflect said progress
Summary
A plugin to the Node
is a class which defines how the Node
will react to installation and state proposal events for a particular App (defined by its appDefinitionAddr
). By registering a plugin you create a mapping from an App to functions onProposedInstall
and onProposedNewState
which the Node
will use for that App when given new installation requests and state updates respectively. The functions simply return boolean
values indicating whether or not the Node
should countersign a request for either of these events.
For example, in a payment channel app the onProposedInstall
function will verify that the aliceBalanceDecrement
and bobBalanceDecrement
fields of the InstallParams
map correctly to the aliceBalance
and bobBalance
values in the initialState
parameter of the InstallParams
. In the case of a newly proposed state, the onProposedNewState
method will determine if aliceBalance
(for the case of Alice) is greater in the new state than in the previously signed state.
TODO
- Write this interface inside of a class
- Explain where in the Node this plugin gets called
- Where does
onProposedNewState
get called
- Where does
- Explain implementation strategy
- Where does
onProposedInstall
get called
Node Plugin
Each plugin adheres to the following interface:
- PluginAppDefinitionAddress: `string`
// listen on & emit Node events
- constructor(pluginParams: Object);
- onProposedInstall(installParams): boolean;
- onProposedNewState(updateParams): boolean;
Open questions:
- what kind of access does a plugin have to the Node?
- where are plugins stored? we need a plugin registry
- Should there be an optional uninstall method on the plugin
- This means for example that the resolution timing could be overridden by the plugin to use different providers
- How does auto-challenging work via plugins? Could PISA functionality be implemented as a plugin?
This began as a spike (https://github.com/counterfactual/monorepo/pull/1495) where it lead to the realization that the expected functionality is slightly different than assumed: there needs to exist the functionality of securely installing an application (as opposed to blindly accepting an installation request) where securely is defined as verifying that the effect of the outcome of the initial state of an application maps to the correct payout of funds according to the deposits being betted by the parties towards said installation.
Therefore this issue leads to two other issues:
- Implementing a naive check for this security verification so that we have an MVP functionality of this in master. This is being worked on here
- Implement the above feature more generically in the node via a "plugin" mechanism (naming TBD, essentially this is a module that gets registered with the node to verify the security of an application)
More relevant insights: the above comment refers to one of two concepts that became more clear through the spike, which was initially termed as "outcome mapper" functionality.
This term came to be used because as of the recent change to the contracts using the interpreter paradigm (reference documentation goes here), outcomes of apps are the data that effectively decide the mapping that's applied to the funds allocated towards an app when the app is being uninstalled.
The second concept that was realized is the notion of determining of whether a state update for an app should be signed or not as determined by an external module that gets registered with the Node. More concretely, an app's state could be updated conditional based on some external data source. This data can come from a view function on a contract (and this contract's address would be specified as part of the app's installation params to be used for helping determine state progression) or this data can from another source such as an HTTP call. The main point being these "state signing plugins" would be JS code that's specified as part of an app's installation params to help with that specific app's state progression dynamic relevant to the channel participants.