Technical details of NeoContract and NeoVM

NeoContract is a smart contract system built on NEO blockchain, serving the purpose of transaction validation, token sales and decentralized app development. It consists of NeoVM, NeoContract APIs and software development kit (SDK).

NeoVM is a decentralized VM designed for NEO where smart contracts are executed. NeoVM is not only applicable to blockchain but also to scenarios elsewhere thanks to its low-coupling architecture.

NeoContract APIs are sets of interfaces that enrich smart contracts with practical and powerful functionality.

SDK is a combination of applications and plugins designed for NEO smart contract developers, which makes NEO smart contract development a user-friendly experience.

Following is detailed explanation.

I — NeoVM

NeoVM contains three essential elements: execution engine, stacks, and interop services.

1. Execution engine: The complete set of instructions designed for it includes constant instructions, flow-control instructions, stack instructions, string instructions, logical instructions, arithmetic instructions, cryptography instructions, data structure instructions and exception instructions, which assist developers when they code complex smart contracts, especially those involving complex data structure, cryptography and exception handling, etc.

Besides, the execution engine has a built-in debugger. You may set a breakpoint or initiate single step execution to debug. Given that the instruction set includes stack operation instructions, as explained above, NeoVM can be categorized as stack-based virtual machine.

2. Stack: NeoVM has 3 available stacks, namely call stack, compute stack and standby stack.

Call stack records the running state at the time of functions being called, so that the program may resume running in the contexts where the function is returned.

Compute stack, or the buffer storage area, can be directly accessed by smart contract code. Take additive operation for example, two additive operands will be pushed into the compute stack and executed following additive instruction. The execution engine will read and add up the operands from the top of calculator stack and write the result back to the top.

Whereas, the standby stack stores data tentatively of no use to the compute stack.

3. Interop services: If we compare execution engine to the CPU of a computer, then the stack is the memory and interop services is the system bus. It connects the execution engine, stacks and external services, allowing smart contracts to access all the NeoContract APIs, e.g. time stamp service and persistent storage, thereby enriching smart contracts with more functions.

Because of its low-coupling nature, NeoVM can be easily used in other blockchains or applied to scenarios elsewhere, as long as there is a suitable interop service API.

II — NeoContract APIs

We have put various advanced APIs in NeoContract that handle tasks in greater number and complexity and are accessible via interop services of NeoVM. Such APIs include runtime data, ledger data, persistent storage, smart contract management and digital assets.

1. Runtime data indicates the current running state of the smart contract. One example is the trigger, whose specification is clearly defined in NEP-7. NEO smart contracts cannot be executed until being triggered. We have defined four triggers applicable to different scenarios.

When a node is verifying a transaction, the validation trigger will be fired to execute associated smart contracts; the application trigger will also be fired when a distributed app is activated by a transaction; the receiving trigger will be fired when a transfer is successfully made on a smart contract, which allows the contract to either turn down the transfer request in the early validation stage or process the transferred amount in the later stage; time stamp server is another notable feature, which allows a running smart contract to retrieve the current time stamp.

Distributed as it is, blockchain must have an interface to ensure that all the nodes reach consensus at a given time. Thus we take the time stamp of a block as the data source of the service. Finally, smart contracts can communicate with verification node at runtime with notifications and logs, allowing verification node to efficiently track the status of smart contracts.

2. Ledger data. On some occasions, smart contracts are required to read blocks, transactions, or balance of the user’s account to make judgement, which explains why we have a lot of APIs in place for smart contracts to read every single field of every transaction. Either via APIs or transactions, external data will be accessible and readable on-chain. As long as there is a mechanism that ensures the reliability of data on-chain, we can implement a decentralized oracle. 3. Persistent storage. NEO has provided data access interface based on key-value pairs. Data records may be read or deleted from or written to the smart contracts using keys. Besides, smart contracts may retrieve and send their storage contexts to other contracts, thereby entrusting other contracts to manage their storage areas.

Based on such mechanism, we can write a particular smart contract to abstract the underlying key-value pair storage function and offer advanced data base management service.

4. Smart contract management allows deployed smart contracts to be managed at runtime. It has three functions: new contract creation and deployment, existing contract upgrading and migration and destruction of deployed smart contract. Once a contract is destroyed, its storage area will be destroyed along with it; once a contract is migrated, the content in the old storage area will also be copied and pasted to the new storage area. 5. Digital assets. NEO digital assets fall into two categories: global assets and contract assets.

NEO and GAS are both global assets. You may also create a new global asset through APIs. All the global assets are based on UTXO model, whose entity credit can be reflected by the NeoID.

Contract assets, on the other hand, depend on the storage function of NeoContract. The entire ledger of contract assets is stored in the storage area of smart contracts, which manage all the accounts. NEP-5 is a token standard specially designed for contract assets. If your contract supports NEP-5, tokens defined in the contract will be supported by the majority of NEO wallets.

III — Software Development Kit (SDK)

To be a qualified NEO smart contract developer, you must first select an advanced programming language you are most familiar with. NEO currently supports .NET languages (C#, VB.NET, F#), Java languages (Java, Kotlin), Python and JavaScript.

Pick your language and IDE is the next thing of your concern. You may choose Visual Studio (C#), an IDE supports development, compilation and commissioning or Eclipse (Java), which is also a good choice. If you choose languages other than C# and Java, you may code with an editor before using a NEO compiler to convert the program into NeoVM byte codes.

NEO compiler can compile the advanced language into byte codes that can be run in NeoVM. Meanwhile, ABI files which conform to NEP-3 protocol will be generated. Deployed on NEO blockchain, these byte codes can get access to the storage area of the blockchain or be invoked by other contracts; or we can put the byte codes inside a transaction and execute them directly.

If the byte codes are directly executed, smart contracts won’t be necessarily deployed, neither deployment fees will be charged by the system. The ABI file which describes a list of functions and events can be used to invocate a smart contract, playing the role of informing node apps and users how to use the contract.

NeoContract 2.0

After giving a detailed breakdown of NeoContract and NeoVM, Erik later envisioned NeoContract enhancement in the future.

Serialize and Deserialize. Smart contracts may involve extremely complex data structure. A set of API will be added to NeoContract to serialize the data into byte arrays or deserialize the byte arrays into the original data structure. Once implemented, the APIs will enable storage and retrieval of any form of data in the storage area. Storage iterator. Due to its limited storage, the contract only reads one record, which is inaccessible unless you know its key. The storage iterator allows users to search records by setting conditions and even read, modify and delete some records. Stack isolatio. As mentioned before, NeoVM has call stack, compute stack and standby stack available for smart contracts. Call stack cannot be directly modified by smart contract, but by using process control instructions, which guarantees data security; compute stack and standby stack are modifiable by changing the contract code. That means an invoker’s compute stack is at the risk of being modified by an invokee. It is less risky if it is a static call because the invoked object is definite and so is its behavior. However, as dynamic call mechanism has already been brought up in NEP-4, which will be applied to future use cases, it is highly possible that the flawed mechanism described above will undermine the data security of invoked contracts in the future. As a countermeasure, we have proposed an enhancement proposal for NeoVM. The proposal describes an intended isolation between compute stack and standby stack, leaving independent stack space for every frame on the call chain. Exception handling. Exception handling ability is another issue on the enhancement proposal. We propose to improve by adding new exception handling instructions to NeoVM that allow the contract to try/catch exceptions and recover if possible. The improvement cannot be implemented without isolating compute stack from others. Dynamic sharding. NEO has a strong system infrastructure that supports a payload up to 1000tps. But with a growing number of apps built on NEO, it is hard to tell whether it is still the case in the future. Therefore, we must prepare an expansion plan to take the upper hand on the “jamming effect”. Sharding is a viable solution to TPS ramp-up. The dynamic sharding proposal under planning is about isolating irrelevant contracts by putting them in different shards and converging relevant ones in the same shard to allow concurrent execution. Relevant contracts are those functioning in a contract call, either an invoker or invokee and vice versa. As the call relationship between contracts keeps changing, the sharding rules will adjust accordingly to maintain the system at an optimal state. Dynamic call proves to be more effective in raising TPS than static call. NeoX. NeoX is a cross-chain solution we proposed, which contains cross-chain asset exchange protocol and cross-chain distributed business logic. One NeoX technology allows smart contracts to be executed across blockchains. Simply put, it takes many steps to execute smart contracts, ending up in either “all success” or “all fail”. It is easier if all these steps are executed on the same chain while much harder across different chains considering the consistency issue.

NeoX is designed to tackle the problem. But to implement the technology, NeoVM must be improved to allow state lock and rollback. Once implemented, the technology will support cross-chain smart contract execution without compromising the consistency, though under one prerequisite — NeoVM or similar technology must be adopted.