writing an amino code-generator, #1: introduction
tomino is a new small side-project of mine. it has two objectives: creating encoders/decoders in other languages; and making faster, code-generated un/marshalers for go.
there are many reasons, as a developer in gno, to be upset about amino. it is not a particularly transparent codebase and it has received very few improvements in many months of development. as i explored last saturday, it also has some gotchas when using it. it has little proper "specifications", and it cannot be easily brought over for usage to other programming languages; partly because it's a very reflect-heavy library to begin with.
after i finished the last post, and thought about it a bit, i was thinking:
- it would be nice if amino supported other languages.
- it would be nice if how amino translated to binary was transparent and understandable.
- it would be nice if there was a way for the library to decouple the marshaling from its related "types"; so that you don't have to import the
sdk/vm
package to use its related types (but can). - it would be nice if we had better specified and clearer behaviour for amino's functioning, so that it's not just a black-box that tackles encoding and decoding.
and thus, tomino is born.

tomino has a couple of basic ideas:
- from a selected list of types/packages, we can do static code analysis to determine what types are being used to marshal with amino; and then we can create an "intermediate representation" that summarizes what types should be marshaled, and how each of them should be encoded/decoded.
- from the "intermediate representation", we can create code-generated destination marshalers and unmarshalers. in go, but also any other language.
the first step, in particular, isn't new. it's essentially how protoc
is working; except that instead of using .proto
files as a source of truth, we use .go
files.
here's a diagram showing the idea:
the intention is to try to make this happen with a small (<5000 LOC) codebase, which can then be reviewed to make explainable, and to match 1-1 with the outputs from amino. then, writing good specifications on how the un/marshalers work; and consequently how developers can use the IR to write their own un/marshalers.
if this looks interesting, you're welcome to take a look and/or contact me. i'll be working on this on and off, as a side project. i agreed with others in the project that it's not urgent; but i think it's an idea with good potential, solving a considerable problem we have in gno and which will be exacerbated the further on we continue with it.
i decided to write "part 1" in the title, because aside from this post, i think there'll be a few more updates at least, and i'll delve a bit more into how this thing works / techniques used. for now, it doesn't even marshal all of the structures i want it to; and i didn't get it to do unmarshaling yet, either, so things are too much in flux to blog about them. but as the dust settles, hopefully i'll be able to tell you some more.