github.com/muhammedhassanm/blockchain@v0.0.0-20200120143007-697261defd4d/sawtooth-core-master/docs/source/app_developers_guide/aws.rst (about) 1 *********************** 2 Using AWS with Sawtooth 3 *********************** 4 5 This tutorial explains how to set up Hyperledger Sawtooth for application 6 development using the Amazon Elastic Compute Cloud (Amazon EC2) service. 7 It shows you how to launch an instance of a Sawtooth validator node from the 8 `Amazon Web Services (AWS) Marketplace <https://aws.amazon.com/marketplace/pp/B075TKQCC2>`_, 9 then walks you through the following tasks: 10 11 * Checking the status of Sawtooth components 12 * Using Sawtooth commands to submit transactions, display block data, and view 13 global state 14 * Examining Sawtooth logs 15 * Resetting the AWS Sawtooth instance 16 17 .. note:: 18 19 This environment requires an AWS account. If you don't have one yet, Amazon 20 provides free accounts so you can try the Sawtooth platform. Sign up at 21 `aws.amazon.com/free <https://aws.amazon.com/free/>`_. 22 23 After completing this tutorial, you will have the application development 24 environment that is required for the other tutorials in this guide. The next 25 tutorial introduces the XO transaction family by using the ``xo`` client 26 commands to play a game of tic-tac-toe. The final set of tutorials describe how 27 to use an SDK to create a transaction family that implements your application's 28 business logic. 29 30 31 About the Application Development Environment 32 ============================================= 33 34 The AWS application development environment is a single validator node that is 35 running a validator, a REST API, and three transaction processors. This 36 environment uses Developer mode (dev mode) consensus and serial transaction 37 processing. 38 39 .. figure:: ../images/appdev-environment-one-node-3TPs.* 40 :width: 100% 41 :align: center 42 :alt: AWS application development environment for Sawtooth 43 44 This environment introduces basic Sawtooth functionality with the 45 `IntegerKey <../transaction_family_specifications/integerkey_transaction_family>`_ 46 and 47 `Settings <../transaction_family_specifications/settings_transaction_family>`_ 48 transaction processors for the business logic and Sawtooth commands as a client. 49 It also includes the 50 `XO <../transaction_family_specifications/xo_transaction_family>`_ 51 transaction processor, which is used in the advanced tutorials. 52 53 The IntegerKey and XO families are simple examples of a transaction family, but 54 Settings is a reference implementation. In a production environment, you should 55 always run a transaction processor that supports the Settings transaction 56 family. 57 58 .. note:: 59 60 The Amazon Machine Image (AMI) for Sawtooth has a ``systemd`` service that 61 handles environment setup steps such as generating keys and creating a 62 genesis block. To learn how the typical startup process works, see 63 :doc:`ubuntu`. 64 65 66 Step 1: Launch a Sawtooth Instance 67 ================================== 68 69 #. Launch a Sawtooth instance from the `Hyperledger Sawtooth product page 70 on the AWS Marketplace <https://aws.amazon.com/marketplace/pp/B075TKQCC2>`_. 71 For more information, see the Amazon guide 72 `Launching an AWS Marketplace Instance 73 <http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/launch-marketplace-console.html>`_. 74 75 .. note:: 76 77 The default security group with recommended settings for Sawtooth 78 allows inbound SSH traffic only. 79 80 * To attach a transaction processor remotely, add an inbound rule to 81 allow TCP traffic on port 4004. 82 83 * To access the REST API remotely, add an inbound rule to allow TCP 84 traffic on port 8008. 85 86 * To communicate with another validator node, add an inbound rule to 87 allow TCP traffic on port 8800. 88 89 For information on editing the security group rules, see Amazon's 90 Security Groups documentation, 91 `Adding, Removing, and Updating Rules <http://docs.aws.amazon.com/AmazonVPC/latest/UserGuide/VPC_SecurityGroups.html#AddRemoveRules>`_. 92 93 #. Log into this Sawtooth instance. Use the user name ``ubuntu`` when 94 connecting. 95 96 For more information, see the Amazon guide 97 `Connect to Your Linux Instance <http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/AccessingInstances.html>`_. 98 99 Once launched, the Sawtooth instance continues to run until you stop it. 100 If you're uncertain about the state or would like to start over, see 101 :ref:`reset-aws-ubuntu-label`. 102 103 104 .. _confirming-connectivity-aws-label: 105 106 Step 2: Check the Status of Sawtooth Components 107 =============================================== 108 109 #. You can use ``ps`` to check that each Sawtooth component is running: 110 111 .. code-block:: console 112 113 $ ps aux | grep [s]awtooth 114 sawtooth 27556 32.3 2.5 5371560864 407176 ? Ssl 15:15 15:53 /usr/bin/python3 /usr/bin/sawtooth-validator 115 sawtooth 27592 1.1 0.2 305796 38816 ? Ssl 15:15 0:33 /usr/bin/python3 /usr/bin/sawtooth-rest-api 116 sawtooth 27622 0.0 0.2 278176 33708 ? Ssl 15:15 0:00 /usr/bin/python3 /usr/bin/identity-tp -v -C tcp://localhost:4004 117 sawtooth 27712 0.0 0.2 278172 33632 ? Ssl 15:15 0:00 /usr/bin/python3 /usr/bin/settings-tp -C tcp://localhost:4004 118 119 #. Or you can use ``systemctl``: 120 121 .. code-block:: console 122 123 $ systemctl | grep [s]awtooth 124 sawtooth-identity-tp.service 125 loaded active running Sawtooth TP Identity 126 sawtooth-rest-api.service 127 loaded active running Sawtooth REST API 128 sawtooth-settings-tp.service 129 loaded active running Sawtooth TP Settings 130 sawtooth-validator.service 131 loaded active running Sawtooth Validator Server 132 133 Step 3: Confirm Connectivity to the REST API 134 ============================================ 135 136 Confirm that you can connect to the REST API from your host system. Enter 137 the following ``curl`` command from a terminal window: 138 139 .. code-block:: console 140 141 $ curl http://localhost:8008/blocks 142 143 144 .. _configure-tf-settings-aws-label: 145 146 Step 4: Use Sawtooth Commands as a Client 147 ========================================= 148 149 Sawtooth includes commands that act as a client application. This step describes 150 how to use the ``intkey`` and ``sawtooth`` commands to create and submit 151 transactions, display blockchain and block data, and examine global state data. 152 153 .. note:: 154 155 Use the ``--help`` option with any Sawtooth command to display the available 156 options and subcommands. 157 158 Creating and Submiting Transactions with intkey 159 ----------------------------------------------- 160 161 The ``intkey`` command creates sample IntegerKey transactions for testing 162 purposes. 163 164 #. Use ``intkey create_batch`` to prepare batches of transactions that set 165 a few keys to random values, then randomly increment and decrement those 166 values. These batches are saved locally in the file ``batches.intkey``. 167 168 .. code-block:: console 169 170 $ intkey create_batch --count 10 --key-count 5 171 Writing to batches.intkey... 172 173 #. Use ``intkey load`` to submit the batches to the validator. 174 175 .. code-block:: console 176 177 $ intkey load 178 batches: 11 batch/sec: 141.7800162868952 179 180 #. The validator displays many log messages showing that the validator is 181 handling the submitted transactions and processing blocks, as in 182 this truncated example: 183 184 .. code-block:: console 185 186 ... 187 78c295614594319ece3fac71145c05ca36fadc3bd6e65 (block_num:13, state:addbd88bc80ecb05793750b7c80b91588043a1287cd8d4b6e0b1e6a68a0e4017, previous_block_id:f4323dfc238938db834aa5d40b4e6c2825bf7eae5cdaf73a9da28cb308a765707e85ac06e72b01e3d7d529132329b55b18d0cc71ab026506edd63bc6b718e80a)^[[0m 188 [2018-03-14 16:24:49.621 INFO chain] Starting block validation of : 60c0c348a00cde622a3664d6d4fb949736b78f8bcb6b77bd0300cdc7675ca9d4116ee23ec18c7cfee5978c295614594319ece3fac71145c05ca36fadc3bd6e65 (block_num:13, state:addbd88bc80ecb05793750b7c80b91588043a1287cd8d4b6e0b1e6a68a0e4017, previous_block_id:f4323dfc238938db834aa5d40b4e6c2825bf7eae5cdaf73a9da28cb308a765707e85ac06e72b01e3d7d529132329b55b18d0cc71ab026506edd63bc6b718e80a) 189 [2018-03-14 16:24:49.646 INFO chain] Comparing current chain head 'f4323dfc238938db834aa5d40b4e6c2825bf7eae5cdaf73a9da28cb308a765707e85ac06e72b01e3d7d529132329b55b18d0cc71ab026506edd63bc6b718e80a (block_num:12, state:c30ed78dde19d9ff58587a8bdd4aa435e09212cd1fee3e95d88faafe44f207cc, previous_block_id:dc98ce9029e6e3527bca18060cbb1325b545054b1589f2df7bf200fb0a09d0572491a3837dea1baf2981f5a960bd108f198806c974efcb3b69d2712809cc6065)' against new block '60c0c348a00cde622a3664d6d4fb949736b78f8bcb6b77bd0300cdc7675ca9d4116ee23ec18c7cfee5978c295614594319ece3fac71145c05ca36fadc3bd6e65 (block_num:13, state:addbd88bc80ecb05793750b7c80b91588043a1287cd8d4b6e0b1e6a68a0e4017, previous_block_id:f4323dfc238938db834aa5d40b4e6c2825bf7eae5cdaf73a9da28cb308a765707e85ac06e72b01e3d7d529132329b55b18d0cc71ab026506edd63bc6b718e80a)' 190 [2018-03-14 16:24:49.647 INFO chain] Fork comparison at height 13 is between - and 60c0c348 191 [2018-03-14 16:24:49.647 INFO chain] Chain head updated to: 60c0c348a00cde622a3664d6d4fb949736b78f8bcb6b77bd0300cdc7675ca9d4116ee23ec18c7cfee5978c295614594319ece3fac71145c05ca36fadc3bd6e65 (block_num:13, state:addbd88bc80ecb05793750b7c80b91588043a1287cd8d4b6e0b1e6a68a0e4017, previous_block_id:f4323dfc238938db834aa5d40b4e6c2825bf7eae5cdaf73a9da28cb308a765707e85ac06e72b01e3d7d529132329b55b18d0cc71ab026506edd63bc6b718e80a) 192 [2018-03-14 16:24:49.648 INFO publisher] Now building on top of block: 60c0c348a00cde622a3664d6d4fb949736b78f8bcb6b77bd0300cdc7675ca9d4116ee23ec18c7cfee5978c295614594319ece3fac71145c05ca36fadc3bd6e65 (block_num:13, state:addbd88bc80ecb05793750b7c80b91588043a1287cd8d4b6e0b1e6a68a0e4017, previous_block_id:f4323dfc238938db834aa5d40b4e6c2825bf7eae5cdaf73a9da28cb308a765707e85ac06e72b01e3d7d529132329b55b18d0cc71ab026506edd63bc6b718e80a) 193 [2018-03-14 16:24:49.649 DEBUG chain] Verify descendant blocks: 60c0c348a00cde622a3664d6d4fb949736b78f8bcb6b77bd0300cdc7675ca9d4116ee23ec18c7cfee5978c295614594319ece3fac71145c05ca36fadc3bd6e65 (block_num:13, state:addbd88bc80ecb05793750b7c80b91588043a1287cd8d4b6e0b1e6a68a0e4017, previous_block_id:f4323dfc238938db834aa5d40b4e6c2825bf7eae5cdaf73a9da28cb308a765707e85ac06e72b01e3d7d529132329b55b18d0cc71ab026506edd63bc6b718e80a) ([]) 194 [2018-03-14 16:24:49.651 INFO chain] Finished block validation of: 60c0c348a00cde622a3664d6d4fb949736b78f8bcb6b77bd0300cdc7675ca9d4116ee23ec18c7cfee5978c295614594319ece3fac71145c05ca36fadc3bd6e65 (block_num:13, state:addbd88bc80ecb05793750b7c80b91588043a1287cd8d4b6e0b1e6a68a0e4017, previous_block_id:f4323dfc238938db834aa5d40b4e6c2825bf7eae5cdaf73a9da28cb308a765707e85ac06e72b01e3d7d529132329b55b18d0cc71ab026506edd63bc6b718e80a) 195 196 197 #. The REST API displays a log message as it communicates with the intkey 198 transaction processor. 199 200 .. code-block:: console 201 202 [2018-03-14 16:24:49.587 INFO helpers] POST /batches HTTP/1.1: 202 status, 1639 size, in 0.030922 s 203 204 #. You can also look at the Sawtooth log files to see what happened. Use the 205 following command to display the last 10 entries in the intkey log file, 206 which show that values have been changed. 207 208 .. code-block:: console 209 210 user@client$ sudo bash -c "tail -10 /var/log/sawtooth/intkey-*-debug.log" 211 [2018-03-14 16:24:49.587 [MainThread] core DEBUG] received message of type: TP_PROCESS_REQUEST 212 [2018-03-14 16:24:49.588 [MainThread] handler DEBUG] incrementing "MvRznE" by 1 213 [2018-03-14 16:24:49.624 [MainThread] core DEBUG] received message of type: TP_PROCESS_REQUEST 214 [2018-03-14 16:24:49.625 [MainThread] handler DEBUG] incrementing "iJWCRq" by 5 215 [2018-03-14 16:24:49.629 [MainThread] core DEBUG] received message of type: TP_PROCESS_REQUEST 216 [2018-03-14 16:24:49.630 [MainThread] handler DEBUG] incrementing "vJJL1N" by 8 217 [2018-03-14 16:24:49.634 [MainThread] core DEBUG] received message of type: TP_PROCESS_REQUEST 218 [2018-03-14 16:24:49.636 [MainThread] handler DEBUG] incrementing "vsTbBo" by 4 219 [2018-03-14 16:24:49.639 [MainThread] core DEBUG] received message of type: TP_PROCESS_REQUEST 220 [2018-03-14 16:24:49.641 [MainThread] handler DEBUG] incrementing "MvRznE" by 1 221 222 .. note:: 223 224 The log file names for the transaction processors contain a random 225 string that is unique for each instance of the transaction processor. 226 For more information, see :ref:`examine-logs-ubuntu-label`. 227 228 Submitting Transactions with sawtooth batch submit 229 -------------------------------------------------- 230 231 In the example above, the ``intkey create_batch`` command created the file 232 ``batches.intkey``. Rather than using ``intkey load`` to submit these 233 transactions, you could use the following command to submit them. 234 235 #. As before, create a batch of transactions. 236 237 .. code-block:: console 238 239 $ intkey create_batch --count 10 --key-count 5 240 Writing to batches.intkey... 241 242 #. Submit the batch file with the following command: 243 244 .. code-block:: console 245 246 $ sawtooth batch submit -f batches.intkey 247 batches: 11, batch/sec: 216.80369536716367 248 249 Viewing Blockchain and Block Data with sawtooth block 250 ----------------------------------------------------- 251 252 The ``sawtooth block`` command displays information about the blocks stored on 253 the blockchain. 254 255 #. Use ``sawtooth block list`` to display the list of blocks stored in state. 256 257 .. code-block:: console 258 259 $ sawtooth block list 260 261 The output incudes the block ID, as in this example: 262 263 .. code-block:: console 264 265 NUM BLOCK_ID 266 8 22e79778855768ea380537fb13ad210b84ca5dd1cdd555db7792a9d029113b0a183d5d71cc5558e04d10a9a9d49031de6e86d6a7ddb25325392d15bb7ccfd5b7 2 8 02a0e049... 267 7 c84346f5e18c6ce29f1b3e6e31534da7cd538533457768f86a267053ddf73c4f1139c9055be283dfe085c94557de24726191eee9996d4192d21fa6acb0b29152 2 20 02a0e049... 268 6 efc0d6175b6329ac5d0814546190976bc6c4e18bd0630824c91e9826f93c7735371f4565a8e84c706737d360873fac383ab1cf289f9bf640b92c570cb1ba1875 2 27 02a0e049... 269 5 840c0ef13023f93e853a4555e5b46e761fc822d4e2d9131581fdabe5cb85f13e2fb45a0afd5f5529fbde5216d22a88dddec4b29eeca5ac7a7b1b1813fcc1399a 2 16 02a0e049... 270 4 4d6e0467431a409185e102301b8bdcbdb9a2b177de99ae139315d9b0fe5e27aa3bd43bda6b168f3ac8f45e84b069292ddc38ec6a1848df16f92cd35c5bd6e6c9 2 20 02a0e049... 271 3 9743e39eadf20e922e242f607d847445aba18dacdf03170bf71e427046a605744c84d9cb7d440d257c21d11e4da47e535ba7525afcbbc037da226db48a18f4a8 2 22 02a0e049... 272 2 6d7e641232649da9b3c23413a31db09ebec7c66f8207a39c6dfcb21392b033163500d367f8592b476e0b9c1e621d6c14e8c0546a7377d9093fb860a00c1ce2d3 2 38 02a0e049... 273 1 7252a5ab3440ee332aef5830b132cf9dc3883180fb086b2a50f62bf7c6c8ff08311b8009da3b3f6e38d3cfac1b3ac4cfd9a864d6a053c8b27df63d1c730469b3 2 120 02a0e049... 274 0 8821a997796f3e38a28dbb8e418ed5cbdd60b8a2e013edd20bca7ebf9a58f1302740374d98db76137e48b41dc404deda40ca4d2303a349133991513d0fec4074 0 0 02a0e049... 275 276 #. From the output generated by ``sawtooth block list``, copy the ID of a block 277 you want to view, then paste it in place of ``{BLOCK_ID}`` in the following 278 command. 279 280 .. code-block:: console 281 282 $ sawtooth block show {BLOCK_ID} 283 284 The output of this command can be quite long, because it includes all data 285 stored under that block. This is a truncated example: 286 287 .. code-block:: console 288 289 batches: 290 - header: 291 signer_public_key: 0276023d4f7323103db8d8683a4b7bc1eae1f66fbbf79c20a51185f589e2d304ce 292 transaction_ids: 293 - 24b168aaf5ea4a76a6c316924a1c26df0878908682ea5740dd70814e7c400d56354dee788191be8e28393c70398906fb467fac8db6279e90e4e61619589d42bf 294 header_signature: a93731646a8fd2bce03b3a17bc2cb3192d8597da93ce735950dccbf0e3cf0b005468fadb94732e013be0bc2afb320be159b452cf835b35870db5fa953220fb35 295 transactions: 296 - header: 297 batcher_public_key: 0276023d4f7323103db8d8683a4b7bc1eae1f66fbbf79c20a51185f589e2d304ce 298 dependencies: [] 299 family_name: sawtooth_settings 300 family_version: '1.0' 301 ... 302 header: 303 batch_ids: 304 - a93731646a8fd2bce03b3a17bc2cb3192d8597da93ce735950dccbf0e3cf0b005468fadb94732e013be0bc2afb320be159b452cf835b35870db5fa953220fb35 305 block_num: 3 306 consensus: RGV2bW9kZQ== 307 previous_block_id: 042f08e1ff49bbf16914a53dc9056fb6e522ca0e2cff872547eac9555c1de2a6200e67fb9daae6dfb90f02bef6a9088e94e5bdece04f622bce67ccecd678d56e 308 signer_public_key: 033fbed13b51eafaca8d1a27abc0d4daf14aab8c0cbc1bb4735c01ff80d6581c52 309 state_root_hash: 5d5ea37cbbf8fe793b6ea4c1ba6738f5eee8fc4c73cdca797736f5afeb41fbef 310 header_signature: ff4f6705bf57e2a1498dc1b649cc9b6a4da2cc8367f1b70c02bc6e7f648a28b53b5f6ad7c2aa639673d873959f5d3fcc11129858ecfcb4d22c79b6845f96c5e3 311 312 Viewing State Data with sawtooth state 313 -------------------------------------- 314 315 The ``sawtooth state`` command lets you display state data. Sawtooth stores 316 state data in a :term:`Merkle-Radix tree`; for more information, see 317 :doc:`../architecture/global_state`. 318 319 #. Use ``sawtooth state list`` to list the nodes (addresses) in state: 320 321 .. code-block:: console 322 323 $ sawtooth state list 324 325 The output will be similar to this truncated example: 326 327 .. code-block:: console 328 329 ADDRESS SIZE DATA 330 1cf126ddb507c936e4ee2ed07aa253c2f4e7487af3a0425f0dc7321f94be02950a081ab7058bf046c788dbaf0f10a980763e023cde0ee282585b9855e6e5f3715bf1fe 11 b'\xa1fcCTdcH\x... 331 1cf1260cd1c2492b6e700d5ef65f136051251502e5d4579827dc303f7ed76ddb7185a19be0c6443503594c3734141d2bdcf5748a2d8c75541a8e568bae063983ea27b9 11 b'\xa1frdLONu\x... 332 1cf126ed7d0ac4f755be5dd040e2dfcd71c616e697943f542682a2feb14d5f146538c643b19bcfc8c4554c9012e56209f94efe580b6a94fb326be9bf5bc9e177d6af52 11 b'\xa1fAUZZqk\x... 333 1cf126c46ff13fcd55713bcfcf7b66eba515a51965e9afa8b4ff3743dc6713f4c40b4254df1a2265d64d58afa14a0051d3e38999704f6e25c80bed29ef9b80aee15c65 11 b'\xa1fLvUYLk\x... 334 1cf126c4b1b09ebf28775b4923e5273c4c01ba89b961e6a9984632612ec9b5af82a0f7c8fc1a44b9ae33bb88f4ed39b590d4774dc43c04c9a9bd89654bbee68c8166f0 13 b'\xa1fXHonWY\x... 335 1cf126e924a506fb2c4bb8d167d20f07d653de2447df2754de9eb61826176c7896205a17e363e457c36ccd2b7c124516a9b573d9a6142f031499b18c127df47798131a 13 b'\xa1foWZXEz\x... 336 1cf126c295a476acf935cd65909ed5ead2ec0168f3ee761dc6f37ea9558fc4e32b71504bf0ad56342a6671db82cb8682d64689838731da34c157fa045c236c97f1dd80 13 b'\xa1fadKGve\x... 337 338 #. Use ``sawtooth state show`` to view state data at a specific address (a node 339 in the Merkle-Radix database). Copy the address from the output of 340 ``sawtooth state list``, then paste it in place of ``{STATE_ADDRESS}`` in 341 the following command: 342 343 .. code-block:: console 344 345 $ sawtooth state show {STATE_ADDRESS} 346 347 The output shows the bytes stored at that address and the block ID of the 348 "chain head" that the current state is tied to, as in this example: 349 350 .. code-block:: console 351 352 DATA: "b'\xa1fcCTdcH\x192B'" 353 HEAD: "0c4364c6d5181282a1c7653038ec9515cb0530c6bfcb46f16e79b77cb524491676638339e8ff8e3cc57155c6d920e6a4d1f53947a31dc02908bcf68a91315ad5" 354 355 356 .. _examine-logs-aws-label: 357 358 Step 5: Examine Sawtooth Logs 359 ============================= 360 361 By default, Sawtooth logs are stored in the directory ``/var/log/sawtooth``. 362 Each component (validator, REST API, and transaction processors) has both a 363 debug log and an error log. This example shows the log files for this 364 application development environment: 365 366 .. code-block:: console 367 368 $ ls -1 /var/log/sawtooth 369 identity-f5c42a08548c4ffa-debug.log 370 identity-f5c42a08548c4ffa-error.log 371 intkey-ae98c3726f9743c4-debug.log 372 intkey-ae98c3726f9743c4-error.log 373 rest_api-debug.log 374 rest_api-error.log 375 settings-6d591c44915b465c-debug.log 376 settings-6d591c44915b465c-error.log 377 validator-debug.log 378 validator-error.log 379 xo-9b8b55265ca0d546-error.log 380 xo-9b8b55265ca0d546-debug.log 381 382 .. note:: 383 384 For the transaction processors, the log file names contain a random string to 385 make the names unique. This string changes for each instance of a transaction 386 processor. The file names on your system will be different than these 387 examples. 388 389 For more information on log files, see 390 :doc:`../sysadmin_guide/log_configuration`. 391 392 393 .. _reset-aws-ubuntu-label: 394 395 Step 6: Reset the AWS Environment (Optional) 396 ============================================ 397 398 When you are done with the AWS environment (or if you want to reset it), you can 399 use the following commands to restore the Sawtooth instance to its original 400 state. 401 402 .. code-block:: console 403 404 $ sudo rm /var/lib/sawtooth/config-genesis.batch 405 $ sudo systemctl restart sawtooth-setup.service 406 407 The first command removes the file ``config-genesis.batch``. The second command 408 restarts the ``sawtooth-setup`` service, which cleans up your validator, creates 409 a new genesis block, and restarts the ``sawtooth-validator`` service so that 410 you're ready to build on a new blockchain. 411 412 413 .. Licensed under Creative Commons Attribution 4.0 International License 414 .. https://creativecommons.org/licenses/by/4.0/