Refactor states update
This commit is contained in:
parent
1f154ce4e6
commit
eb1ce0bfc9
@ -174,28 +174,46 @@ impl Process {
|
||||
Ok(last_state.commited_in)
|
||||
}
|
||||
|
||||
/// We want to always keep an empty state with only the latest unspent commited_in value at the last position
|
||||
pub fn insert_state(&mut self, prd_update: &Prd) -> anyhow::Result<()> {
|
||||
if prd_update.prd_type != PrdType::Update { return Err(anyhow::Error::msg("Only update prd allowed")) }
|
||||
pub fn update_states_tip(&mut self, new_commitment: OutPoint) -> anyhow::Result<()> {
|
||||
if self.states.is_empty() { return Err(anyhow::Error::msg("Empty Process")); }
|
||||
let new_encrypted_pcd: Value = serde_json::from_str(&prd_update.payload).unwrap();
|
||||
let last_index = self.states.len() - 1;
|
||||
let last_value = self.states.get(last_index).unwrap();
|
||||
if last_value.encrypted_pcd != Value::Null ||
|
||||
last_value.keys != Map::new() ||
|
||||
last_value.pcd_commitment != Value::Null ||
|
||||
last_value.validation_tokens != vec![]
|
||||
{
|
||||
return Err(anyhow::Error::msg("Last state is not empty"));
|
||||
let last_value = self.states.last().unwrap();
|
||||
if !last_value.is_empty() {
|
||||
return Err(anyhow::Error::msg("Last value should be empty"));
|
||||
}
|
||||
let empty_state = self.states.remove(last_index);
|
||||
let new_state = ProcessState {
|
||||
commited_in: empty_state.commited_in,
|
||||
pcd_commitment: prd_update.pcd_commitments.clone(),
|
||||
encrypted_pcd: new_encrypted_pcd,
|
||||
keys: prd_update.keys.clone(),
|
||||
validation_tokens: vec![]
|
||||
if last_value.commited_in == new_commitment {
|
||||
return Err(anyhow::Error::msg("new_commitment is the same than existing tip"));
|
||||
}
|
||||
|
||||
// Before updating we make sure that we only have one concurrent state
|
||||
let concurrent_states = self.get_latest_concurrent_states()?;
|
||||
if concurrent_states.len() != 2 {
|
||||
return Err(anyhow::Error::msg("We must have exactly one state for the current tip"));
|
||||
}
|
||||
|
||||
// Replace the existing tip
|
||||
let new_tip = ProcessState {
|
||||
commited_in: new_commitment,
|
||||
..Default::default()
|
||||
};
|
||||
let _ = self.states.pop().unwrap();
|
||||
self.states.push(new_tip);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// We want to insert a new state that would be commited by the last UTXO
|
||||
/// The new state *must* have the same commited_in than the last empty one
|
||||
/// We want to always keep an empty state with only the latest unspent commited_in value at the last position
|
||||
pub fn insert_concurrent_state(&mut self, new_state: ProcessState) -> anyhow::Result<()> {
|
||||
if self.states.is_empty() { return Err(anyhow::Error::msg("Empty Process")); }
|
||||
let last_value = self.states.last().unwrap();
|
||||
if !last_value.is_empty() {
|
||||
return Err(anyhow::Error::msg("Last value should be empty"));
|
||||
}
|
||||
if last_value.commited_in != new_state.commited_in {
|
||||
return Err(anyhow::Error::msg("A concurrent state must have the same commited in than the tip of the states"));
|
||||
}
|
||||
let empty_state = self.states.pop().unwrap();
|
||||
self.states.push(new_state);
|
||||
// We always keep an empty state at the end
|
||||
self.states.push(empty_state);
|
||||
@ -281,36 +299,22 @@ impl Process {
|
||||
Ok(states)
|
||||
}
|
||||
|
||||
pub fn remove_latest_concurrent_states(&mut self) -> anyhow::Result<Vec<ProcessState>> {
|
||||
pub fn remove_all_concurrent_states(&mut self) -> anyhow::Result<Vec<ProcessState>> {
|
||||
if self.get_number_of_states() == 0 {
|
||||
// This should never happen, but we better get rid of it now
|
||||
return Err(anyhow::Error::msg("process is empty".to_owned()));
|
||||
}
|
||||
|
||||
let mut previous_commited_in = OutPoint::null();
|
||||
// Iterate backwards, find the reverse position, and adjust to forward position
|
||||
let reverse_position = self.states.iter().rev().position(|state| {
|
||||
if previous_commited_in == OutPoint::null() {
|
||||
previous_commited_in = state.commited_in;
|
||||
false // Continue iterating
|
||||
} else if previous_commited_in != state.commited_in {
|
||||
true // Stop when a different commited_in is found
|
||||
} else {
|
||||
false // Continue iterating
|
||||
}
|
||||
});
|
||||
let empty_state = self.states.pop().unwrap();
|
||||
let last_commitment_outpoint = empty_state.commited_in;
|
||||
let split_index = self.states.iter().position(|state| state.commited_in == last_commitment_outpoint).unwrap();
|
||||
|
||||
let forward_position = reverse_position.map(|pos| self.states.len() - pos - 1);
|
||||
let removed = self.states.split_off(split_index);
|
||||
|
||||
match forward_position {
|
||||
Some(pos) => Ok(self.states.split_off(pos)),
|
||||
None => {
|
||||
// We take everything out
|
||||
let res = self.states.to_vec();
|
||||
self.states = vec![];
|
||||
Ok(res)
|
||||
}
|
||||
}
|
||||
// We make sure we always have an empty state at the end
|
||||
self.states.push(empty_state);
|
||||
|
||||
Ok(removed)
|
||||
}
|
||||
|
||||
pub fn get_latest_commited_state(&self) -> Option<&ProcessState> {
|
||||
@ -379,8 +383,7 @@ mod tests {
|
||||
|
||||
use serde_json::json;
|
||||
use sp_client::{
|
||||
bitcoin::{secp256k1::SecretKey, Network},
|
||||
spclient::{SpClient, SpWallet, SpendKey},
|
||||
bitcoin::{secp256k1::SecretKey, Network}, silentpayments::utils::SilentPaymentAddress, spclient::{SpClient, SpWallet, SpendKey}
|
||||
};
|
||||
|
||||
use crate::pcd::{Member, ValidationRule};
|
||||
|
Loading…
x
Reference in New Issue
Block a user