Skip to content

Commit

Permalink
treat negative desposits as zero
Browse files Browse the repository at this point in the history
  • Loading branch information
OlofBlomqvist committed Jun 25, 2023
1 parent 16460df commit fb6aea2
Show file tree
Hide file tree
Showing 6 changed files with 374 additions and 40 deletions.
4 changes: 2 additions & 2 deletions src/lib/extras/js.rs
Original file line number Diff line number Diff line change
Expand Up @@ -387,7 +387,7 @@ impl WASMMarloweStateMachine {
}

#[wasm_bindgen]
pub fn apply_input_deposit_for_role(&mut self,from_role:&str,to_role:&str,token_name:&str,currency_symbol:&str,quantity:u64) {
pub fn apply_input_deposit_for_role(&mut self,from_role:&str,to_role:&str,token_name:&str,currency_symbol:&str,quantity:i64) {
let asset = Token {
currency_symbol: currency_symbol.into(),
token_name: token_name.into()
Expand All @@ -399,7 +399,7 @@ impl WASMMarloweStateMachine {
}

#[wasm_bindgen]
pub fn apply_input_deposit_for_addr(&mut self,from_bech32_addr:&str,to_bech32_addr:&str,token_name:&str,currency_symbol:&str,quantity:u64) {
pub fn apply_input_deposit_for_addr(&mut self,from_bech32_addr:&str,to_bech32_addr:&str,token_name:&str,currency_symbol:&str,quantity:i64) {
let asset = Token {
currency_symbol: currency_symbol.into(),
token_name: token_name.into()
Expand Down
49 changes: 31 additions & 18 deletions src/lib/semantics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ pub enum InputType {
Deposit {
who_is_expected_to_pay:Party ,
expected_asset_type: Token,
expected_amount: u64,
expected_amount: i64,
expected_target_account:crate::types::marlowe::AccountId,
continuation: Contract
},
Expand Down Expand Up @@ -120,7 +120,7 @@ pub trait ContractSemantics<T> {
fn apply_input_choice(&self,applied_choice_name:&str, applied_choice_owner:Party, applied_chosen_value: i64) ->
Result<ContractInstance,ApplyInputChoiceError>;

fn apply_input_deposit(&self,from:Party, asset: Token, quantity: u64, to:crate::types::marlowe::AccountId) ->
fn apply_input_deposit(&self,from:Party, asset: Token, quantity: i64, to:crate::types::marlowe::AccountId) ->
Result<ContractInstance,ApplyInputDepositError>;

fn apply_input_action(&self,action:crate::types::marlowe::InputAction) ->
Expand Down Expand Up @@ -390,8 +390,9 @@ impl ContractSemantics<ContractInstance> for ContractInstance {

match action {
InputAction::Deposit { into_account, input_from_party, of_tokens, that_deposits } => {

match (into_account,input_from_party,of_tokens) {
(Some(a), Some(b), Some(c)) => match self.apply_input_deposit(b, c, that_deposits, AccountId::Role { role_token: "nisse".to_owned() }) {
(Some(_a), Some(b), Some(c)) => match self.apply_input_deposit(b, c, that_deposits, AccountId::Role { role_token: "nisse".to_owned() }) {
Ok(v) => Ok(v),
Err(e) => Err(ActionApplicationError::InvalidDeposit(e)),
},
Expand Down Expand Up @@ -419,7 +420,7 @@ impl ContractSemantics<ContractInstance> for ContractInstance {
let result = self.step(true);
match result {
Ok(r) => match r.0.process() {
Ok((a,b)) => Ok(a),
Ok((a,_b)) => Ok(a),
Err(e) => Err(ActionApplicationError::Unknown(
format!("Applied notify successfully but failed to invoke process() (step 2).. {:?}",e)
)),
Expand Down Expand Up @@ -485,7 +486,7 @@ impl ContractSemantics<ContractInstance> for ContractInstance {

}

fn apply_input_deposit(&self,from:Party, asset: Token, quantity: u64, to:crate::types::marlowe::AccountId) -> Result<ContractInstance,ApplyInputDepositError> {
fn apply_input_deposit(&self,from:Party, asset: Token, quantity: i64, to:crate::types::marlowe::AccountId) -> Result<ContractInstance,ApplyInputDepositError> {

let (mut new_instance,machine_state) = match self.process() {
Ok((a, b)) => (a,b),
Expand All @@ -510,30 +511,43 @@ impl ContractSemantics<ContractInstance> for ContractInstance {
continuation
} => {

// When a contract expects negative deposit amounts, we accept the redeemer matching that exact negative value,
// but we treat the applied input value as zero, thus it will not actually affect the value of any account.
let clamped_quantity = 0.max(quantity) as u64;

if who_is_expected_to_pay == &from
&& &asset == expected_asset_type
&& &quantity == expected_amount
&& expected_target_account == &to
{
// Add or update amount for the party that is depositing value to their account.
if let Some(existing_amount) = new_instance.state.accounts.get_mut(&(from.clone(),asset.clone())) {
*existing_amount = *existing_amount + quantity;
let mut old_amount : u64 = 0;
let new_amount : u64;

// Add or update amount for the target account.
if let Some(existing_amount) = new_instance.state.accounts.get_mut(&(expected_target_account.clone(),asset.clone())) {
old_amount = *existing_amount;
new_amount = *existing_amount + clamped_quantity;
*existing_amount = *existing_amount + clamped_quantity;
} else {
new_amount = clamped_quantity;
new_instance.state.accounts.insert(
(from.clone(),asset.clone()),
quantity
(expected_target_account.clone(),asset.clone()),
clamped_quantity
);
}

new_instance.contract = continuation.clone();
new_instance.applied.push(AppliedInput::Deposit(
from,
from.clone(),
expected_target_account.clone(),
expected_asset_type.clone(),
quantity
clamped_quantity
));
new_instance.logs.push(format!("Deposit was successfully applied: '{x:?}' has been applied."));
if clamped_quantity as i64 > quantity {
new_instance.logs.push(format!("Deposit was successfully applied: '{x:?}' has been applied. {from}. Because this was a negative deposit, it counted as zero - so the target account {expected_target_account} did not change at all but stays at {old_amount} {expected_asset_type}"));
} else {
new_instance.logs.push(format!("Deposit was successfully applied: '{x:?}' has been applied. {from} has added {clamped_quantity} of {expected_asset_type} to the account of {expected_target_account} which now contains {new_amount} {expected_asset_type} (before this, it contained only {old_amount})"));
}
return Ok(new_instance)
}
}
Expand Down Expand Up @@ -729,14 +743,10 @@ impl ContractSemantics<ContractInstance> for ContractInstance {
match expected_amount {
Ok(v) =>
{
if v < 0 {
return Err(format!("Expected amount turned out negative.. This is most likely a bug in the marlowe_lang crate. {:?} {:?}", self.state ,depo))
}

expected_inputs.push(InputType::Deposit {
who_is_expected_to_pay: from.clone(),
expected_asset_type: tok.clone(),
expected_amount: v as u64,
expected_amount: v,
expected_target_account: to.clone(),
continuation: *(continuation.clone())
})
Expand Down Expand Up @@ -822,3 +832,6 @@ impl ContractSemantics<ContractInstance> for ContractInstance {
new_instance
}
}



20 changes: 10 additions & 10 deletions src/lib/tests/core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -407,9 +407,9 @@ fn can_find_uninitialized_inputs() -> Result<(),String> {
}

if found_inputs.len() != (result.uninitialized_const_params.len() + result.uninitialized_time_params.len()) {
println!("parser found these consts: {:?}",result.uninitialized_const_params);
println!("parser found these times: {:?}",result.uninitialized_time_params);
println!("contract impl found these: {:?}",found_inputs);
// println!("parser found these consts: {:?}",result.uninitialized_const_params);
// println!("parser found these times: {:?}",result.uninitialized_time_params);
// println!("contract impl found these: {:?}",found_inputs);
return Err(format!("PARSE AND STRUCT IMPL DIFF!"))
}

Expand Down Expand Up @@ -519,7 +519,7 @@ pub fn marlowe_strict_conversion() -> Result<(),String> {
pub fn basic_marlowe_strict_example_code() -> Result<(),String> {

use crate::types::marlowe_strict::*;
use crate::serialization::*;
// use crate::serialization::*;

let p1 = Party::role("P1");
let p2 = Party::role("P2");
Expand Down Expand Up @@ -549,11 +549,11 @@ pub fn basic_marlowe_strict_example_code() -> Result<(),String> {
timeout_continuation: Contract::Close.into()
};

let serializable_contract : crate::types::marlowe::Contract = contract.try_into()?;
let _serializable_contract : crate::types::marlowe::Contract = contract.try_into()?;

println!("{}",marlowe::serialize(serializable_contract.clone()));
println!("{}",json::serialize(serializable_contract.clone())?);
println!("{}",cborhex::serialize(serializable_contract.clone())?);
// println!("{}",marlowe::serialize(serializable_contract.clone()));
// println!("{}",json::serialize(serializable_contract.clone())?);
// println!("{}",cborhex::serialize(serializable_contract.clone())?);


Ok(())
Expand Down Expand Up @@ -615,8 +615,8 @@ fn marlowe_strict_with_iter_example() {
timeout: chrono::Utc::now().checked_add_days(Days::new(1)).unwrap().timestamp_millis(),
timeout_continuation: Contract::Close.into()
};
let serialized = marlowe::serialize_strict(contract).unwrap();
println!("{}",parsing::fmt::fmt(&serialized))
let _serialized = marlowe::serialize_strict(contract).unwrap();
// println!("{}",parsing::fmt::fmt(&serialized))
}


Expand Down
Loading

0 comments on commit fb6aea2

Please sign in to comment.