(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.
