DaiLambda, Inc.
Jun FURUSE/古瀬淳
Kyoto, 2020-06-25
https://scamlang.dev
What is SCaml
Yet another compiler from OCaml to Michelson.
“Smart Contract Abstract Machine Language”
For Smart contracts
Strict Subset of OCaml
Small (7500 loc.).
Strict Subset of OCaml
Valid SCaml program is valid OCaml program.
No special features for smart contracts.
Some OCaml features are disabled:
No recursion
No polymoprhism
No ML functors
No objects
No mutability
Small
Built over OCaml’s compiler­libs:
Reusing OCaml’s parser and type-checker.
SCaml compiles OCaml’s typed AST to Michelson.
The first version was in 3000 loc written in 5 days.
and Serious
Serious compiler.
All the Michelson opcodes are supported.
Optimizations.
Carthage ready (i.e. entry points, closures)
Benefit of being Strict Subset
OCaml programmers can use SCaml immediately.
Newbies can learn SCaml via OCaml tutorial.
Many OCaml eco-system tools can be used for free:
Menhir, Tuareg, indender, reformatter
Dune (build system)
PPX, P4, ReasonML
Possibilities of being Strict Subset
Simluation in native code
Native compilation with simulated primitives:
dApp development in one language
Contracts: to Michelson by SCaml
UI: to JS by JSOO
Server: to native by OCaml
Certification in Coq and F*
Availability
Docker images
OPAM
opam install scaml
(requires OCaml 4.09.1)
Source
https://hub.docker.com/layers/dailambda/scaml
https://gitlab.com/dailambda/scaml
Writing smart contracts in SCaml
Start with open SCaml
SCaml is the standard library for SCaml:
Ordinary Stdlib is not working.
open SCaml
Entry points with [@entry]
Allowed only in the last linked module:
let [@entry] f param storage = ...
val f : param_ty  
        ­> storage_ty  
        ­> SCaml.operation list * storage_ty
Simplest smart contract
Does nothing:
Compilation;
let [@entry] default () () = [], ()
$ scamlc nothing.ml 
Linking Nothing 
(outputs nothing.tz)
Numeralic types int, nat, tz
Int (­12)
Nat 42
Tz 1.23 (in tez, not micro tez)
with monomorphic operators: (+), (+^),(+$)
Options, Lists, Sets, Maps
Some 1
[ Int 1; Int 2; Int 3 ]
Set [ Nat 1; Nat 2; Nat 3 ]
Map [ (Int 1, "one"), (Int 2, "two") ]
Set and Map only take constants for now.
Blockchain related constants
In style of a constructor + a string constant:
Key_hash "tz1KqTpEZ7Yob7QbPE4Hy4.."
Signature "edsigtteMcYkviZ3rTaM6N7DW.."
Timestamp "2019­09­11T08:30:23Z"
Pairs, Sums, Variants, and Records
Compiled down to pairs and sums.
Using right balanced tree,
with optimization for nullary variants (like OCaml)
Full pattern match
Nested patterns
Or patterns
Guards
Non-exhaustive check
TODO: Pattern match heuristics for
efficiency
Modules
module M = struct .. end
for code grouping
No module aliases and functors
Link of multiple *.ml files
scamlc a.ml b.ml c.ml
Exceptions
User definable
Reported as (Pair "Module.My_error" 1)
in Michelson.
Exception is not catchable.
(* module.ml *) 
exception My_error of int 
 
raise (My_error (Int 1))
SCaml specific errors
Error number to indicate the nature:
Easy to distinguish OCaml errors and SCaml ones.
[ESCaml000] SCaml does not support objects
Surprises
Surprises on closures
Michelson closure must be packable.
Its environment cannot carry unpackables:
    Operations, Contracts, and BigMaps.
SCaml functions (except entry points) cannot have
free variables of unpackable types:
Error: [ESCaml400] Function body cannot have 
a free variable occurrence `x` with 
unpackable type.
Surprises on closures: Example
ops is a free in fun c ­> ...
and its type is unpackable operation list
List.fold_left (fun ops ­> fun c ­> 
  Operation.transfer_tokens () (Tz 1.) c  
  :: ops) 
  [] contracts 
 
Error: [ESCaml400] Function body cannot have 
a free variable occurrence `ops` with 
unpackable type.
Surprises on closures: Mitigation
Use uncurried version:
List.fold_left' (fun (ops, c) ­> 
  Operation.transfer_tokens () (Tz 1.0) c 
  :: ops) 
  ([], contracts)
SCaml eco system
Merlin
IDE framework for Emacs, Vim, VSCode
OCamlFormat
Reformatter/Indenter
SCaml in Dune
Almost unable to use scamlc in Dune build system.
Dune is not forgiving once you step away from the
standard OCaml development.
SCaml in Dune: scaml.ppx
SCaml compiler integrated into OCaml PPX.
Allows SCaml compilation in Dune workflow:
SCaml code is pre-compiled and embeded in OCaml object files.
OCaml executable to link SCaml code and emit Michelson.
module Contract = struct 
  [@@@SCaml] (* Smart contract part *) 
  let [@entry] default () _ = ... 
end 
 
let () = SCamlc.Ppx.emit ~outputprefix:"out"
SCaml in Dune: scaml.ppx
OCaml code now can have SCaml code inside:
structures tagged with [@@@SCaml].
Possibilities:
Test code in OCaml
Simulation driver in OCaml
Sharing server side and client code
SCaml errors in Merlin
scaml.ppx makes Merlin browsable SCaml specific
errors on the fly.
SCaml with Reason
ReasonML is just another syntax of OCaml.
ReasonML to SCaml to Michelson almost for free.
Candies
Not quite useful to me but some people love:
TrySCaml (compiling SCaml compiler to JS)
SCaml Blocky (using OCaml Blocky)
Interop
Interop between Camls with typerep
ppx_typerep_conv: embed type def info in OCaml.
type t = Foo of int | Bar  
[@@deriving typerep] 
          
module Smart_contract = struct 
  [@@@SCaml] 
  let [@entry] default () _ =  
    [], Foo (Int 42) 
end
Interop between Camls with typerep
SCaml to Michelson:
Michelson to SCaml:
SCaml type to Michelson type in OCaml:
SCamlc.Typerep.to_micehlson typerep_of_t  
  (Foo (Int 42))
SCamlc.Typerep.of_micheline typerep_of_t  
  "{ Right 42 }"
SCamlc.Typerep.to_michelson_type 
  typerep_of_t
Typesafe pack/unpack simulation
Original pack/unpack cannot be simulated:
Extend with typerep:
OCaml can pack’/unpack’ type-safely.
SCaml ignores typerep arguments.
Obj.pack : 'a ­> bytes 
Obj.unpack : bytes ­> 'a option
pack' : 'a typerep ­> 'a ­> bytes 
unpack' : 'a typerep ­> bytes ­> 'a option
Simulation
SCaml.ml: OCaml simualtion of SCaml primitives.
Things to do:
Blockchain state
Semantics of operations
Globals (NOW, AMOUNT, etc)
Must be done
Test framework
Michelson test
Against (sandbox|test net) using (Flextesa|Tezt)
Simulation test
Unit test/QCheck using simulation in OCaml
Internal
Compilation path
Parsing by OCaml parser
Typing by OCaml type checker
Unifying types for entry points and storage
Translation to an IL, pure monomorhpic core ML
(Code with unsupported language features are rejected.)
Optimization
Compilation to Michelson
Unifying types for entry points and
storage
Frees us from writing type constraits around
[@entry].
Translation to an intermediate language
Convert to IML, an almost pure core ML:
Rejects unsupported OCaml features
Disintegrate OCaml types to binary type combinations
(pairs/sums)
Pattern match compilation
Optimization
Same as :
K-normalization
Beta/Assoc/Inline/Elim loop
Reverse K-normalization
Reverse K-norm is required since in our Michelson
compilation:
stack depth = size of typing environment.
MinCaml
Compilation to Michelson
Compilation keeps the SCaml typing environment
and Michelson stack isomorphic.
This makes algorithm simple but stack tends deeper
and deeper.
Some efforts required
SCam Language
A scam never calls it a scam.
https://gitlab.com/dailambda/scaml

SCaml update 2020-06

  • 1.
    DaiLambda, Inc. Jun FURUSE/古瀬淳 Kyoto,2020-06-25 https://scamlang.dev
  • 2.
    What is SCaml Yetanother compiler from OCaml to Michelson. “Smart Contract Abstract Machine Language” For Smart contracts Strict Subset of OCaml Small (7500 loc.).
  • 3.
    Strict Subset ofOCaml Valid SCaml program is valid OCaml program. No special features for smart contracts. Some OCaml features are disabled: No recursion No polymoprhism No ML functors No objects No mutability
  • 4.
    Small Built over OCaml’scompiler­libs: Reusing OCaml’s parser and type-checker. SCaml compiles OCaml’s typed AST to Michelson. The first version was in 3000 loc written in 5 days.
  • 5.
    and Serious Serious compiler. Allthe Michelson opcodes are supported. Optimizations. Carthage ready (i.e. entry points, closures)
  • 6.
    Benefit of beingStrict Subset OCaml programmers can use SCaml immediately. Newbies can learn SCaml via OCaml tutorial. Many OCaml eco-system tools can be used for free: Menhir, Tuareg, indender, reformatter Dune (build system) PPX, P4, ReasonML
  • 7.
    Possibilities of beingStrict Subset Simluation in native code Native compilation with simulated primitives: dApp development in one language Contracts: to Michelson by SCaml UI: to JS by JSOO Server: to native by OCaml Certification in Coq and F*
  • 8.
    Availability Docker images OPAM opam install scaml (requires OCaml4.09.1) Source https://hub.docker.com/layers/dailambda/scaml https://gitlab.com/dailambda/scaml
  • 9.
  • 10.
    Start with open SCaml SCamlis the standard library for SCaml: Ordinary Stdlib is not working. open SCaml
  • 11.
    Entry points with[@entry] Allowed only in the last linked module: let [@entry] f param storage = ... val f : param_ty           ­> storage_ty           ­> SCaml.operation list * storage_ty
  • 12.
    Simplest smart contract Doesnothing: Compilation; let [@entry] default () () = [], () $ scamlc nothing.ml  Linking Nothing  (outputs nothing.tz)
  • 13.
    Numeralic types int,nat, tz Int (­12) Nat 42 Tz 1.23 (in tez, not micro tez) with monomorphic operators: (+), (+^),(+$)
  • 14.
    Options, Lists, Sets,Maps Some 1 [ Int 1; Int 2; Int 3 ] Set [ Nat 1; Nat 2; Nat 3 ] Map [ (Int 1, "one"), (Int 2, "two") ] Set and Map only take constants for now.
  • 15.
    Blockchain related constants Instyle of a constructor + a string constant: Key_hash "tz1KqTpEZ7Yob7QbPE4Hy4.." Signature "edsigtteMcYkviZ3rTaM6N7DW.." Timestamp "2019­09­11T08:30:23Z"
  • 16.
    Pairs, Sums, Variants,and Records Compiled down to pairs and sums. Using right balanced tree, with optimization for nullary variants (like OCaml)
  • 17.
    Full pattern match Nestedpatterns Or patterns Guards Non-exhaustive check TODO: Pattern match heuristics for efficiency
  • 18.
    Modules module M = struct .. end for code grouping Nomodule aliases and functors Link of multiple *.ml files scamlc a.ml b.ml c.ml
  • 19.
    Exceptions User definable Reported as(Pair "Module.My_error" 1) in Michelson. Exception is not catchable. (* module.ml *)  exception My_error of int    raise (My_error (Int 1))
  • 20.
    SCaml specific errors Errornumber to indicate the nature: Easy to distinguish OCaml errors and SCaml ones. [ESCaml000] SCaml does not support objects
  • 21.
  • 22.
    Surprises on closures Michelsonclosure must be packable. Its environment cannot carry unpackables:     Operations, Contracts, and BigMaps. SCaml functions (except entry points) cannot have free variables of unpackable types: Error: [ESCaml400] Function body cannot have  a free variable occurrence `x` with  unpackable type.
  • 23.
    Surprises on closures:Example ops is a free in fun c ­> ... and its type is unpackable operation list List.fold_left (fun ops ­> fun c ­>    Operation.transfer_tokens () (Tz 1.) c     :: ops)    [] contracts    Error: [ESCaml400] Function body cannot have  a free variable occurrence `ops` with  unpackable type.
  • 24.
    Surprises on closures:Mitigation Use uncurried version: List.fold_left' (fun (ops, c) ­>    Operation.transfer_tokens () (Tz 1.0) c    :: ops)    ([], contracts)
  • 25.
  • 26.
    Merlin IDE framework forEmacs, Vim, VSCode
  • 27.
  • 28.
    SCaml in Dune Almostunable to use scamlc in Dune build system. Dune is not forgiving once you step away from the standard OCaml development.
  • 29.
    SCaml in Dune:scaml.ppx SCaml compiler integrated into OCaml PPX. Allows SCaml compilation in Dune workflow: SCaml code is pre-compiled and embeded in OCaml object files. OCaml executable to link SCaml code and emit Michelson. module Contract = struct    [@@@SCaml] (* Smart contract part *)    let [@entry] default () _ = ...  end    let () = SCamlc.Ppx.emit ~outputprefix:"out"
  • 30.
    SCaml in Dune:scaml.ppx OCaml code now can have SCaml code inside: structures tagged with [@@@SCaml]. Possibilities: Test code in OCaml Simulation driver in OCaml Sharing server side and client code
  • 31.
    SCaml errors inMerlin scaml.ppx makes Merlin browsable SCaml specific errors on the fly.
  • 32.
    SCaml with Reason ReasonMLis just another syntax of OCaml. ReasonML to SCaml to Michelson almost for free.
  • 33.
    Candies Not quite usefulto me but some people love: TrySCaml (compiling SCaml compiler to JS) SCaml Blocky (using OCaml Blocky)
  • 34.
  • 35.
    Interop between Camlswith typerep ppx_typerep_conv: embed type def info in OCaml. type t = Foo of int | Bar   [@@deriving typerep]             module Smart_contract = struct    [@@@SCaml]    let [@entry] default () _ =       [], Foo (Int 42)  end
  • 36.
    Interop between Camlswith typerep SCaml to Michelson: Michelson to SCaml: SCaml type to Michelson type in OCaml: SCamlc.Typerep.to_micehlson typerep_of_t     (Foo (Int 42)) SCamlc.Typerep.of_micheline typerep_of_t     "{ Right 42 }" SCamlc.Typerep.to_michelson_type    typerep_of_t
  • 37.
    Typesafe pack/unpack simulation Originalpack/unpack cannot be simulated: Extend with typerep: OCaml can pack’/unpack’ type-safely. SCaml ignores typerep arguments. Obj.pack : 'a ­> bytes  Obj.unpack : bytes ­> 'a option pack' : 'a typerep ­> 'a ­> bytes  unpack' : 'a typerep ­> bytes ­> 'a option
  • 38.
    Simulation SCaml.ml: OCaml simualtionof SCaml primitives. Things to do: Blockchain state Semantics of operations Globals (NOW, AMOUNT, etc) Must be done
  • 39.
    Test framework Michelson test Against(sandbox|test net) using (Flextesa|Tezt) Simulation test Unit test/QCheck using simulation in OCaml
  • 40.
  • 41.
    Compilation path Parsing byOCaml parser Typing by OCaml type checker Unifying types for entry points and storage Translation to an IL, pure monomorhpic core ML (Code with unsupported language features are rejected.) Optimization Compilation to Michelson
  • 42.
    Unifying types forentry points and storage Frees us from writing type constraits around [@entry].
  • 43.
    Translation to anintermediate language Convert to IML, an almost pure core ML: Rejects unsupported OCaml features Disintegrate OCaml types to binary type combinations (pairs/sums) Pattern match compilation
  • 44.
    Optimization Same as : K-normalization Beta/Assoc/Inline/Elimloop Reverse K-normalization Reverse K-norm is required since in our Michelson compilation: stack depth = size of typing environment. MinCaml
  • 45.
    Compilation to Michelson Compilationkeeps the SCaml typing environment and Michelson stack isomorphic. This makes algorithm simple but stack tends deeper and deeper. Some efforts required
  • 46.
    SCam Language A scamnever calls it a scam. https://gitlab.com/dailambda/scaml