howl.moe

gno: gonative is going away

Published on 28/11/2024 by Morgan Bazalgette • 4 minutes
it's a system to connect gno and go code together, used for packages like fmt, but it has some problems and is not inspectable using static analysis

i often expressed in issue comments and conversations that i don't really like what i call "gonative". with that word, i generally refer to the entirety of the code in gnovm/pkg/gnolang/gonative.go, but also to the other large part of the codebase that handles the special cases of NativeType and NativeValue. there's been some efforts to improve it lately, and i've been reviewing and merging them provided that they 1. improve some existing flows 2. don't involve too much hassle in reviewing or further maintenance.

but, partly related to the native bindings effort, there's an issue to get these removed. to get some context, let's explore the two mechanisms whereby you can execute go code inside of gno:

there are essentially two problems with NativeValue/NativeType:

static analysis

this is a problem that native bindings was attempting to solve as well: long ago, native functions were all defined in a big "native injector". the consequence was that none of the functions natively defined were "visible" from static analysis tools, like gno doc.

aside from gno doc, tools like gnopls cannot currently "see" these functions, without adding them as exceptions within the code itself. native bindings solved this by adopting the same approach used in go for functions that are defined using assembly: body-less declarations. if you inspect the sync/atomic package, as an example, you'll see that most functions are simply without a function body, because their source is in assembly.

similarly, in gno, native functions are now declared like this; to allow anyone who inspects the source to easily see the matching native go code.

go reflect limitations and risks

this last one is particularly annoying, and is a known "gotcha" when testing; as it's common to be using unexported fields, but when you throw them into a fmt.Printf, the gnovm just panics. the "simple" solution is to use println instead, which, as a native machine function, has no problem with unexported fields. but it's still annoying.

the removal

in the short term, we're shrinking the amount of gonative code and removing its usage from the gnovm. by the mainnet launch, which is on the horizon, we should have all of its related code removed.

there is nothing more satisfying than deleting code :)