Crate marlowe_lang

source ·
Expand description

An experimental implementation of the Marlowe language for Cardano smart contracts.

Its primary use-case is for creating smart contracts in Rust rather than directly using Marlowe, and instead be able to export the contracts into Marlowe programatically.

Grammars

This crate uses Pest.rs!

[grammars.rs] Click to expand/collapse
WHITESPACE = _{ " " | "\t" | "\r" | "\n" | "\r\n" }
comma  = _{ "," }
lpar   = _{ "(" }
rpar   = _{ ")" }
lbra   = _{ "[" }
rbra   = _{ "]" }

Number = @{
    "-"{0,1} ~ ASCII_DIGIT+
}





quoted_string = _{ "\"" ~ string ~ "\""  }
string = { str_char* }
str_char = _{
    !("\"" | "\\") ~ ANY
    | "\\" ~ ("\"" | "\\" )
}



Timeout = _{ TimeoutHole | TimeConstant | TimeParam }
TimeConstant = ${ ASCII_DIGIT+ }
TimeInterval = { lpar ~ "TimeInterval" ~ Timeout  ~ Timeout  ~ rpar }
TimeParam = { lpar  ~ "TimeParam"  ~ quoted_string  ~ rpar }

Token = _{TokenHole|ADA|Currency}
ADA = { "Token \"\" \"\"" }
Currency = { lpar  ~ "Token"  ~ quoted_string  ~ quoted_string  ~ rpar }
ChoiceId = { lpar  ~"ChoiceId"  ~ quoted_string  ~ Party  ~ rpar}
Value = _{   
    AvailableMoney
    | ChoiceValue
    | MulValue
    | DivValue
    | SubValue
    | AddValue
    | NegValue
    | UseValue
    | TimeIntervalStart
    | TimeIntervalEnd
    | ValueHole
    | ConstantParam
    | Constant
    | Cond
 }
    TimeIntervalStart = { "TimeIntervalStart" }
    TimeIntervalEnd = { "TimeIntervalEnd" }
    Cond = { lpar  ~ "Cond"  ~ Observation  ~ Value  ~ Value  ~ rpar}
    ChoiceValue = { lpar  ~ "ChoiceValue"  ~ ChoiceId  ~ rpar}
    MulValue = { lpar  ~ "MulValue"  ~ Value  ~ Value  ~ rpar }
    DivValue = { lpar  ~ "DivValue"  ~ Value  ~ Value  ~ rpar}
    SubValue = { lpar  ~ "SubValue"  ~ Value  ~ Value  ~ rpar}
    AddValue = { lpar  ~ "AddValue"  ~ Value  ~ Value  ~ rpar}
    NegValue = { lpar  ~ "NegValue"  ~ Value  ~ rpar}
    UseValue = { lpar  ~ "UseValue"  ~ ValueId  ~ rpar}
    Constant = { lpar  ~ "Constant"  ~ Number  ~ rpar }
    ConstantParam = { lpar  ~ "ConstantParam"  ~ quoted_string  ~ rpar }
    AvailableMoney = { lpar  ~ "AvailableMoney"  ~ Party  ~ Token  ~ rpar}

Observation = _{ ObservationHole | TrueObs | FalseObs | ValueEQ | ValueLE | 
                 ValueLT | ValueGT | ValueGE | OrObs | 
                 NotObs | AndObs | ChoseSomething }
    ValueEQ = { lpar  ~ "ValueEQ"    ~ Value   ~ Value ~WHITESPACE*  ~ rpar }
    ValueLE = { lpar  ~ "ValueLE"   ~ Value   ~ Value ~WHITESPACE*  ~ rpar }
    ValueLT = { lpar  ~ "ValueLT"   ~ Value   ~ Value ~WHITESPACE*  ~ rpar }
    ValueGT = { lpar  ~ "ValueGT"   ~ Value   ~ Value ~WHITESPACE*  ~ rpar }
    ValueGE = { lpar  ~ "ValueGE"   ~ Value   ~ Value ~WHITESPACE*  ~ rpar }
    TrueObs = { "TrueObs" }
    FalseObs = { "FalseObs" }
    ChoseSomething = { lpar  ~ "ChoseSomething"  ~ ChoiceId ~ WHITESPACE* ~ rpar }
    NotObs = { lpar  ~ "NotObs"  ~ Observation  ~ rpar }
    OrObs =  { lpar  ~ "OrObs"   ~ Observation  ~ Observation  ~ rpar }
    AndObs = { lpar  ~ "AndObs"  ~ Observation  ~ Observation  ~ rpar }
   
Action = _{ ActionHole | Notify | Choice | Deposit }
    Deposit = { lpar  ~"Deposit"  ~ Party  ~ FromParty  ~ Token  ~ Value  ~ rpar }
    Choice =  { lpar  ~"Choice"   ~ ChoiceId  ~ ArrayOfBounds  ~ rpar }
    Notify =  { lpar  ~"Notify"   ~ Observation  ~ rpar }


PossiblyMerkleizedContract = _{ContractHole|NonMerkleizedContract|MerkleizedContract}
    NonMerkleizedContract = { WrappedContract }
    MerkleizedContract = {
        lpar ~ "MerkleizedThen" ~ quoted_string  ~ rpar
        | "MerkleizedThen" ~ quoted_string
    }

Case = {
    lpar ~ "Case"  ~ Action  ~ PossiblyMerkleizedContract ~ rpar
    | "Case"  ~ Action ~ PossiblyMerkleizedContract
    
}

Bound = ${ 
    lpar ~ "Bound" ~ WHITESPACE+ ~ Number ~ WHITESPACE+ ~ Number ~ WHITESPACE* ~ rpar
    | "Bound" ~ WHITESPACE+ ~ Number ~ WHITESPACE+ ~ Number ~ WHITESPACE*
}

Payee = _{ PayeeHole | PayeeAccount | PayeeParty }
PayeeAccount = { lpar  ~ "Account"  ~ Party  ~ rpar }
PayeeParty = { lpar  ~ "Party"  ~ Party  ~ rpar }
Party = _{ PartyHole | Role | Address }
FromParty = _{ FromPartyHole | Role | Address }
Role = { lpar  ~ "Role"  ~ quoted_string  ~ rpar }
Address = { lpar  ~ "Address"  ~ quoted_string  ~ rpar }
Account = { "Account"  ~ Party }

MainContract = _{ Contract ~ EOI }

ValueId = { quoted_string }

Contract = { Close | When | If | Let | Assert | Pay }
    When   = { "When"  ~ ArrayOfCases  ~ Timeout  ~ WrappedContract }
    Pay    = { "Pay"   ~ Party  ~ Payee  ~ Token  ~ Value   ~ WrappedContract }
    If     = { "If"    ~ Observation  ~ WrappedContract  ~ WrappedContract }
    Let    = { "Let"   ~ ValueId  ~ Value  ~ WrappedContract }
    Assert = { "Assert"  ~ Observation  ~ WrappedContract }
    Close  = { "Close" }

WrappedContract = _{
    ContractHole | Close | "("  ~ (Assert|Let|If|Pay|When)  ~  ")"
}

ArrayOfCases = { 
     lbra ~ (Case|CaseHole) ~ ("," ~ (Case|CaseHole))* ~ rbra 
     | lbra ~ rbra
}

ArrayOfBounds = { 
     lbra ~ (Bound|BoundHole) ~ ("," ~ (Bound|BoundHole))* ~ rbra 
     | lbra ~ rbra
}

Hole = _ { "?"~("-"|"_"|ASCII_DIGIT|ASCII_ALPHA)* }
PartyHole = { Hole }
FromPartyHole = { Hole }
ContractHole = { Hole }
PayeeHole = { Hole }
ValueHole = { Hole }
ObservationHole = { Hole }
TimeoutHole = { Hole }
TokenHole = { Hole }
BoundHole = { Hole }
RoleHole = { Hole }
CaseHole = { Hole }
ActionHole = { Hole }
AccountHole = { Hole }

Example usage

use marlowe_lang::types::marlowe::*;
use marlowe_lang::{
 deserialization::marlowe::deserialize,
 serialization::marlowe::serialize,
};
 
let my_contract = Contract::When {
    when: vec![
        Some(PossiblyMerkleizedCase::Raw { 
            case: Some(Action::Notify { 
                notify_if: Some(Observation::True)
            }), 
            then: Some(Contract::Close) })
    ],
    timeout: Some(Timeout::TimeParam("test".into())),
    timeout_continuation: Some(Contract::Close.boxed()),
};
 
let serialized = serialize(my_contract);
let deserialized : Contract = deserialize(&serialized).unwrap().contract;
println!("{serialized}");
Where ‘println!(“{serialized}”)’ would output this:
When [ Case (Notify (True)) Close ] (TimeParam "test") Close

Re-exports

Modules