freenet / freenet-core

Declare your digital independence
https://freenet.org/
Apache License 2.0
2.27k stars 77 forks source link

Contract interaction #167

Closed sanity closed 2 years ago

sanity commented 2 years ago

Goal

Allow contracts to inspect the state of other contracts when deciding whether to validate their state or update it in response to a delta.

Approach

This approach treats update_state() like a consumer of UpdateData events, which can contain the state or delta for the current contract or related contracts as specified. The function may return when the state has been updated or request additional related contracts.

fn validate_state(
        _parameters: Parameters<'static>, 
        state: State<'static>,
        related: Map<ContractInstanceId, Option<State<'static>>>,
) -> ValidateResult

pub enum ValidateResult {
   Valid,
   Invalid,
   /// The peer will attempt to retrieve the requested contract states
   /// and will call validate_state() again when it retrieves them.
   RequestRelated(Vec<ContractInstanceId>),
}

// Delta validation is a simple spam prevention mechanism, supporting
// related contracts for this would be overkill
fn validate_delta(
        _parameters: Parameters<'static>, 
        state: Delta<'static>,
) -> bool

/// Called every time one or more UpdateDatas are received,
/// can update state and/or volatile memory in response
fn update_state(
    data: Vec<UpdateData>,
  parameters: Parameters<'static>,
  state: State<'static>,
) -> UpdateResult 

pub enum UpdateData {
  State(Vec<u8>),
  Delta(Vec<u8>),
  StateAndDelta { state : UpdateData::State, delta : UpdateData::Delta },
  RelatedState { relatedTo: ContractInstanceId, state : UpdateData::State },
  RelatedDelta { relatedTo : ContractInstanceId, delta : UpdateData::Delta },
  RelatedStateAndDelta { 
     relatedTo : ContractInstanceId, 
     state : UpdateData::State, 
     delta : UpdateData::Delta,
   },
}

pub struct UpdateResult {
    new_state : Option<State<'static>>,
    related : Vec<Related>,
}

pub struct Related {
    contract_instance_id : ContractInstanceId,
    mode : RelatedMode,
}

pub enum RelatedMode {
  /// Retrieve the state once, not concerned with
  /// subsequent changes
  StateOnce,

  /// Retrieve the state once, and then supply
  /// deltas from then on. More efficient.
  StateOnceThenDeltas,

  /// Retrieve the state and then provide new states
  /// every time it updates.
  StateEvery,

  StateThenStateAndDeltas,
}
iduartgomez commented 2 years ago

Note to self: Map<Contract, Option<State>> is a type that the node and the contract can understand through some means (initially the easiest way by it being de/serializable) so the contracts can communicate the node the requirements needed to run a contract.

sanity commented 2 years ago

There is a related proposal: #245

The difference is that the interdependent contracts mechanism has no way to ensure that the other contracts are processed accurately. This limits how they can be safely used to usecases like spam prevention. In a nutshell, this means that we can look at the state of other contracts to decide whether a state update should be applied to this contract or ignored. This is ok because the damage that can be done by the node misbehaving will be limited to this node.

245 describes a higher level system that includes verification and reputation to ensure accuracy.

This proposal probably needs to be reworked to account for this.

sanity commented 2 years ago

Discussion with @iduartgomez: we should go with the more flexible approach until we identify specific ways it can be abused

sanity commented 2 years ago

I've made this change.

sanity commented 2 years ago

What happens if a contract gets a state update but ignores it due to the state of another contract, but then a short amount of time later the state of the other contract changes?

To reduce the sensitivity to the order in which state changes are received, it may make sense to call the contract methods again if the state of a related contract changes soon after a previous change.

sanity commented 2 years ago

Rewrite API, new approach.

sanity commented 2 years ago

Remove volatile memory per discussion with @iduartgomez

sanity commented 2 years ago

Added StateAndDeltas mode.