Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

NEP: NEO Executable Format (NEF) #121

Merged
merged 26 commits into from
Jul 29, 2021
Merged
Changes from 19 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
113 changes: 113 additions & 0 deletions nep-16.mediawiki
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
<pre>
NEP: 16
Title: NEO Executable Format (NEF)
Author: Fernando Díaz Toledano <shargon@gmail.com>, Erik Zhang <erik@neo.org>, Igor Machado Coelho <igormachado@gmail.com>, Li Jianying <lightsever@hotmail.com>, Vitor Nazário Coelho <vncoelho@gmail.com>
Type: Standard
Status: Accepted
Created: 2020-03-31
</pre>

==Abstract==

Compiled code to be executed by the Neo virtual machine is represented using a binary format, typically stored in a file, known as the <code>nef</code> file format. The <code>nef</code> file contains Neo bytecodes, as well as other ancillary information such as byte ordering and compiler used.

This NEP describes the NEF standard for NEO smart contracts.

==Motivation==

For the sake of security, we need to place strong syntactic and structural constraints on the executable file. With the <code>nef</code> file format, we can guarantee both the validity and functionality of the compiled file.

==Specification==

In the field definitions below, we provide both the definitions of the fields as well as the corresponding functions.

==NefFile Structure==
erikzhang marked this conversation as resolved.
Show resolved Hide resolved

A <code>nef</code> file consists of a stream of 8-bit bytes. Multibyte data items are always stored in little-endian order, where the low bytes come first. Its structure is described further below.

<pre>
nef_file
{
4-byte magic;
32-byte compiler;
32-byte version;
bettybao1209 marked this conversation as resolved.
Show resolved Hide resolved
2-byte reserve;
method_token{
20-byte hash;
var-byte method;
2-byte parametersCount;
1-byte hasReturnValue;
1-byte callFlags;
} tokens[];
2-byte reserve;
var-byte script;
4-byte checksum;
}
</pre>

erikzhang marked this conversation as resolved.
Show resolved Hide resolved
===magic===

The <code>magic</code> item supplies the magic number identifying the <code>NEF3</code> file format; it has the value <code>0x3346454E</code>.

===compiler===

The <code>compiler</code> is a UTF-8 encoded <code>string</code> representing the compiler used to create the data in the <code>script</code> item. It is a fixed-length item, which is padded to force alignment on 32-byte boundary.

===version===

The compiler <code>version</code> is represented using a 32-byte string encoded in UTF-8. It must be padded with padding bytes to make it up to the required length if shorter than 32 bytes.

===reserve===

All bits of the <code>reserve</code> item are reserved for future use and must be set to zero in generated nef files.

===tokens===

Each entry in the <code>tokens</code> item must be a <code>method_token</code> structure giving a necessary description of a method in this contract.

====hash====

====method====

The <code>method</code> item is used to represent constant string values of the method name. It has s single-byte length prefix and up to 32 byte string contents encoded in UTF-8.
====parametersCount====

The <code>parametersCount</code> denotes the number of formal parameters of the method.

====hasReturnValue====

The <code>hasReturnValue</code> item is a boolean value that indicates whether the method has return value or not.

====callFlags====

The value of the <code>callFlags</code> item is a mask of flags used to denote the calling permission to the method. The Interpretation of each flag, when set, is specified in the following table:

{|
!Flag Name !!Value !!Interpretation
|-
| None || 0 || called without other permissions
|-
| ReadStates || 0b00000001 || allow to read the storage
|-
| WriteStates || 0b00000010 || allow to write the storage
|-
| AllowCall || 0b00000100 || allow to call methods in other contracts
|-
| AllowNotify || 0b00001000 || allow to send the notification
|-
| States || 0b00000011 || allow to read and write the storage
|-
| ReadOnly || 0b00000101 || allow to read the storage and call methods in other contracts
|-
| All || 0b00001111 || equipped with all permissions above
erikzhang marked this conversation as resolved.
Show resolved Hide resolved
|}

All bits of the <code>callFlags</code> item not assigned in the table are reserved for future use. They should be set to zero in generated <code>nef</code> files.

===script===

The value of <code>script</code> stores the raw VM opcodes. The data should be serialised using the variable length format as described in the [https://docs.neo.org/developerguide/en/articles/conventions.html#variable-length-types documentation].

===checksum===

The <code>checksum</code> item is used not only to ensure a corrupt-free transmission, but also to ensure that the file has not been tampered with. It is computed by using the SHA256 algorithm to hash the serialised <code>nef</code> file excluding <code>checksum</code> twice, and converting the result into a 32-bit unsigned integer, which must be identical with the last four bytes of the <code>nef</code> file.