Plutus and Extended UTxO

Plutus and Extended UTxO

VIDEO: https://www.youtube.com/watch?v=TFezjgwuw8Y

This presentation was part of PlutusFest 2018 and introduces the design and architecture of the Plutus Platform, a Haskell-based environment and toolchain for developing contracts for the Cardano blockchain. The key features are its use of a standard purely functional programming language (instead of inventing a new language, which appears to be the popular approach), being based on a ledger-architecture that resembles a functional data flow graph (UTxO ledger, rather than an account-based ledger), and its tight integration and co-development of on-chain code (executed by block producing nodes) and off-chain code (executed on client machines).

See https://testnet.iohkdev.io/plutus/ for an online environment to write and test Plutus code and https://github.com/input-output-hk/plutus/ for the code.

2cc5323ccdfc09b921f1be34b3d78a69?s=128

Manuel Chakravarty

December 11, 2018
Tweet

Transcript

  1. 3.

    PLUTUS What is Plutus? Innovative development and execution platform for

    distributed contract applications on Cardano SL & CL.
  2. 9.
  3. 17.

    PLUTUS input output typed function safe usage :: ⍺ ::

    β local reasoning type-directed design
  4. 18.

    PLUTUS input output typed function safe usage :: ⍺ ::

    β local reasoning type-directed design advanced testing & verification
  5. 24.

    PLUTUS core Plutus Core not a bytecode not a classic

    virtual machine typed FP calculus abstract machine interpreter
  6. 25.

    PLUTUS core Plutus Core small, powerful & based on peer-reviewed

    science not a bytecode not a classic virtual machine typed FP calculus abstract machine interpreter
  7. 38.
  8. 39.
  9. 45.

    PLUTUS Input Output ν: Validator x: Value ρ: Redeemer ν(ρ)

    ≟ True ν: Validator x: Value ρ: Redeemer core core core core
  10. 46.

    PLUTUS Input Output ν: Validator x: Value ρ: Redeemer ν(ρ)

    ≟ True ν: Validator x: Value ρ: Redeemer δ: Data core core core core core
  11. 47.

    PLUTUS Input Output ν: Validator x: Value ρ: Redeemer ν(ρ)

    ≟ True ν: Validator x: Value ρ: Redeemer δ: Data σ: State core core core core core
  12. 48.

    PLUTUS Input Output ν: Validator x: Value ρ: Redeemer ν(ρ)

    ≟ True ν: Validator x: Value ρ: Redeemer ν(ρ, δ, σ, x) ≟ True δ: Data σ: State core core core core core
  13. 49.

    PLUTUS ν: Validator x: Value ρ: Redeemer ν(ρ, δ, σ,

    x) ≟ True δ: Data σ: State Extended UTxO core core core
  14. 50.

    PLUTUS ν: Validator x: Value ρ: Redeemer ν(ρ, δ, σ,

    x) ≟ True δ: Data σ: State Extended UTxO Preserves the superior structure of UTxO ledgers core core core
  15. 51.

    PLUTUS ν: Validator x: Value ρ: Redeemer ν(ρ, δ, σ,

    x) ≟ True δ: Data σ: State Extended UTxO Preserves the superior structure of UTxO ledgers Greatly increases the expressive power of scripts core core core
  16. 52.

    PLUTUS Extended UTxO Preserves the superior structure of UTxO ledgers

    Greatly increases the expressive power of scripts
  17. 53.

    PLUTUS Extended UTxO Preserves the superior structure of UTxO ledgers

    Greatly increases the expressive power of scripts data flows with value
  18. 54.

    PLUTUS Extended UTxO Preserves the superior structure of UTxO ledgers

    Greatly increases the expressive power of scripts data flows with value scripts have an identity
  19. 55.

    PLUTUS Extended UTxO Preserves the superior structure of UTxO ledgers

    Greatly increases the expressive power of scripts data flows with value scripts have an identity invariants across transaction chains
  20. 57.
  21. 61.

    PLUTUS Simple crowdfunding 1. Payment into campaign until a payment

    deadline 2. If funding goal reached, campaign owner can collect funds
  22. 62.

    PLUTUS Simple crowdfunding 1. Payment into campaign until a payment

    deadline 2. If funding goal reached, campaign owner can collect funds 3. If funding goal not reached, refunds can be obtained by contributors
  23. 63.

    PLUTUS Simple crowdfunding 1. Payment into campaign until a payment

    deadline 2. If funding goal reached, campaign owner can collect funds 3. If funding goal not reached, refunds can be obtained by contributors 4. If campaign owner does not collect by collection deadline, contributors can also obtain refunds
  24. 64.

    PLUTUS 1. Payment into campaign until a payment deadline 2.

    If funding goal reached, campaign owner can collect funds 3. If funding goal not reached, refunds can be obtained by contributors 4. If campaign owner does not collect by collection deadline, contributors can also obtain refunds
  25. 65.

    PLUTUS 1. Payment into campaign until a payment deadline 2.

    If funding goal reached, campaign owner can collect funds 3. If funding goal not reached, refunds can be obtained by contributors 4. If campaign owner does not collect by collection deadline, contributors can also obtain refunds pragma solidity ^0.4.6; contract WinnerTakesAll { uint minimumEntryFee; uint public deadlineProjects; uint public deadlineCampaign; uint public winningFunds; address public winningAddress; struct Project { address addr; string name; string url; uint funds; bool initialized; } … Solidity (on-chain)
  26. 66.

    PLUTUS pragma solidity ^0.4.6; contract WinnerTakesAll { uint minimumEntryFee; uint

    public deadlineProjects; uint public deadlineCampaign; uint public winningFunds; address public winningAddress; struct Project { address addr; string name; string url; uint funds; bool initialized; } … Solidity (on-chain) var Web3 = require('web3'); var web3 = new Web3(); web3.setProvider(new web3.providers.HttpProvider(”http:… var accounts = web3.eth.accounts; accounts.forEach(function(v) { $(”#supportFrom”).append(”<opt… $(”#projectAddr”).append(”<opt… }); var compiled = web3.eth.compile.so… var code = compiled.code; var abi = compiled.info.abiDefinit… var contract = web3.eth.contract(a… … JavaScript (off-chain) +
  27. 67.

    PLUTUS pragma solidity ^0.4.6; contract WinnerTakesAll { uint minimumEntryFee; uint

    public deadlineProjects; uint public deadlineCampaign; uint public winningFunds; address public winningAddress; struct Project { address addr; string name; string url; uint funds; bool initialized; } … Solidity var Web3 = require('web3'); var web3 = new Web3(); web3.setProvider(new web3.providers.HttpProvider(”http:… var accounts = web3.eth.accounts; accounts.forEach(function(v) { $(”#supportFrom”).append(”<opt… $(”#projectAddr”).append(”<opt… }); var compiled = web3.eth.compile.so… var code = compiled.code; var abi = compiled.info.abiDefinit… var contract = web3.eth.contract(a… … JavaScript
  28. 68.

    PLUTUS pragma solidity ^0.4.6; contract WinnerTakesAll { uint minimumEntryFee; uint

    public deadlineProjects; uint public deadlineCampaign; uint public winningFunds; address public winningAddress; struct Project { address addr; string name; string url; uint funds; bool initialized; } … Solidity var Web3 = require('web3'); var web3 = new Web3(); web3.setProvider(new web3.providers.HttpProvider(”http:… var accounts = web3.eth.accounts; accounts.forEach(function(v) { $(”#supportFrom”).append(”<opt… $(”#projectAddr”).append(”<opt… }); var compiled = web3.eth.compile.so… var code = compiled.code; var abi = compiled.info.abiDefinit… var contract = web3.eth.contract(a… … JavaScript off-chain (wallet) on-chain (transaction)
  29. 69.

    PLUTUS pragma solidity ^0.4.6; contract WinnerTakesAll { uint minimumEntryFee; uint

    public deadlineProjects; uint public deadlineCampaign; uint public winningFunds; address public winningAddress; struct Project { address addr; string name; string url; uint funds; bool initialized; } … Solidity var Web3 = require('web3'); var web3 = new Web3(); web3.setProvider(new web3.providers.HttpProvider(”http:… var accounts = web3.eth.accounts; accounts.forEach(function(v) { $(”#supportFrom”).append(”<opt… $(”#projectAddr”).append(”<opt… }); var compiled = web3.eth.compile.so… var code = compiled.code; var abi = compiled.info.abiDefinit… var contract = web3.eth.contract(a… … JavaScript off-chain (wallet) on-chain (transaction) two-level (staged) programming model JavaScript Solidity
  30. 78.
  31. 79.

    PLUTUS Haskell (Plutus Tx) Haskell off-chain (wallet) on-chain (transaction) two-level

    (staged) programming model meta programming integrated compact
  32. 80.

    PLUTUS Haskell (Plutus Tx) Haskell off-chain (wallet) on-chain (transaction) two-level

    (staged) programming model meta programming integrated compact robust
  33. 82.

    PLUTUS contribute :: Campaign -> Value -> MockWallet () contribute

    campaign value = do when (value <= 0) $ throwOtherError "Must contribute a positive value" Haskell
  34. 83.

    PLUTUS contribute :: Campaign -> Value -> MockWallet () contribute

    campaign value = do when (value <= 0) $ throwOtherError "Must contribute a positive value" ownPK <- ownPubKey Haskell
  35. 84.

    PLUTUS contribute :: Campaign -> Value -> MockWallet () contribute

    campaign value = do when (value <= 0) $ throwOtherError "Must contribute a positive value" ownPK <- ownPubKey tx <- payToScript Haskell
  36. 85.

    PLUTUS contribute :: Campaign -> Value -> MockWallet () contribute

    campaign value = do when (value <= 0) $ throwOtherError "Must contribute a positive value" ownPK <- ownPubKey tx <- payToScript (Ledger.scriptAddress (contributionScript campaign)) Haskell
  37. 86.

    PLUTUS contribute :: Campaign -> Value -> MockWallet () contribute

    campaign value = do when (value <= 0) $ throwOtherError "Must contribute a positive value" ownPK <- ownPubKey tx <- payToScript (Ledger.scriptAddress (contributionScript campaign)) value Haskell
  38. 87.

    PLUTUS contribute :: Campaign -> Value -> MockWallet () contribute

    campaign value = do when (value <= 0) $ throwOtherError "Must contribute a positive value" ownPK <- ownPubKey tx <- payToScript (Ledger.scriptAddress (contributionScript campaign)) value DataScript (Ledger.lifted ownPK) Haskell
  39. 88.

    PLUTUS contribute :: Campaign -> Value -> MockWallet () contribute

    campaign value = do when (value <= 0) $ throwOtherError "Must contribute a positive value" ownPK <- ownPubKey tx <- payToScript (Ledger.scriptAddress (contributionScript campaign)) value DataScript (Ledger.lifted ownPK) register (refundTrigger campaign) (refundHandler (Ledger.hashTx tx) campaign) contributionScript :: Campaign -> ValidatorScript Haskell
  40. 92.

    PLUTUS contributionScript :: Campaign -> ValidatorScript contributionScript campaign = ValidatorScript

    (validator `apply` campaign) where validator = Ledger.fromCompiledCode $$(PlutusTx.compile [|| (\Campaign{..} action contrib tx -> Plutus Tx Haskell
  41. 93.

    PLUTUS contributionScript :: Campaign -> ValidatorScript contributionScript campaign = ValidatorScript

    (validator `apply` campaign) where validator = Ledger.fromCompiledCode $$(PlutusTx.compile [|| (\Campaign{..} action contrib tx -> let PendingTx ps outs _ _ (Height h) _ _ = tx Plutus Tx Haskell
  42. 94.

    PLUTUS contributionScript :: Campaign -> ValidatorScript contributionScript campaign = ValidatorScript

    (validator `apply` campaign) where validator = Ledger.fromCompiledCode $$(PlutusTx.compile [|| (\Campaign{..} action contrib tx -> let PendingTx ps outs _ _ (Height h) _ _ = tx isValid = case action of Plutus Tx Haskell
  43. 95.

    PLUTUS contributionScript :: Campaign -> ValidatorScript contributionScript campaign = ValidatorScript

    (validator `apply` campaign) where validator = Ledger.fromCompiledCode $$(PlutusTx.compile [|| (\Campaign{..} action contrib tx -> let PendingTx ps outs _ _ (Height h) _ _ = tx isValid = case action of Refund -> h > collectionDeadline && Plutus Tx Haskell
  44. 96.

    PLUTUS contributionScript :: Campaign -> ValidatorScript contributionScript campaign = ValidatorScript

    (validator `apply` campaign) where validator = Ledger.fromCompiledCode $$(PlutusTx.compile [|| (\Campaign{..} action contrib tx -> let PendingTx ps outs _ _ (Height h) _ _ = tx isValid = case action of Refund -> h > collectionDeadline && contributorOnly outs && Plutus Tx Haskell
  45. 97.

    PLUTUS contributionScript :: Campaign -> ValidatorScript contributionScript campaign = ValidatorScript

    (validator `apply` campaign) where validator = Ledger.fromCompiledCode $$(PlutusTx.compile [|| (\Campaign{..} action contrib tx -> let PendingTx ps outs _ _ (Height h) _ _ = tx isValid = case action of Refund -> h > collectionDeadline && contributorOnly outs && $$(txSignedBy) tx contrib Plutus Tx Haskell
  46. 98.

    PLUTUS contributionScript :: Campaign -> ValidatorScript contributionScript campaign = ValidatorScript

    (validator `apply` campaign) where validator = Ledger.fromCompiledCode $$(PlutusTx.compile [|| (\Campaign{..} action contrib tx -> let PendingTx ps outs _ _ (Height h) _ _ = tx isValid = case action of Refund -> h > collectionDeadline && contributorOnly outs && $$(txSignedBy) tx contrib Collect -> h > deadline && Plutus Tx Haskell
  47. 99.

    PLUTUS contributionScript :: Campaign -> ValidatorScript contributionScript campaign = ValidatorScript

    (validator `apply` campaign) where validator = Ledger.fromCompiledCode $$(PlutusTx.compile [|| (\Campaign{..} action contrib tx -> let PendingTx ps outs _ _ (Height h) _ _ = tx isValid = case action of Refund -> h > collectionDeadline && contributorOnly outs && $$(txSignedBy) tx contrib Collect -> h > deadline && h <= collectionDeadline && Plutus Tx Haskell
  48. 100.

    PLUTUS contributionScript :: Campaign -> ValidatorScript contributionScript campaign = ValidatorScript

    (validator `apply` campaign) where validator = Ledger.fromCompiledCode $$(PlutusTx.compile [|| (\Campaign{..} action contrib tx -> let PendingTx ps outs _ _ (Height h) _ _ = tx isValid = case action of Refund -> h > collectionDeadline && contributorOnly outs && $$(txSignedBy) tx contrib Collect -> h > deadline && h <= collectionDeadline && totalInputs >= target && Plutus Tx Haskell
  49. 101.

    PLUTUS contributionScript :: Campaign -> ValidatorScript contributionScript campaign = ValidatorScript

    (validator `apply` campaign) where validator = Ledger.fromCompiledCode $$(PlutusTx.compile [|| (\Campaign{..} action contrib tx -> let PendingTx ps outs _ _ (Height h) _ _ = tx isValid = case action of Refund -> h > collectionDeadline && contributorOnly outs && $$(txSignedBy) tx contrib Collect -> h > deadline && h <= collectionDeadline && totalInputs >= target && $$(txSignedBy) p campaignOwner Plutus Tx Haskell
  50. 102.

    PLUTUS contributionScript :: Campaign -> ValidatorScript contributionScript campaign = ValidatorScript

    (validator `apply` campaign) where validator = Ledger.fromCompiledCode $$(PlutusTx.compile [|| (\Campaign{..} action contrib tx -> let PendingTx ps outs _ _ (Height h) _ _ = tx isValid = case action of Refund -> h > collectionDeadline && contributorOnly outs && $$(txSignedBy) tx contrib Collect -> h > deadline && h <= collectionDeadline && totalInputs >= target && $$(txSignedBy) p campaignOwner in $$(P.errorIfNot) isValid ||]) Plutus Tx Haskell
  51. 105.

    PLUTUS contribute :: Campaign -> Value -> MockWallet () contribute

    campaign value = do when (value <= 0) $ throwOtherError "Must contribute a positive value" ownPK <- ownPubKey tx <- payToScript (Ledger.scriptAddress (contributionScript campaign)) value DataScript (Ledger.lifted ownPK) register (refundTrigger campaign) (refundHandler (Ledger.hashTx tx) campaign) contributionScript :: Campaign -> ValidatorScript contributionScript campaign = ValidatorScript (validator `apply` campaign) where validator = Ledger.fromCompiledCode $$(PlutusTx.compile [|| (\Campaign{..} action contrib tx -> let PendingTx ps outs _ _ (Height h) _ _ = tx isValid = case action of Refund -> h > collectionDeadline && contributorOnly outs && $$(txSignedBy) tx contrib Collect -> h > deadline && h <= collectionDeadline && totalInputs >= target && $$(txSignedBy) p campaignOwner in $$(P.errorIfNot) isValid ||]) off-chain on-chain
  52. 106.

    PLUTUS contribute :: Campaign -> Value -> MockWallet () contribute

    campaign value = do when (value <= 0) $ throwOtherError "Must contribute a positive value" ownPK <- ownPubKey tx <- payToScript (Ledger.scriptAddress (contributionScript campaign)) value DataScript (Ledger.lifted ownPK) register (refundTrigger campaign) (refundHandler (Ledger.hashTx tx) campaign) contributionScript :: Campaign -> ValidatorScript contributionScript campaign = ValidatorScript (validator `apply` campaign) where validator = Ledger.fromCompiledCode $$(PlutusTx.compile [|| (\Campaign{..} action contrib tx -> let PendingTx ps outs _ _ (Height h) _ _ = tx isValid = case action of Refund -> h > collectionDeadline && contributorOnly outs && $$(txSignedBy) tx contrib Collect -> h > deadline && h <= collectionDeadline && totalInputs >= target && $$(txSignedBy) p campaignOwner in $$(P.errorIfNot) isValid ||]) core off-chain on-chain
  53. 107.

    PLUTUS contribute :: Campaign -> Value -> MockWallet () contribute

    campaign value = do when (value <= 0) $ throwOtherError "Must contribute a positive value" ownPK <- ownPubKey tx <- payToScript (Ledger.scriptAddress (contributionScript campaign)) value DataScript (Ledger.lifted ownPK) register (refundTrigger campaign) (refundHandler (Ledger.hashTx tx) campaign) contributionScript :: Campaign -> ValidatorScript contributionScript campaign = ValidatorScript (validator `apply` campaign) where validator = Ledger.fromCompiledCode $$(PlutusTx.compile [|| (\Campaign{..} action contrib tx -> let PendingTx ps outs _ _ (Height h) _ _ = tx isValid = case action of Refund -> h > collectionDeadline && contributorOnly outs && $$(txSignedBy) tx contrib Collect -> h > deadline && h <= collectionDeadline && totalInputs >= target && $$(txSignedBy) p campaignOwner in $$(P.errorIfNot) isValid ||]) core core off-chain on-chain
  54. 108.

    PLUTUS contribute :: Campaign -> Value -> MockWallet () contribute

    campaign value = do when (value <= 0) $ throwOtherError "Must contribute a positive value" ownPK <- ownPubKey tx <- payToScript (Ledger.scriptAddress (contributionScript campaign)) value DataScript (Ledger.lifted ownPK) register (refundTrigger campaign) (refundHandler (Ledger.hashTx tx) campaign) contributionScript :: Campaign -> ValidatorScript contributionScript campaign = ValidatorScript (validator `apply` campaign) where validator = Ledger.fromCompiledCode $$(PlutusTx.compile [|| (\Campaign{..} action contrib tx -> let PendingTx ps outs _ _ (Height h) _ _ = tx isValid = case action of Refund -> h > collectionDeadline && contributorOnly outs && $$(txSignedBy) tx contrib Collect -> h > deadline && h <= collectionDeadline && totalInputs >= target && $$(txSignedBy) p campaignOwner in $$(P.errorIfNot) isValid ||]) core core off-chain on-chain