Getting Started

Overview

This tutorial walks through the process of setting up a virtual development environment for the Distributed Ledger using Docker or Virtualbox/Vagrant. At the end, you will have a running validator and a running transaction processor. You will have submitted transactions to the validator.

Additional sections guide you in the following tasks:

Commands in this tutorial can be run via Terminal.app on MacOS, Git Bash on Windows, etc.

Clone Repository

You’ll need to have git installed in order to clone the Sawtooth Lake source code repository. You can find up-to-date installation instructions here:

Note

When checking out Sawtooth Lake on Windows for use with vagrant, you should take steps to ensure that Windows-style CRLF line endings are not added to the code. The bash scripts used by your vagrant VM will not run correctly with CRLF line endings. Git uses a configuration setting, core.autocrlf, to control whether or not LF-style line endings are automatically converted to CRLF-style line endings. This setting should be set in such a way that CRLFs are not introduced into your repository.

Open up a terminal and run the following:

% cd $HOME
% mkdir project
% cd project
% git clone https://github.com/hyperledger/sawtooth-core.git

Note

On a Windows environment, the suggested version of the last command above is:

C:\> git clone https://github.com/hyperledger/sawtooth-core.git
--config core.autocrlf=false

Docker Instructions

Prerequisites

The following tools are required:

Environment Startup

To start up the environment, run:

% cd sawtooth-core
% docker-compose -f docker/compose/sawtooth-demo.yaml up

Downloading the docker images that comprise the Sawtooth Lake demo environment can take serveral minutes. Once you see the containers registering and creating intial blocks you can move on to the next step.

Attaching to compose_validator_1, compose_tp_xo_python_1, compose_client_1, compose_tp_intkey_python_1, compose_tp_config_1, compose_rest_api_1
validator_1         | writing file: /etc/sawtooth/keys/validator.priv
validator_1         | writing file: /etc/sawtooth/keys/validator.pub
validator_1         | Generating /var/lib/sawtooth/genesis.batch
tp_xo_python_1      | [19:03:47 DEBUG   selector_events] Using selector: ZMQSelector
validator_1         | [19:03:47.537 INFO     path] Skipping path loading from non-existent config file: /etc/sawtooth/path.toml
tp_xo_python_1      | [19:03:47 INFO    core] register attempt: OK
validator_1         | [19:03:47.538 INFO     cli] config [path]: config_dir = "/etc/sawtooth"
tp_intkey_python_1  | [19:03:47 DEBUG   selector_events] Using selector: ZMQSelector
validator_1         | [19:03:47.538 INFO     cli] config [path]: key_dir = "/etc/sawtooth/keys"
tp_intkey_python_1  | [19:03:47 INFO    core] register attempt: OK

Open a new terminal so we can connect to the client container:

% docker exec -it compose_client_1 bash

Your environment is ready! Continue on to Multi-language support for transaction processors.

Resetting The Environment

If the environment needs to be reset for any reason, it can be returned to the default state by logging out of the client container, then pressing CTRL-c from the window where you originally ran docker-compose. Once the containers have all shut down run ‘docker-compose -f sawtooth-demo.yaml down’.

validator_1         | [00:27:56.753 DEBUG    interconnect] message round trip: TP_PROCESS_RESPONSE 0.03986167907714844
validator_1         | [00:27:56.756 INFO     chain] on_block_validated: 44ccc3e6(1, S:910b9c23, P:05b2a651)
validator_1         | [00:27:56.761 INFO     chain] Chain head updated to: 44ccc3e6(1, S:910b9c23, P:05b2a651)
validator_1         | [00:27:56.762 INFO     publisher] Now building on top of block: 44ccc3e6(1, S:910b9c23, P:05b2a651)
validator_1         | [00:27:56.763 INFO     chain] Finished block validation of: 44ccc3e6(1, S:910b9c23, P:05b2a651)
Gracefully stopping... (press Ctrl+C again to force)
Stopping compose_tp_xo_python_1 ... done
Stopping compose_tp_config_1 ... done
Stopping compose_client_1 ... done
Stopping compose_rest_api_1 ... done
Stopping compose_tp_intkey_python_1 ... done
Stopping compose_validator_1 ... done

% docker-compose -f sawtooth-demo.yaml down

Vagrant and Virtualbox Instructions

Prerequisites

The following tools are required:

Proxy Settings

If you are behind a network proxy, follow these steps before continuing:

  1. Set the following environment variables:
  • http_proxy
  • https_proxy

If you are using the Bash shell, run the following commands:

Warning

The example URLs and port numbers used below are examples only. Please substitute the actual URL, with actual port numbers, used in your environment. Contact your network administrator for the information if necessary.

% export http_proxy=http://example-proxy-server.com:3128
% export https_proxy=https://example-proxy-server.com:3129

If you are using Windows, run the following commands:

% set http_proxy=http://example-proxy-server.com:3128
% set https_proxy=https://example-proxy-server.com:3129
  1. Install the vagrant-proxyconf plugin:
% cd sawtooth-core/tools
% vagrant plugin install vagrant-proxyconf

Environment Startup

In order to start the vagrant VM, run:

% cd sawtooth-core/tools
% vagrant up

Note

We have encountered an intermittent problem on Windows hosts which presents as an ‘Operation not permitted’ error in the vagrant startup output. If you encounter this error, perform a ‘vagrant destroy’ and then run ‘vagrant up’ again.

Downloading the Vagrant box file, booting the VM, and running through the bootstrap scripts will take several minutes.

Once the ‘vagrant up’ command has finished executing, run:

% vagrant ssh

By default, Vagrant sets up ssh keys so that users can log into the VM without setting up additional accounts or credentials. The logged in user, vagrant (uid 1000), also has permissions to execute sudo with no password required. Any number of vagrant ssh sessions can be established from the host.

Note

Occasionally, the configuration files used to create the vagrant environment change and this can result in vagrant asking for a password when doing vagrant up or vagrant ssh. This is usually a sign that your environment is out of date. If this happens, please follow the instructions below to reset your environment. This is especially common when switching between versions of Sawtooth Lake, eg. 0.7 -> 0.8.

Resetting The Environment

If the VM needs to be reset for any reason, it can be returned to the default state by running the following commands from the sawtooth-core/tools directory on the host:

% vagrant destroy
% vagrant up

Warning

vagrant destroy will delete all contents within the VM. However, /vagrant and /project are shared with the host and will be preserved.

Building sawtooth-core

Most of the components of Sawtooth Lake depend partially on code that must first be built. This includes C++/swig code and generating protobuf classes for each language. Sawtooth Lake also includes SDKs for other languages, including Java and JavaScript, which require building. To build the python portion of Sawtooth Lake within vagrant, do:

$ /project/sawtooth-core/bin/build_python

This will allow you to run and test Sawtooth Lake components manually. The automated tests for python and all other languages rely on docker to ensure reproducibility. To run the automated tests for python, first run the following:

$ /project/sawtooth-core/bin/build_all -l python

This will create docker images for all the python components and run build_python inside a build container. You can then run the automated tests with:

$ /project/sawtooth-core/bin/run_tests -x java_sdk -x javascript_sdk

If you are not behind a proxy, you can build and test everything Sawtooth Lake has to offer with:

$ /project/sawtooth-core/bin/build_all
$ /project/sawtooth-core/bin/run_tests

Validator Start-up Process

Caution

Genesis block and validator startup are handled for you if you’re using the Docker workflow. You can skip to Multi-language support for transaction processors if you’d like, or keep reading to better understand the startup process.

Create Genesis Block

In most use cases, it is not necessary to create a genesis block when starting a validator, because the validator joins an existing distributed ledger network. However, as a developer, you may often need to create short-lived test networks. In this case, you need to create a genesis block when instantiating a new network.

The genesis block contains some initial values that are necessary when a Sawtooth Lake distributed ledger is created and used for the first time.

To create the genesis block, log in to the development environment with the command vagrant ssh and run the following command:

$ sawtooth admin genesis
Generating /home/ubuntu/sawtooth/data/genesis.batch

Note

If you need to delete previously existing block-chain data before running a validator in the vagrant environment, simply run the following command: rm /home/ubuntu/sawtooth/data/*

Start Validator

To start a validator, log in to the development environment with vagrant ssh and run the following commands:

$ cd sawtooth-core/
$ sawtooth keygen --key-dir /home/ubuntu/sawtooth/keys/ validator
$ validator -vv --public-uri tcp://localhost:8800

Note

To run the validator with less verbose logging, use the command validator -v.

This will start the validator. Logging output will be printed to the terminal window. The validator outputs something similar to this to the terminal window:

[16:18:30.145 INFO    chain] Chain controller initialized with chain head: None
[16:18:30.145 INFO    publisher] Now building on top of block: None

To stop the validator, press CTRL-c.

Running a transaction processor

Caution

The necessary transaction processors are started automatically if you’re using Docker with this tutorial. Keep reading if for more information about transaction processors or skip ahead to Multi-language support for transaction processors.

Transaction processors can be started either before or after the validator is started.

To start an intkey transaction processor, log in to the development environment with vagrant ssh and run the following commands:

$ cd sawtooth-core/
$ tp_intkey_python -v tcp://127.0.0.1:40000

This will start a transaction processor that includes an intkey handler, which can understand and process transactions that use the built-in intkey transaction family. The processor communicates with the validator on TCP port 40000.

The endpoint (tcp://127.0.0.1:40000 in this example) to connect to must be specified when starting the transaction processor. This tells the transaction processor which validator to connect to. This is useful, because it is possible to run transaction processors on separate machines.

The transaction processor produces the following output:

[23:07:57 INFO    core] register attempt: OK

Note

In a production environment, you should always run a transaction processor that supports the config transaction family. See Config Transaction Family Usage for more information.

To stop the transaction processor, press CTRL-c.

Multi-language support for transaction processors

Sawtooth Lake includes additional transaction processors:

  • tp_config
    • A config family transaction processor written in Python
  • tp_intkey_java
    • An intkey transaction processor written in Java
  • tp_intkey_javascript
    • An intkey transaction processor written in JavaScript
    • Requires node.js
  • tp_intkey_jvm_sc
    • An intkey transaction processor implemented as a smart contract.
    • The bytecode to run a transaction is stored in state and the blockchain.
    • Requires Java
  • tp_validator_registry
    • A transaction family used by the PoET consensus algorithm implementation to keep track of other validators.
  • tp_xo_python
    • An XO transaction processor written in Python

Creating And Submitting Transactions

The intkey command is provided to create sample transactions of the intkey transaction type for testing purposes.

This section guide you through the following tasks:

  1. Prepare a batch of intkey transactions that set the keys to random values.
  2. Generate inc (increment) and dec (decrement) transactions to apply to the existing state stored in the blockchain.
  3. Submit these transactions to the validator.

Run the following commands from the Vagrant CLI:

$ intkey create_batch
$ intkey load -f batches.intkey

Or from the Docker CLI:

$ intkey create_batch
$ intkey load -f batches.intkey -U tcp://validator:40000

You can observe the processing of the intkey transactions by observing the logging output of the validator. A truncated example of the validator’s output is shown below:

[19:29:26 INFO    core] register attempt: OK
[19:31:06 INFO    handler] processing: Verb=set Name=eBuPof Value=99811 address=1cf126c584128aaf1837c90c83748ab222c11b8bbd2fe6cc30f17fe35f2acb9af8efd4ee3f092b676546316cf85b2e929b68d9c5314e93ac318ba527ec74aa3ed1bc2e
[19:31:06 INFO    handler] processing: Verb=set Name=HOUUQS Value=10140 address=1cf126380fa9e716a05ac815741fd1960d5952e60f8747e13334f79504c57d0287b77cf9b78284d0e1544f6f0366d66c6e6eb99dc5c154b84175b2d20008d721c7b623
[19:31:06 INFO    handler] processing: Verb=set Name=lrnuDC Value=92318 address=1cf12617c797cf8c27254bbdb5c9bda09f9405b9494ae32b79b9b6d30881ca8552d5932a68f703d1b6754b9feb2edafa76a797fc0826110381b0f8614f2c6853316b47
[19:31:06 INFO    handler] processing: Verb=set Name=BKaiql Value=94175 address=1cf12669cbc17d076a1accb4b0bb61f40ed4f999173b90e3ca2591875a55fee2947661e60fa1c57b41ef0f2660176b945a01c85ff645543297068a3fb1306324a19612
[19:31:06 INFO    handler] processing: Verb=set Name=wpMQmE Value=47316 address=1cf1260f6bdf66b65ff7c00ec58c4deccffd167bfee7a85698880dfa485df3de1ec18a5b2d1dc12849743d1c74320108360a2d40d223b35fbc1c4ea03bbd8306480c62
[19:31:06 INFO    handler] processing: Verb=set Name=GTgrvP Value=31921 address=1cf12606ac7db03c756133c07d7d02b59f3ef9eae6774fe59c75c88ab66a9fabbbaef9975dbf9aa197d1090ed126d7b18e2

Config Transaction Family Usage

Sawtooth Lake provides a config transaction family that stores on- chain configuration settings, along with a config family transaction processor written in Python.

Caution

A config transaction processor container and rest api container are started for you if you’re using the Docker workflow. You can skip to Step Three: Create And Submit Batch or read on to learn how to start the config transaction processor and rest api.

One of the on-chain settings is the list of supported transaction families. To configure this setting, follow these steps:

Step One: Start Config Family Processor

To start the config family transaction processor, run the following commands from the Vagrant CLI:

$ tp_config tcp://localhost:40000

Confirm that the transaction processor registers with the validator by viewing the Vagrant shell in which the validator is running. A successful registration event produces the following output:

[21:03:55.955 INFO    processor_handlers] registered transaction processor: identity=b'6d2d80275ae280ea', family=sawtooth_config, version=1.0, encoding=application/protobuf, namespaces=<google.protobuf.pyext._message.RepeatedScalarContainer object at 0x7e1ff042f6c0>
[21:03:55.956 DEBUG   interconnect] ServerThread sending TP_REGISTER_RESPONSE to b'6d2d80275ae280ea'

Step Two: Starting the Rest API

In order to configure a running validator, you must start the REST API application. Run the following command to start the rest api:

rest_api --stream-url tcp://127.0.0.1:40000

Step Three: Create And Submit Batch

In the example below, a JSON array is submitted to the sawtooth config command, which creates and submits a batch of transactions containing the configuration change.

The JSON array used tells the validator or validator network to accept transactions of the following types:

  • intkey
  • sawtooth_config

To create and submit the batch containing the new configuration, enter the following commands from the Vagrant CLI:

$ sawtooth keygen my_key
$ sawtooth config proposal create --key /home/ubuntu/.sawtooth/keys/my_key.priv sawtooth.validator.transaction_families='[{"family": "intkey", "version": "1.0", "encoding": "application/protobuf"}, {"family":"sawtooth_config", "version":"1.0", "encoding":"application/protobuf"}]'

Or from the Docker CLI:

$ sawtooth keygen my_key
$ sawtooth config proposal create --key /root/.sawtooth/keys/my_key.priv sawtooth.validator.transaction_families='[{"family": "intkey", "version": "1.0", "encoding": "application/protobuf"}, {"family":"sawtooth_config", "version":"1.0", "encoding":"application/protobuf"}]' --url http://rest_api:8080

A TP_PROCESS_REQUEST message appears in the logging output of the validator.

Viewing Blocks and State

You can view the blocks stored in the block-chain, and the nodes of the Markle tree, using the sawtooth CLI.

Note

The sawtooth CLI provides help for all subcommands. For example, to get help for the block subcommand, enter the command sawtooth block -h.

Log in to the Vagrant environment with the command vagrant ssh to run the commands below.

Starting the Rest API

Caution

As with the transaction processors above, a rest api container is started for you with the Docker workflow.

In order to submit queries to the validator, you must start the REST API application. Run the following command to start the rest api:

rest_api --stream-url tcp://127.0.0.1:40000

Viewing List Of Blocks

Enter the command sawtooth block list to view the blocks stored by the state:

In Vagrant:

$ sawtooth block list

In Docker:

$ sawtooth block list --url http://rest_api:8080
NUM  BLOCK_ID
8    22e79778855768ea380537fb13ad210b84ca5dd1cdd555db7792a9d029113b0a183d5d71cc5558e04d10a9a9d49031de6e86d6a7ddb25325392d15bb7ccfd5b7  2     8     02a0e049...
7    c84346f5e18c6ce29f1b3e6e31534da7cd538533457768f86a267053ddf73c4f1139c9055be283dfe085c94557de24726191eee9996d4192d21fa6acb0b29152  2     20    02a0e049...
6    efc0d6175b6329ac5d0814546190976bc6c4e18bd0630824c91e9826f93c7735371f4565a8e84c706737d360873fac383ab1cf289f9bf640b92c570cb1ba1875  2     27    02a0e049...
5    840c0ef13023f93e853a4555e5b46e761fc822d4e2d9131581fdabe5cb85f13e2fb45a0afd5f5529fbde5216d22a88dddec4b29eeca5ac7a7b1b1813fcc1399a  2     16    02a0e049...
4    4d6e0467431a409185e102301b8bdcbdb9a2b177de99ae139315d9b0fe5e27aa3bd43bda6b168f3ac8f45e84b069292ddc38ec6a1848df16f92cd35c5bd6e6c9  2     20    02a0e049...
3    9743e39eadf20e922e242f607d847445aba18dacdf03170bf71e427046a605744c84d9cb7d440d257c21d11e4da47e535ba7525afcbbc037da226db48a18f4a8  2     22    02a0e049...
2    6d7e641232649da9b3c23413a31db09ebec7c66f8207a39c6dfcb21392b033163500d367f8592b476e0b9c1e621d6c14e8c0546a7377d9093fb860a00c1ce2d3  2     38    02a0e049...
1    7252a5ab3440ee332aef5830b132cf9dc3883180fb086b2a50f62bf7c6c8ff08311b8009da3b3f6e38d3cfac1b3ac4cfd9a864d6a053c8b27df63d1c730469b3  2     120   02a0e049...
0    8821a997796f3e38a28dbb8e418ed5cbdd60b8a2e013edd20bca7ebf9a58f1302740374d98db76137e48b41dc404deda40ca4d2303a349133991513d0fec4074  0     0     02a0e049...

Viewing A Particular Block

Using the sawtooth block list command as shown above, copy the block id you want to view, then use the sawtooth block show command (truncated output shown):

In Vagrant:

$ sawtooth block show 22e79778855768ea380537fb13ad210b84ca5dd1cdd555db7792a9d029113b0a183d5d71cc5558e04d10a9a9d49031de6e86d6a7ddb25325392d15bb7ccfd5b7

In Docker:

$ sawtooth block show --url http://rest_api:8080 22e79778855768ea380537fb13ad210b84ca5dd1cdd555db7792a9d029113b0a183d5d71cc5558e04d10a9a9d49031de6e86d6a7ddb25325392d15bb7ccfd5b7
  batches:
- header:
    signer_pubkey: 0380be3421629849b1d03af520d7fa2cdc24c2d2611771ddf946ef3aaae216be84
    transaction_ids:
    - c498c916da09450597053ada1938858a11d94e2ed5c18f92cd7d34b865af646144d180bdc121a48eb753b4abd326baa3ea26ee8a29b07119052320370d24ab84
    - c68de164421bbcfcc9ea60b725bae289aecd02ddde6f520e6e85b3227337e2971e89bbff468bdebe408e0facc343c612a32db98e5ac4da2296a7acf4033073cd
    - faf9121f9744716363253cb0ff4b6011093ada6e19dae63ae04a58a1fca25424779a13628a047c009d2e73d0e7baddc95b428b4a22cf1c60961d6dcae8ee60fa
  header_signature: 2ff874edfa80a8e6b718e7d10e91970150fcc3fcfd46d38eb18f356e7a733baa40d9e816247985d7ea7ef2492c09cd9c1830267471c6e35dca0d19f5c6d2b61e
  transactions:
  - header:
      batcher_pubkey: 0380be3421629849b1d03af520d7fa2cdc24c2d2611771ddf946ef3aaae216be84
      dependencies:
      - 19ad647bd292c980e00f05eed6078b471ca2d603b842bc4eaecf301d61f15c0d3705a4ec8d915ceb646f35d443da43569f58c906faf3713853fe638c7a0ea410
      family_name: intkey
      family_version: '1.0'
      inputs:
      - 1cf126c15b04cb20206d45c4d0e432d036420401dbd90f064683399fae55b99af1a543f7de79cfafa4f220a22fa248f8346fb1ad0343fcf8d7708565ebb8a3deaac09d
      nonce: 0x1.63021cad39ceep+30
      outputs:
      - 1cf126c15b04cb20206d45c4d0e432d036420401dbd90f064683399fae55b99af1a543f7de79cfafa4f220a22fa248f8346fb1ad0343fcf8d7708565ebb8a3deaac09d
      payload_encoding: application/cbor
      payload_sha512: 942a09c0254c4a5712ffd152dc6218fc5453451726d935ac1ba67de93147b5e7be605da7ab91245f48029b41f493a1cc8dfc45bb090ac97420580eb1bdded01f
      signer_pubkey: 0380be3421629849b1d03af520d7fa2cdc24c2d2611771ddf946ef3aaae216be84
    header_signature: c498c916da09450597053ada1938858a11d94e2ed5c18f92cd7d34b865af646144d180bdc121a48eb753b4abd326baa3ea26ee8a29b07119052320370d24ab84
    payload: o2ROYW1lZnFrbGR1emVWYWx1ZQFkVmVyYmNpbmM=

Viewing The State

Use the command sawtooth state list to list the nodes in the Merkle tree (truncated list):

In Vagrant:

$ sawtooth state list

In Docker:

$ sawtooth state list --url http://rest_api:8080
ADDRESS                                                                                                                                SIZE DATA
1cf126ddb507c936e4ee2ed07aa253c2f4e7487af3a0425f0dc7321f94be02950a081ab7058bf046c788dbaf0f10a980763e023cde0ee282585b9855e6e5f3715bf1fe 11   b'\xa1fcCTdcH\x...
1cf1260cd1c2492b6e700d5ef65f136051251502e5d4579827dc303f7ed76ddb7185a19be0c6443503594c3734141d2bdcf5748a2d8c75541a8e568bae063983ea27b9 11   b'\xa1frdLONu\x...
1cf126ed7d0ac4f755be5dd040e2dfcd71c616e697943f542682a2feb14d5f146538c643b19bcfc8c4554c9012e56209f94efe580b6a94fb326be9bf5bc9e177d6af52 11   b'\xa1fAUZZqk\x...
1cf126c46ff13fcd55713bcfcf7b66eba515a51965e9afa8b4ff3743dc6713f4c40b4254df1a2265d64d58afa14a0051d3e38999704f6e25c80bed29ef9b80aee15c65 11   b'\xa1fLvUYLk\x...
1cf126c4b1b09ebf28775b4923e5273c4c01ba89b961e6a9984632612ec9b5af82a0f7c8fc1a44b9ae33bb88f4ed39b590d4774dc43c04c9a9bd89654bbee68c8166f0 13   b'\xa1fXHonWY\x...
1cf126e924a506fb2c4bb8d167d20f07d653de2447df2754de9eb61826176c7896205a17e363e457c36ccd2b7c124516a9b573d9a6142f031499b18c127df47798131a 13   b'\xa1foWZXEz\x...
1cf126c295a476acf935cd65909ed5ead2ec0168f3ee761dc6f37ea9558fc4e32b71504bf0ad56342a6671db82cb8682d64689838731da34c157fa045c236c97f1dd80 13   b'\xa1fadKGve\x...

Viewing Data In A Node

Using the sawtooth state list command show above, copy the node id you want to view, then use the sawtooth state show command to view the node:

In Vagrant:

$ sawtooth state show 1cf126ddb507c936e4ee2ed07aa253c2f4e7487af3a0425f0dc7321f94be02950a081ab7058bf046c788dbaf0f10a980763e023cde0ee282585b9855e6e5f3715bf1fe

In Docker:

$ sawtooth state show --url http://rest_api:8080 1cf126ddb507c936e4ee2ed07aa253c2f4e7487af3a0425f0dc7321f94be02950a081ab7058bf046c788dbaf0f10a980763e023cde0ee282585b9855e6e5f3715bf1fe
DATA: "b'\xa1fcCTdcH\x192B'"
HEAD: "0c4364c6d5181282a1c7653038ec9515cb0530c6bfcb46f16e79b77cb524491676638339e8ff8e3cc57155c6d920e6a4d1f53947a31dc02908bcf68a91315ad5"

Using Sawtooth Cluster To Start A Network

Caution

The sawtooth cluster command is not intended for use inside the Docker environment.

The sawtooth cluster command can be used to start a network of validators and transaction processors.

The following command will start a network of two validators and two transaction processors:

$ sawtooth cluster start --count 2 -m subprocess -P tp_intkey_python

You can view the running processes that are part of the network with the following command:

$ ps -ef | grep python
ubuntu   26036 22422 14 22:59 pts/0    00:00:02 python /project/sawtooth-core/bin/sawtooth cluster start --count 2 -m subprocess -P tp_intkey_python
ubuntu   26039 26036  7 23:00 pts/0    00:00:00 python3 /project/sawtooth-core/bin/validator --component-endpoint 0.0.0.0:40000 --network-endpoint tcp://0.0.0.0:8800
ubuntu   26040 26036  8 23:00 pts/0    00:00:00 python3 /project/sawtooth-core/bin/tp_intkey_python 0.0.0.0:40000
ubuntu   26041 26036  7 23:00 pts/0    00:00:00 python3 /project/sawtooth-core/bin/validator --component-endpoint 0.0.0.0:40001 --network-endpoint tcp://0.0.0.0:8801
ubuntu   26042 26036  7 23:00 pts/0    00:00:00 python3 /project/sawtooth-core/bin/tp_intkey_python 0.0.0.0:40001

To submit sample transactions, follow the steps above under Creating and submitting transactions.

To stop a running network that was started using the subprocess management method, simply press CTRL-c.