Commit 6522fed8 authored by Dario Pinto's avatar Dario Pinto
Browse files

port comments, borderless cards on index

parent 0ed30bf4
......@@ -59,3 +59,22 @@ File "/home/mi/Bureau/po.why", line 3017, characters 1-2450:Valid (0.8750) (222)
[ Acknowledgement: this work is financially supported by the [BWare project]( ]
# Comments
Joshua Pratt (10 January 2020 at 5 h 20 min):
> Can the compiled alt-ergo.js be uploaded to npm? I’d love to use it in a web page I’m working on.
OCamlPro (6 March 2020 at 16 h 03 min):
> Hi Joshua, thanks for passing by 🙂 We have no plans of building a bridge between a version of Alt-Ergo in JS and npm. However, you can tweak Alt-Ergo to suit your needs! We would recommend taking a look at Try Why3, where you will find a JavaScript version of Alt-Ergo. You can follow their instructions to build Alt-Ergo in JavaScript
Bharat Jayaraman (26 February 2020 at 17 h 37 min):
> This is VERY USEFUL tool!
> I am using it in a course on software verification here in Buffalo. It’s great for checking verification conditions.
> Many thanks,
> Bharat
OCamlPro (6 March 2020 at 16 h 04 min):
> Hi Bharat! Thank you for your message, we are always glad to hear from our users! If you feel so inclined, you can drop us an email at to tell us more about your experience with Alt-Ergo and any feedback you may have.
......@@ -325,3 +325,23 @@ For some low level packed bitfield manipulation you can have a look at [some mor
## Conclusion
So if you want to write non allocating code in OCaml, turn everything in CPS, add additional arguments everywhere, turn your sum types in unboxed GADTs, manipulate a single large bigarrays. And enjoy !
# Comments
Gaetan Dubreil (3 April 2016 at 11 h 16 min):
> Thank you for this attractive and informative post.
> Just to be sure, is it not ‘t’ rather than ‘l’ that must be past to the fold_left function?
> You said “we only have tail calls now” but I don’t see any none tail calls in the first place, am I wrong?
Pierre Chambart (4 April 2016 at 14 h 48 min):
> There where effectively some typos. Thanks for noticing.
> There is one non-tail call in fold_left: the call to f. But effectively the recursion is tail.
kantien (25 May 2016 at 13 h 57 min):
> Interesting article, but i have one question. Can we say, from the proof theory point of view, that turning the code in CPS style not to allocate is just an application of the Gentzen’s cut-elimination theorem ?
> I explain in more details this interpretation : if we have a proof P1 of the proposition A and a proof P2 of the proposition A ⇒ B, we can produce a proof P3 of proposition B by applying the cut rule or modus ponens, but the theorem says that we can eliminate the use of cut rule and produce a direct proof P4 of the proposition B. But modus ponens (or cut rule) is just the rule for typing function application : if f has type ‘a -> ‘b and x has type ‘a then f x has type ‘b. And so the cut-elimination theorem says that we can produce an object of type ‘b without allocate an object of type ‘a (this is not necessary to produce the P1 proof, or more exactly this is not necessary to put the P1’s conclusion in the environment in order to use it as a premise of the P2 proof ). Am I right ?
jdxu (4 January 2021 at 11 h 36 min):
> Very useful article. BTW, is there any document/tutorial/article about cmm syntax?
......@@ -130,3 +130,22 @@ works.
> NOTE: this article is cross-posted on []( and [](/blog).
# Comments
Louis Gesbert (16 March 2017 at 14 h 31 min):
> Some discussion on a better naming and making some parts of this more widely available in the opam CLI is ongoing at
Hez Carty (16 March 2017 at 17 h 23 min):
> Is it possible/planned to support sharing of compilers across local (or global) switches? It would be very useful to have a global 4.04.0+flambda switch including only the compiler itself or the compiler + basic tools like ocp-indent and merlin. Then a number of projects could share this base installation but have their own locally installed dependencies without duplicating the entire build time per-project.
Louis Gesbert (17 March 2017 at 10 h 10 min):
> Sharing compilers, or other packages across switches is not supported at the moment. However:
> You can still use the global `system compiler` on any switch, local or not, to avoid its recompilation
> What is planned, as a first step, for after the 2.0 release, is to add a cache of compiled packages. Hooks are already in place to allow this, and opam is able to track the files installed by each package already, so the most difficult part is probably going to be the relocation issues with OCaml itself.
> A cache is an easier solution to warrant consistency: with shared switches, the problem of reinstallations and keeping everything consistent gets much more complex — what happens when you change the compiler of your “master” switch ?
Hez Carty (20 March 2017 at 16 h 46 min):
> That sounds great, thank you. Should make this kind of local switch more useful when working with large numbers of projects.
......@@ -399,3 +399,9 @@ And that's it !
Of course that's a bit cheating since the program is not executable, but who cares really ?
If you want to use it, I made a small (ugly) [script]( generating those types. You can try it on bigger problems, but in fact it is a bit exponential. So you shouldn't really expect an answer too soon.
# Comments
Louis Gesbert (28 April 2017 at 8 h 11 min):
> Brilliant!
......@@ -108,3 +108,16 @@ still need to install tools that are tightly bound to a compiler version, like
> []( and
> [](/blog).
# Comments
Jeremie Dimino (11 May 2017 at 8 h 27 min):
> Thanks, that seems like a useful feature. Regarding relocation of the compiler, shouldn’t it be enough to set the environment variable OCAMLLIB? AFAIK the stdlib directory is the only hardcoded path on the compiler.
Louis Gesbert (11 May 2017 at 8 h 56 min):
> Last I checked, there were a few more problematic points, in particular generated bytecode executables statically referring to their interpreter; but yes, in any case, it’s worth experimenting in that direction using the new hooks, to see how it works in practice.
Jeremie Dimino (12 May 2017 at 9 h 13 min):
> Indeed, I remember that we had a similar problem in the initial setup to test the public release of Jane Street packages: we were using long paths for the opam roots and the generated #! where too long for the OS… What I did back then is write a program that scanned the tree and rewrote the #! to use “#!/usr/bin/env ocamlrun”.
> That could be an option here. The rewriting only need to be done once, since the compiler uses `ocamlc -where`/camlheader when generating a bytecode executable.
......@@ -71,3 +71,15 @@ A few other new options have been added to `opam install` and related commands,
- `opam install --working-dir` uses the working directory state of your project, instead of the state registered in the version control system. Don't worry, opam will warn you if you have uncommitted changes and forgot to specify `--working-dir`.
> NOTE: this article is cross-posted on []( and [](/blog).
# Comments
Hez Carty (4 May 2017 at 21 h 30 min):
> Would a command like “opam init $DIR” and “opam init $DIR –deps-only” work for an auto-intialization interface? Ideally creating the equivalent to a bare .opam/ using $DIR as $OPAMROOT + install a local switch + “opam install .” (with –deps-only if specified) under the newly created switch.
Louis Gesbert (5 May 2017 at 7 h 50 min):
> `opam init DIR` is currently used and means “use DIR as your initial, default package repository”.
> Overloading `opam init` sounds like a good approach though, esp. since the default of the command is already to create an initial switch. But a new flag, e.g. `opam init –here`, could be used to mean: do `opam init –bare` (it’s idempotent), `opam switch create .` and then `opam install .`.
> The issue that remains is inherent to compound commands: we would have to port e.g. the `–deps-only` option to `opam init`, making the interface and doc heavier, and it would only make sense in this specific use-case ; either that or limit the expressivity of the compound command, requiring people to fallback to the individual ones when they need some more specific features.
......@@ -263,3 +263,26 @@ We have seen how to compile, deploy, call and examine Liquidity contracts on the
- Slides in [English](
- and [French](
# Comments
fredcy (9 February 2018 at 3 h 14 min):
> It says “Here we define a type abbreviation votes […]” but I don’t see any `votes` symbol in the nearby code.
> [Still working through the document. I’m eager to try Liquidity rather than write in Michelson.]
alain (9 February 2018 at 7 h 18 min):
> You are right, thanks for catching this. I’ve updated the contract code to use type `votes`.
branch (26 February 2019 at 18 h 28 min):
> Why the “Deploy” button can be inactive, while liquidity contract is compiled successfully?
alain (6 March 2019 at 15 h 09 min):
> For the Deploy button to become active, you need to specify an initial value for the storage directly in the code of the smart contract. This can be done by writing a constant directly or a function.
let%init storage = (* the value of your initial storage*)
let%init storage x y z = (* the value of your initial storage, function of x, y and z *)
......@@ -283,3 +283,18 @@ tezos-client transfer 10 from my_account to KT1GgUJwMQoFayRYNwamRAYCvHBLzgorLoGo
**Alain Mebsout**: Alain is a senior engineer at OCamlPro. Alain was involved in Tezos early in 2017, participating in the design of the ICO infrastructure and in particular, the Bitcoin and Ethereum smart contracts. Since then, Alain has been developing the Liquidity language, compiler and online editor, and has started working on the verification of Liquidity smart contracts. Alain also contributed some code in the Tezos node to improve Michelson. Alain holds a PhD in Computer Science on formal verification of programs.
# Comments
Luiz Milfont (14 December 2018 at 17 h 21 min):
> Hello Mr. Alain Mebsout. My name is Milfont and I am the author of TezosJ SDK library, that allows to interact with Tezos blockchain through Java programming language.I did’t know this game before and got interested. I wonder if you would like me to create an Android version of your game, that would be an Android APP that would create a wallet automatically for the player and then he would pull a jackpot handle, sending the transaction with the parameters to your smart contract. I would like to know if you agree with this, and allow me to do it, using your already deployed game. Thanks in advance. Milfont. Twitter: @luizmilfont
michsell (1 October 2019 at 15 h 29 min):
> Hello Alain,
> I just played the game you designed, the problem is I cannot get any feedback even that 1utz for losing the game. Is the game retired? If so, can anyone help to remove it from tzscan dapps page: Also, by any chance I may get the tezzies back…
> Many thanks!
> Best regards,
> Michshell
......@@ -335,3 +335,12 @@ signature in the run, preapply and injection RPCs ?
If we can reply to these questions, we will also be able to sign
operations offline.
# Comments
lizhihohng (5 May 2019 at 6 h 59 min):
> Before forge or sign a transaction, how to get a gas or gas limit, not a hard gas limit from contants?
Juliane (16 November 2019 at 15 h 29 min):
> Good answer back in return of this difficulty with solid arguments and explaining all on the topic of that.
......@@ -212,4 +212,72 @@ Secp256k1 keys (same as Bitcoin/Ethereum) and `tz3` for P256 keys;
finally, a realistic wallet would probably use cryptographic chips, on
a mobile phone or an external device (Ledger, etc.).
# Comments
Anthony (28 November 2018 at 2 h 01 min):
> Fabrice, you talk about signing the operation using tezos-client, which can then be used with the run_operation, however when . you talk about doing it in a script, it doesn’t include the edsig or checksum or converted back into a usable form for run_operations. Can you explain how this is done in a script?
> Thanks
> Anthony
Fabrice Le Fessant (29 November 2018 at 15 h 07 min):
> You are right, `run_operation` needs an `edsig` signature, not the hexadecimal encoding. To generate the `edsig`, you just need to use the reverse operation of `base58check.b58decode`, i.e. `base58check.b58encode`, on the concatenation of 3 byte arrays:
> 1/ the 5-bytes prefix that will generate the initial `edsig` characters, i.e. `0x09f5cd8612` in hexadecimal
> 2/ the raw signature `s`
> 3/ the 4 initial bytes of a checksum: the checksum is computed as `sha256(sha256(s))`
Badalona (27 December 2018 at 13 h 13 min):
> Hi Fabrice.
> I will aprreciate if you show the coding of step 3. My checksum is always wrong.
> Thanks
Alain (16 January 2019 at 16 h 26 min):
> The checksum is on prefix + s.
> Here is a python3 script to do it:
> ./ 637e08251cae646a42e6eb8bea86ece5256cf777c52bc474b73ec476ee1d70e84c6ba21276d41bc212e4d878615f4a31323d39959e07539bc066b84174a8ff0dedsigtkpiSSschcaCt9pUVrpNPf7TTcgvgDEDD6NCEHMy8NNQJCGnMfLZzYoQj74yLjo9wx6MPVV29CvVzgi7qEcEUok3k7AuMg
from pyblake2 import blake2b
import hashlib
import base58check
import ed25519
import sys
def sha256 (x) :
return hashlib.sha256(x).digest()
def b58check (prefix, b) :
x = prefix + b
checksum = sha256(sha256(x))[0:4]
return base58check.b58encode(x + checksum)
edsig_prefix = bytes([9, 245, 205, 134, 18])
hexsig = sys.argv[1]
bytessig = bytes.fromhex(hexsig)
b58sig = b58check (edsig_prefix, bytessig)
Anthony (29 November 2018 at 21 h 49 min):
> Fabrice,
> Thanks for the information would you be able to show the coding as you have done in your blog?
> Thanks
> Anthony
Mark Robson (9 February 2020 at 23 h 51 min):
> Great information, but can the article be updated to include the things discussed in the comments? As I can’t see the private key of bootstrap1 I can’t replicate locally. Been going around in circles on that point
stacey roberts (7 May 2020 at 13 h 53 min):
> Can you help me to clear about how tezos can support to build a fully decentralized supply chain eco system?
leesadaisy (16 September 2020 at 10 h 25 min):
> Hi there! Thanks for sharing useful info. Keep up your work.
Alice Jenifferze (17 September 2020 at 10 h 51 min):
> Thanks for sharing!
......@@ -123,3 +123,11 @@ in the public Tezos code base. We will inform you as soon as our Pull
Request is ready, for more testing ! If all testing and review goes
well, we hope it can be merged in the next release !
# Comments
Jack (30 January 2019 at 15 h 30 min):
> Please release this as a MR on gitlab so those of us not using docker can start testing the code.
Fabrice Le Fessant (10 February 2019 at 15 h 39 min):
> That was done: [here](/2019/02/04/improving-tezos-storage-gitlab-branch-for-testers/)
......@@ -21,3 +21,72 @@ migrate the database back to Irmin (and terminate the node
Enjoy and send us feedback !!
# Comments
AppaDude (10 February 2019 at 15 h 12 min):
> I must be missing something. I compiled and issued the required rpc trigger:
> /storage/context/gc with the command
> ~/tezos/tezos-client rpc get /storage/context/gc
> But I just got an empty JSON response of {} and the size of the .tezos-node folder is unchanged. Any advice is much appreciated.
> Thank you!
Fabrice Le Fessant (10 February 2019 at 15 h 47 min):
> By default, garbage collection will keep 9 cycles of blocks (~36000 blocks). If you have fewer blocks, or if you are using Irontez on a former Tezos database, and fewer than 9 cycles have been stored in Irontez, nothing will happen. If you want to force a garbage collection, you should tell Irontez to keep fewer block (but more than 100, that’s the minimum that we enforce):
> ~/tezos/tezos-client rpc get ‘/storage/context/gc?keep=120’
> should trigger a GC if the node has been running on Irontez for at least 2 hours.
AppaDude (10 February 2019 at 16 h 04 min):
> I think it did work. I was confused because the total disk space for the .tezos-node folder remained unchanged. Upon closer inspection, I see these contents and sizes:
> These are the contents of .tezos-node, can I safely delete context.backup?
> 4.0K config.json
> 269M context
> 75G context.backup
> 4.0K identity.json
> 4.0K lock
> 1.4M peers.json
> 5.4G store
> 4.0K version.json
> Is it safe to delete context.backup if I do not plan to revert? (/storage/context/revert)
Fabrice Le Fessant (10 February 2019 at 20 h 51 min):
> Yes, normally. Don’t forget it is still under beta-testing…
> Note that `/storage/context/revert` works even if you remove `context.backup`.
Jack (23 February 2019 at 0 h 24 min):
> Have there been any issues reported with missing endorsements or missing bakings with this patch? We have been using this gc version ( for the past month and ever since we switched we have been missing endorsements and missing bakings. The disk space savings is amazing, but if we keep missing ends/bakes, it’s going to hurt our reputation as a baking service.
Fabrice Le Fessant (23 February 2019 at 6 h 58 min):
> Hi,
> I am not sure what you are asking for. Are you using our version (, or the one on the Tezos repository ? Our version is very different, so if you are using the other one, you should contact them directly on the merge request. On our version, we got a report last week, and the branch has been fixed immediately (but not yet the docker images, should be done in the next days).
Jack (25 February 2019 at 15 h 53 min):
> I was using the 720MR and experiencing issues with baking/endorsing. I understand that 720MR and IronTez are different. I was simply asking if your version has had any reports of baking/endorsing troubles.
Jack (25 February 2019 at 15 h 51 min):
> Is there no way to convert a “standard node” to IronTez? I was running the official tezos-node, and my datadir is around 90G. I compiled IronTez and started it up on that same dir, then ran `rpc get /storage/context/gc` and nothing is happening. I thought this was supposed to convert my datadir to irontez? If not, what is the RPC to do this? Or must I start from scratch to be 100% irontez?
Fabrice Le Fessant (25 February 2019 at 16 h 24 min):
> There are two ways to get a full Irontez DB:
> - Start a node from scratch and wait for one or two days…
> - Use an existing node, run Irontez on it for 2 hours, and then call `rpc get /storage/context/gc?keep=100` . 100 is the number of blocks to be kept. After 2 hours, the last 120 blocks should be stored in the IronTez DB, so the old DB will not be used anymore. Note that Irontez will not delete the old DB, just rename it. You should go there and remove the file to recover the disk space.
Jack (27 February 2019 at 1 h 24 min):
> Where do we send feedback/get help? Email? Slack? Reddit?
Banjo E. (3 March 2019 at 2 h 40 min):
> There is a major problem for bakers who want to use the irontez branch. After garbage collection, the baker application will not start because the baker requests a rpc call for the genesis block information. That genesis block information is gone after the garbage collection. Please address this isssue soon. Thank you!
Fabrice Le Fessant (6 March 2019 at 21 h 44 min):
> I pushed a new branch with a tentative fix: . Unfortunately, I could not test it (I am far away from work for two weeks), so feedback is really welcome, before pushing in the irontez branch.
......@@ -99,3 +99,8 @@ node.
> Don’t hesitate to contact us if you want to deploy a blockchain with IronTez, or for more information !
# Comments
Kristen (3 May 2019 at 0 h 30 min):
> I really wanted to keep using IronTez but I ran into bugs that have not yet been fixed, the code is out of date with upstream, and there is no real avenue for support/assistance other than email.
......@@ -94,3 +94,14 @@ These improvements are still very much a work in progress. We have not reached t
This does not mean there are no news to enjoy before our efforts show on the mainstream compiler! While working on Flambda 2.0, we did deploy a number of patches on the compiler both before and after the Flambda stage. We proposed all the changes independant enough to be proposed on their own. Some of these fixes have been merged already. Others are still under discussion and some, like the recursive values patch mentioned above, are still waiting for cleanup or documentation before submission.
# Comments
Jon Harrop (30 August 2019 at 20 h 11 min):
> What is the status of multicore OCaml?
Vincent Laviron (2 September 2019 at 16 h 22 min):
> OCamlPro is not working on multicore OCaml. It is still being worked on elsewhere, with efforts concentrated around OCaml Labs, but I don’t have more information than what is publicly available. All of the work we described here is not expected to interfere with multicore.
Lindsay (25 September 2020 at 20 h 20 min):
> Thanks for your continued work on the compiler and tooling! Am curious if there is any news regarding the item “Separate compilation of recursive modules”.
......@@ -141,3 +141,24 @@ And here we are with 4.08, in the present day! We can now put exceptions under o
We did not add 4.09 to this journey to the past, as this release is still solidly in the *now* at the time of this blogpost. Rest assured, we will see much more awesome features in OCaml in the future! In the meantime, we are working on updating more cheat sheets: keep posted!
# Comments
Micheal Bacarella (23 September 2019 at 18 h 17 min):
> For a blog-post from a company called OCaml PRO this seems like a rather tone-deaf PR action.
> I wanted to read this and get hyped but instead I’m disappointed and I continue to feel like a chump advocating for this language.
> Why? Because this is a rather underwhelming summary of *8 years* of language activity. Perhaps you guys didn’t intend for this to hit the front of Hacker News, and maybe this stuff is really exciting to programming language PhDs, but I don’t see how the average business OCaml developer would relate to many of these changes at all. It makes OCaml (still!) seem like an out-of-touch academic language where the major complaints about the language are ignored (multicore, Windows support, programming-in-the-large, debugging) while ivory tower people fiddle with really nailing type-based selection in GADTs.
> I expect INRIA not to care about the business community but aren’t you guys called OCaml PRO? I thought you *liked* money.
> You clearly just intended this to be an interesting summary of changes to your cheatsheet but it’s turned into a PR release for the language and leaves normals with the continued impression that this language is a joke.
Thomas Blanc (24 September 2019 at 14 h 57 min):
> Yes, latency can be frustrating even in the OCaml realm. Thanks for your comment, it is nice to see people caring about it and trying to remedy through contributions or comments.
> Note that we only posted on expecting to get one or two comments. The reason for this post was that while updating the CS we were surprised to see how much the language had changed and decided to write about it.
> You do raise some good points though. We did work on a full windows support back in the day. The project was discontinued because nobody was willing to buy it. We also worked on memory profiling for the debugging of memory leaks (before other alternatives existed). We did not maintain it because the project had no money input. I personally worked on compile-time detection of uncaught exception until the public funding of that project ran out. We also had a proposal for namespaces in the language that would have facilitated programming-in-the-large (no funding) and worked on multicore (funding for one man for one year).
......@@ -251,4 +251,24 @@ The different strategies are:
Remember that whatever works best for you, it’s still better than having to `malloc` and `free` by hand. Happy allocating!
# Comments
gasche (23 March 2020 at 17 h 50 min):
> What about higher overhead values than 120, like 140, 160, 180 and 200?
Thomas Blanc (23 March 2020 at 18 h 17 min):
> Because 100 was the overhead value Leo advised in the PR discussion I decided to put it in the results. As 120 got the same maximum heap size as next-fit I found it worth putting it in. Higher overhead values lead to faster execution time but a bigger heap.
> I don’t have my numbers at hand right now. You’re probably right that they are relevant (to you and Damien at least) but I didn’t want to have a huge table at the end of the post.
nbbb (24 March 2020 at 11 h 18 min):
> Higher values would allow us to see if best-fit can reproduce the performance characteristics of next-fit, for some value of the overhead.
nbbb (24 March 2020 at 16 h 51 min):
> I just realized that 120 already has a heap as bit as next-fit — so best-fit can’t get as good as next-fit in this example, and higher values of the overhead are not quite as informative. Should have read more closely the first time.
Thomas Blanc (24 March 2020 at 16 h 55 min):
> Sorry that it wasn’t as clear as it could be.
> Note that opam and dose are in the best-case scenario of best-fit. Your own code would probably produce a different result and I encourage you to test it and communicate about it.
......@@ -195,3 +195,24 @@ This proof of concept shows how functor packs can ease some complicated build sy
Packs were an old concept mainly outdated by module aliases. They were not practical as they are some sort of monolithic libraries shaped into a unique module containing sub modules. While they perfectly use the module system for its namespacing properties, their usage enforces the compiler to link an entire library even if only one module is actually used. This improvement allows programmers to define big functors, functors that are split among multiple files, resulting in what we can view as a way to implement some form of parameterized libraries.
In the second part, we will cover another aspect of the rehabilitation of packs: using packs to implement mutually recursive compilation units.
# Comments
François Bobot (25 September 2020 at 9 h 16 min):
> I believe there is a typo
module Mylib (P : P_SIG) = struct
module A = A_funct(P)
module B = A_funct(P)
> The last must be `B_funct(P)`, the next example as also the same typo.
Pierrick Couderc (25 September 2020 at 10 h 31 min):
> Indeed, thank you!
Cyrus Omar (8 February 2021 at 3 h 49 min):
> This looks very useful! Any updates on this work? I’d like to be able to use it from dune.
......@@ -9,7 +9,7 @@ We have years of experience on the research and development of programming langu
<br />
<div class="row">
<div class="col-4">
<div class="card bg-transparent" >
<div class="card bg-transparent border-0" >
<img src="assets/img/home_industry.png" />
<div class="card-body">
<h5 class="card-title">For industrial partners who face challenges</h5>
......@@ -18,7 +18,7 @@ We have years of experience on the research and development of programming langu
<div class="col-4">
<div class="card bg-transparent" >
<div class="card bg-transparent border-0" >
<img src="assets/img/home_research.png" />
<div class="card-body">
<h5 class="card-title">For R&amp;D labs who need collaboration</h5>
......@@ -27,7 +27,7 @@ We have years of experience on the research and development of programming langu
<div class="col-4">
<div class="card bg-transparent" >
<div class="card bg-transparent border-0" >
<img src="assets/img/home_dev.png" />
<div class="card-body">
<h5 class="card-title">For developers to reach mastery</h5>
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment