Solution overview
Let us start by creating a high level understanding of all the components that are involved in the solution and how they communicate with each other. Once we have a basic understanding we'll dive deeper into the details in the Smart Contracts chapter as well as other chapters thereafter.
Front and backend
One of the goals for this iteration was to try and keep it as close as possible to a python-only solution. Javascript solutions are out there in abundance compared to python and hopefully this makes a small change in that. Despite these intentions a little bit of HTML and javascript (in the form of jQuery) was required to present an easy accessible user interface via the web browser.
The backend runs on the well proven Django web framework. Prediction events can be created and interacted with in the web browser and are sent from the backend to the Middleware to be registered on the blockchain. A couple of API endpoints are exposed that allows the Middleware to report back on events happening on the blockchain (e.g. registration success, event completion etc). This data is stored in an SQLite database such that they can be easily retrieved and presented to the user.
More details on what events the smart contracts generate will be discussed in the Smart contracts chapter.
Middleware
The middleware is a slightly modified neo-python instance. The regular prompt.py
is replaced by precognition-rest-apis.py
which is a minimized node that connects to the blockchain and starts up the the following 3 services
- A web API service build on the Klein Web Micro-Framework that exposes an interface that the Django backend can send its data and commands to that need to be executed on the blockchain.
- An experimental RPC API server that supports the official NEO RCP API. Be ware that the
sendrawtransaction
API is the only command that can modify state on the blockchain. All other RPC API's are read-only. - A notification 'server' that listens to events happening on the blockchain and sends specific data that we're interested in back to the Django Backend for storage.
For more examples on starting rest-api servers, notification servers, minimal nodes and alike have a look at the /examples/ folder of neo-python.
The Blockchain
The blockchain in this solution is a private NEO network started inside the Docker image. It consists of 4 NEO Consensus nodes that make up the basis of the network. At this point in time only the NEO C# client has consensus support and the network is build upon 4 NEO-CLI instances. I'd like to point out that consensus support is in the making for neo-python
stay tuned. The Middleware client connects to this private network such that it can push transactions onto the network aswell as listen and process transactions incoming to capture the smart contract notifications. Interaction with smart contracts on the blockchain happens through Invocation Transactions as described in the NEO Network protocol. Because all data is stored on the blockchain and the middleware keeps a copy of the blockchain we'll later on see that we can retrieve certain information by instrumenting the NEO Virtual Machine directly without having to push an Invocation Transaction onto the network.
The four consensus nodes each have an RPC server enabled that accepts the NEO RCP API, just like the RPC service described in point 2 of the Middleware section. On the block chain there are four smart contracts deployed which we'll discuss shortly next and then dive into more detail in the next chapter.
Smart contracts
Smart contracts deployed on the network are of course an essential part of the network. The bottom two token contracts follow the NEP5 Standard which describes a generalized interaction mechanism for tokenized smart contracts. You can see these as the brothers and sisters of RPX , DBC and other tokens currently deployed on the MainNet. They're based on the NEX ICO Template with a slight adjustment to allow free token minting to have balance for demonstration purposes. Feel free to diff the sources.
The Event
contract is currently our main smart contract for registering events to. As said before it implements the parimutuel betting algorithm. It can accept any Oracle
smart contract for logging and resolving the final outcome of its events. It communicates with contracts via Dynamic Application Calls (the yellow-ish lines). The Central Oracle
contract is one of the many types of oracles you can implement. This oracle registers exactly 1 owner per event that can log the final result and trigger the event resolution. An example of such a central authority could be the Chinese government for the China Sport Lottery events as discussed in the Introduction.
Let us now dive into more details of the Event
and Central Oracle
smart contracts and see how we can interact with them in the next chapter.