(electronic chiming)
- [Narrator] Let's create a simple blockchain application
using the JS library.
Open up a terminal
and create a new directory for the project.
Then install the LotionJS library
by running npm install lotion.
Now let's create a new file called app.js.
First, let's import the Lotion library
with a require statement.
Then we'll create a new Lotion app and pass in an object
that contains one field called initialState,
which itself is an object.
For now, we'll just have one field
in the initialState, called count.
This field is just going to track the number of transactions
that have occurred so far.
A Lotion application is usually a single function
that takes the state and transaction as input
and then computes the next state of the blockchain
based on the transaction.
Now let's write our state transition function.
Let's create a function called stateFunc
and it takes two parameters: the state and the transaction.
Into the function, we can retrieve
the current state of our app from the state variable
and get the count value.
We can also get fields from the transaction object, as well.
For our simple application,
we'll only increment the count state
if the nonce field of this transaction
is equal to the current count of the app.
We'll see where the nonce field of the transaction
comes from in a second.
Now we're done with our state transition function.
We need to tell the app to use this function.
We can do this by calling the app.use
and passing the name of our stateFunc function.
You can have more than one transaction handler functions,
but we'll just have one in our simple application for now,
which is stateFunc.
If you have more than one, the order in which the
transaction handler functions are called
is in the order you invoked app.use.
So the first one will be the first function to get called.
One thing to know about the transaction handler
is that it must be deterministic.
This means that given the same input, state,
and transaction, the mutated state should
always be the same.
Otherwise, consensus could not be reached
among the Tendermint nodes.
Finally, to finish our app, we'll call the app.listen
and pass in a port number,
which we'll use 3000 for this example.
This will start a local HTTP server on port 3000,
which you can use to query the state of the blockchain,
as well as create new transactions.
Let's start the app in the terminal by typing node app.js.
Now, open up a new terminal window
and we can query the state of the blockchain
by sending GET requests to localhost:3000/state.
You can do this by using the curl command
or simply type this URL into a browser window.
Either way, you should see a JSON data structure that
contains the count field and it should equal to zero.
Now, to send a transaction to the blockchain,
we need to send a POST request
and we can do this using the curl command again,
but this time we'll use the -d option
to specify the data we want to send.
In this case, the transaction data structure
is a JSON object that
contains one field called nonce.
Remember, in our transaction handler function, stateFunc,
we access the nonce field
in our transaction input parameter,
which is this field we specified here.
Now let's take at the return value
from the POST request for this new transaction.
It's a JSON object that contains a result field
which contains the height of the current blockchain
and the hash of the latest block.
We'll learn more about the check_tx
and the deliver_tx data structure in a later lesson,
but for now, all you need to know is it's related
to the underlying consensus and networking layer,
which is provided for you by Tendermint Core.
If we query the state of our blockchain again,
you'll notice that the count value has increased to one.
This is because we sent a transaction
to the blockchain with our POST request
and our state transition function took
the previous state and the transaction
and updated the state.
You might be asking yourself,
"Where are the blockchain-related data?
And how is this a blockchain
if it's only running locally on my computer?
Shouldn't there be many different nodes in the system?"
The LotionJS library stores all the blocks
and related data in your home directory
under a hidden folder called .lotion.
Inside this directory, we see a networks folder,
for each of your Lotion apps will be
under its own network directory.
The network ID, which is the name of the folder,
is automatically generated for you by LotionJS.
So in our example,
we have a network ID that starts with f6.
Inside this folder, we see just a few files and subfolders.
The data directory contains various blockchain data
such as blocks, and transactions, and memory pools.
The two other important files we want to look at
is genesis.json and config.toml file.
If we open up genesis.json file,
we can see some of the information about our blockchain.
For example, we see our blockchain as an ID,
which says DmPY4h.
We see the genesis time of our blockchain
and the hash of our application as well.
In addition, we have a list of validators
for our blockchain.
Right now we only have one,
which is the node we started
when we ran our app.js file locally on this computer.
LotionJS automatically creates a key pair for you.
If you open priv_validator.json file,
you'll be able to see the public and private key values.
Next, if we open up the config.toml file,
we can see some information
of our configuration for our blockchain.
The proxy_app shows the TCP socket URL
that our app uses internally
to communicate with Tendermint Core.
The Tendermint Core runs in a separate process as our app
and they communicate over sockets.
It is also possible to run both Tendermint Core
and an application blockchain interface app
in the same process, but we'll learn more
about these details in a later lesson.
The moniker field,
which allows us to have a human-readable
name for our local node, if we desire.
For example, I can set it to Jack's Computer,
in order for other people to
identify my computer more easily.
The fast_sync option allows those that are very far behind
to the tip of the current blockchain
to catch up very quickly
by downloading blocks in parallel and verifying them.
The db_backend allows us to choose what database to use.
The default is leveldb.
The log_level specifies the verbosity
of what you want to see in the output log.
The RPC, or Remote Procedure Call, server,
running on port 46657, is used by Tendermint Core
and light clients can communicate directly
with Tendermint Core through this RPC server.
We'll learn more about this in a future lesson, as well.
The last option under p2p is a port we specify
for other peers to connect to from our local node.
The default port is running on 46656 on TCP
and the seeds field allows us to specify
a comma-separated list of other peers we can connect to,
if they are known.
Before we finish this lesson,
let's talk about the architecture
of the application we built.
When we ran our app.js file with LotionJS,
underneath the hood we have
a few different processes running.
One is the Tendermint Core,
which is responsible for consensus and networking.
One is our application,
which communicates with the Tendermint Core
through the Application BlockChain Interface on port 46658.
The other process is the HTTP web server
running on port 3000.
How all this is connected together,
is that when the web server receives requests,
either GET or POST requests from users,
it communicates with the Tendermint Core,
through the RPC server, which is running on port 46657.
Then, the Tendermint Core communicates with our application
through the Application BlockChain Interface on port 46658.
Finally, if we had other peers or nodes in the system,
they can connect to our node by port 46656,
which is also running inside the Tendermint Core process.
If you want to see more videos about Cosmos,
such as building your own cryptocurrency,
inter-blockchain communication, and many more,
go to blockgeeks.com for our full Cosmos course.
Thanks for watching.