By Victor Dods on behalf of LedgerDomain.
In the project root, execute the following command in a terminal.
make generated-artifacts && make initialization && make up
This brings up the blockchain network and web server; once you see
www.skraukosaur.com | server listening at http://:::3000
you can then point your browser at http://localhost:3000
to use the app's web client.
To bring the services down, hit Ctrl+C in the terminal. The following command resets everything to a completely clean state.
make clean
Note that there are more minimal sets of commands that could be used for iteration during development, but this one should suffice, if draconian.
It is apparently necessary to have Docker v1.13 (or presumably anything higher). I was getting inexplicable (and worse, nondeterministic) DNS resolution failures between services during GRPC calls with Docker v1.12.
This application uses Hyperledger Fabric v1.0.1. The necessary components are:
- hyperledger/fabric-peer:x86_64-1.0.1 docker image
- hyperledger/fabric-orderer:x86_64-1.0.1 docker image
- hyperledger/fabric-ca:x86_64-1.0.1 docker image
- hyperledger/fabric-tools:x86_64-1.0.1 docker image
- hyperledger/fabric-baseimage:x86_64-0.3.0 docker image
These will be retrieved automatically when bringing the various docker services up, but they can be pulled manually ahead of time to avoid overhead in starting the application.
Clone this repo with the following command.
git clone https://github.com/vdods/FabricWebApp.git
As a one-time step, generate all necessary configuration and cryptographic material using the following command.
make generated-artifacts
Among other things, this creates a docker volume fabricwebapp_generated_artifacts__volume
containing all certs
and keys necessary for dispersal to the various components of this blockchain application. In particular, this
creates a root CA (which for security purposes should remain offline because it has the root cert and key from
which all trust derives) for each organization which signs certs for the intermediate CAs (which will be online)
which create the certs/keys for the various peers, orderers, and users.
Then, as a one-time step, initialize the persistent volumes for each component of this application using the following command.
make initialization
This copies the necessary config/crypto materials to the volume for each component of the application (e.g. CAs, orderer(s), peers, web server(s)).
Finally, as a repeatable step, bring up the application services using the following command.
make up
The web app (in web/server/app.js
) will automatically read the application and network configuration files
(web/server/appcfg.json
and web/server/netcfg.json
respectively), create necessary keystores, enroll all users
defined in netcfg.json
, create all channels defined in appcfg.json
, send participating organizations invitation
to join the respective channels, install/instantiate chaincode on the peers of each channel, and finally offer
a REST API and a simple web client on http://localhost:3000
. Point your web browser to this address to use
the web client.
Docker-compose is set to abort upon container exit, so if there's a problem, it will exit with a nonzero return code, and the logs for the relevant services can be viewed.
The web client simply presents UI elements for invoking all the different available transactions on behalf of the specified user ("Invoking User Name"). The event log is displayed on the right and shows the results of all transactions.
The name of the privileged user is Admin
-- this user can invoke any transaction, and only this user can invoke
create_account
and query_account_names
. In order to invoke transactions as other users, the create_account
transaction must be successfully invoked by Admin
. For example,
Invoking User Name: Admin
Account Name: Alice
Initial Balance: 123
Create Account (click the button)
After success, the user Alice
can then be used as "Invoking User Name" to attempt to invoke transactions.
Certain transactions have certain constraints (e.g only Admin
or the account owner can transfer an amount
out of an account).
This application demonstrates three organizations (e.g. companies) participating together to provide a bank-type
application via simple web client where bank accounts can be created, balances queried, and transfers made between
accounts. It's based on the balance-transfer
example from [http://github.com/hyperledger/fabric-samples].
The components of this application (hostname and description) are:
- Org0 components:
- <N/A> : Org0's (root) CA (certificate authority) which, to keep the root cert/key safe, is not run online
- ca.org0.skraukosaur.com : Org0's (intermediate) CA which is run online
- peer0.org0.skraukosaur.com : Org0's peer0 node
- peer1.org0.skraukosaur.com : Org0's peer1 node
- Org1 components:
- <N/A> : Org1's (root) CA which, to keep the root cert/key safe, is not run online
- ca.org1.skraukosaur.com : Org1's (intermediate) CA which is run online
- peer0.org1.skraukosaur.com : Org0's peer0 node
- peer0.org1.skraukosaur.com : Org0's peer1 node
- Org2 components:
- <N/A> : Org2's (root) CA which, to keep the root cert/key safe, is not run online
- <N/A> : Org2's (intermediate) CA which is not run online because it's not used in this app after initialization
- orderer.org2.skraukosaur.com : Org2's orderer node
- Other components:
- www.skraukosaur.com : The web server (not formally associated with an organization like the others components are)
The docker-compose.yaml
file and the supporting docker/ca-base.yaml
and docker/peer-base.yaml
files are what
define the services that run.
The source files are structured under the following directory structure:
chaincode
: This is what is run on the peers to execute transactionsdocker
: Files defining docker-compose servicessource-artifacts
: Configuration files and script(s) used to create the generated artifacts described aboveweb/server
: Node.js-based web server which drives the blockchain application and offers a simple REST API to the web clientweb/client
: Minimal web client to drive the blockchain app from the user side
Docker volumes:
fabricwebapp_generated_artifacts__volume
: Generated bymake generated-artifacts
, and contains all CAs and CA-generated materials -- thecrypto-config
dir created byfabric-ca-cryptogen.sh
, themychannel.tx
channel configuration used to create the channel for use by the blockchain app, and theorderer.genesis.block
file used to initialize the blockchain with the participating organizations' credentials.fabricwebapp_com_skraukosaur_org0_ca__volume
: Org0's CA and state (user registration and enrollment)fabricwebapp_com_skraukosaur_org0_peer0__volume
: Org0's peer0 configuration and statefabricwebapp_com_skraukosaur_org0_peer1__volume
: Org0's peer1 configuration and statefabricwebapp_com_skraukosaur_org1_ca__volume
: Org1's CA and state (user registration and enrollment)fabricwebapp_com_skraukosaur_org1_peer0__volume
: Org1's peer0 configuration and statefabricwebapp_com_skraukosaur_org1_peer1__volume
: Org1's peer1 configuration and statefabricwebapp_com_skraukosaur_org2_ca__volume
: Org2's CA and state (user registration and enrollment), though this is not used by a running servicefabricwebapp_com_skraukosaur_org2_orderer__volume
: Org2's orderer configuration and statefabricwebapp_com_skraukosaur_www__config_volume
: Crypto/config materials used by the www.skraukosaur.com web serverfabricwebapp_com_skraukosaur_www__home_volume
: Keystore(s) and other persistent state used by the www.skraukosaur.com web serverfabricwebapp_com_skraukosaur_www__node_modules_volume
: Thenode_modules
directory used by the www.skraukosaur.com web server
Docker images:
www.skraukosaur.com-env:v0.0
: The image, based onhyperledger/fabric-baseimage:x86_64-0.3.1
, is what thewww.skraukosaur.com
service runs within. It installs a couple of python2 packages via apt-get that are needed for thenpm install
process to succeed.
There are several make
targets that make controlling the docker-compose services defined in docker-compose.yaml
easier.
-
The command
make generated-artifacts
Creates the
fabricwebapp_generated_artifacts__volume
docker volume and generates all configuration and cryptographic materials necessary to later disperse (viamake initialization
) to the various components of the blockchain app. -
The command
make initialization
Creates the
fabricwebapp_com_skraukosaur_*__volume
docker volumes and copies the necessary files fromfabricwebapp_generated_artifacts__volume
to the respective volumes. This represents the communication of configuration/cryptographic material via out-of-bands channels to the participating servers. -
The command
make up
Creates and starts all services, volumes, and networks and prints all services' logs to the console. Hitting Ctrl+C in this mode will stop all services. If any container exits, all will exit.
-
The command
make up-detached
does the same as
make up
except that it spins up all services in the background and does not print logs to the console. -
The command
make logs-follow
can be used voluntarily, in the case that
make up-detached
was used, to follow the services' log printouts. Hitting Ctrl+C will detach from the log printout but not stop the services. Note that currently the peers' state is not persisted between runs, so the blockchain will be lost upon stopping the containers. -
The command
make down
brings down all services, but do not delete any persisted volumes (i.e. docker-based persistent storage). Note that currently the peers' state is not persisted between runs, so the blockchain will be lost upon stopping the containers.
-
The command
make down && make rm-state-volumes && make initialization && make up
is a convenient single command you can use after stopping services to reset all services back to a clean state and restart them, following the services' logs. There is typically no need to delete the persistent
fabricwebapp_com_skraukosaur_www__node_modules_volume
volume because it is not likely to qualitatively change or be corrupted (though that does happen sometimes during development for various reasons). Note that the web server service indocker-compose.yaml
does execute the commandnpm install
, so any updates toweb/server/package.json
should automatically take effect. -
The command
make build-chaincode
builds the chaincode in a separate service, and succeeds or fails quite quickly. This is used to avoid the slow startup of the peers and other services needed to have the chaincode compile in the "real" way as in a production environment, and instead be able to iterate quickly when working on the chaincode.
-
The command
make show-all-generated-resources
will show all non-source resources that this project created that currently still exist. See also the
make rm-all-generated-resources
command.
-
The command
make rm-build-chaincode-state
deletes the build artifacts generated by
make build-chaincode
, and can be used to force a "clean build" of the chaincode. -
The command
make rm-www-image
deletes the docker image in which the www.skraukosaur.com service runs.
-
The command
make rm-state-volumes
deletes the persistent storage of the web server (in particular, the
fabricwebapp_webserver_tmp
andfabricwebapp_webserver_homedir
volumes), and can be used for example to reset the web server to a 'clean' state, not having anything in the key/value store(s). This can be executed only if the services are not up. WARNING: This will delete all of your webserver keystore data, and is IRREVERSIBLE! -
The command
make rm-node-modules
deletes the node_modules directory of the web server (in particular, the
fabricwebapp_webserver_homedir_node_modules
volume). This can be executed only if the services are not up. This does not delete any real data that can't be easily recreated, though it may involve downloading a lot of node.js dependencies. -
The command
make rm-generated-artifacts
will delete all generated artifacts. In particular, it will delete the entire
generated-artifacts
directory. This does not delete any real data that can't be easily recreated. -
The command
make rm-chaincode-docker-resources
Deletes the docker containers created by the peers to run chaincode in net mode (which is default, as opposed to dev mode, specified by the
--peer-chaincodedev=true
option to the peer executable), as well as the docker images on which they run. This shouldn't be necessary except to do a full clean-up, or when modifying chaincode (Fabric doesn't appear to detect that chaincode needs to be recompiled as of v1.0.0-alpha2). This does not delete any real data that can't be easily recreated. -
The command
make rm-all-generated-resources
or equivalently
make clean
will delete all non-source resources that this project created and currently still exist. This should reset the project back to its original state with no leftover persistent data. So be careful, because this will also delete your blockchain state and web server keystore.
There is a simple shell script based test that can be run against the web server. Bring the services up
(see above documentation on how), and then in a separate console, run ./test_rest_api.sh
. It should
make several transactions and check their responses. The script will succeed only if the responses were
as expected. The test script must be run against a "fresh" server.
- The
.env
file contains the default environment variable values to be used indocker-compose.yaml
. In particular:- GENERAL_LOGGING_LEVEL controls how verbose the logging for each service is.
- TLS_ENABLED controls if TLS communication between each service is enabled.
- WARNING: I have not been able to get the trustedRoots option for the TLS connection to the CA to work; thus
I have set
"rejectUnauthorized":false
innetcfg.json
to disable the check that the TLS server's cert is signed by a trusted CA. The connection is still encrypted via TLS, but as is, it is vulnerable to man-in-the-middle attacks.
- Get the trustedRoots verification working for TLS connection to CA. As noted in Random Notes, it is currently disabled, and therefore is vulnerable to man-in-the-middle attacks.
- Use the fabric-ca-server-config.yaml files for ca.orgN.skraukosaur.com in fabric-ca-cryptogen.sh so that the CAs can be custom configured.
- Verify that the state is preserved correctly between calls, and that the web server correctly handles existing persistent data in its keystore (regarding enrollment).
- Create a single Makefile rule that ensures the correct artifacts/volumes/etc exist (creating if necessary), and then brings up all necessary services. This rule should be able to be used to run the set of services again even if they exist already. It should be the single, turn-key command that drives this entire example app.
- Separate the
make generated-artifacts
step up into one command to generate the artifacts for each organization. This will require modifyingfabric-ca-cryptogen.sh
accordingly.
This was originally a fork of https://github.com/ratnakar-asara/Fabric_SampleWebApp but has diverged quite a bit since then.