From 20eadfd7f0a5957cbfbb86ee43b404cd609e4a8f Mon Sep 17 00:00:00 2001 From: Gregory Haskins Date: Wed, 1 Feb 2017 22:06:11 -0500 Subject: [PATCH] Import release v0.8.0 This is a legacy import of the release originally managed in pure github. You may find the history of this release in the archives here: https://github.com/hyperledger-archives/fabric-chaintool/releases/tag/v0.8.0 Change-Id: I0a5a38b4aae103c534287c3fd8f3a6c269efc9ce Signed-off-by: Gregory Haskins --- .gitignore | 12 + .travis.yml | 1 + CHANGELOG.md | 24 + LICENSE | 202 + MAINTAINERS.txt | 3 + Makefile | 37 + README.md | 427 ++ documentation/platforms/golang/README.md | 115 + examples/example02/README.md | 191 + examples/example02/app/chaincode.yaml | 18 + .../app/src/chaincode/chaincode_example02.go | 152 + .../example02/app/src/interfaces/appinit.cci | 10 + .../org.hyperledger.chaincode.example02.cci | 23 + examples/example02/client/rest/cljs/Makefile | 17 + .../example02/client/rest/cljs/appinit.proto | 19 + .../org.hyperledger.chaincode.example02.proto | 29 + .../example02/client/rest/cljs/project.clj | 24 + .../client/rest/cljs/src/example02/core.cljs | 43 + .../client/rest/cljs/src/example02/main.cljs | 98 + .../client/rest/cljs/src/example02/rpc.cljs | 45 + .../client/rest/nodejs/appinit.proto | 19 + .../example02/client/rest/nodejs/index.js | 101 + .../org.hyperledger.chaincode.example02.proto | 29 + .../example02/client/rest/nodejs/package.json | 14 + examples/example02/client/sdk/Makefile | 18 + examples/example02/client/sdk/appinit.proto | 19 + .../org.hyperledger.chaincode.example02.proto | 29 + examples/example02/client/sdk/project.clj | 27 + .../client/sdk/src/example02/core.cljs | 69 + .../client/sdk/src/example02/hlc/core.cljs | 38 + .../client/sdk/src/example02/hlc/user.cljs | 30 + .../client/sdk/src/example02/main.cljs | 87 + .../client/sdk/src/example02/rpc.cljs | 20 + .../client/sdk/src/example02/util.cljs | 7 + examples/invoker/chaincode.yaml | 26 + examples/invoker/src/chaincode/chaincode.go | 101 + examples/invoker/src/interfaces/appinit.cci | 4 + .../org.hyperledger.chaincode.example02.cci | 23 + examples/parameterless/chaincode.yaml | 18 + examples/parameterless/src/chaincode/main.go | 56 + .../parameterless/src/interfaces/appinit.cci | 2 + ...ledger.chaincode.example.parameterless.cci | 8 + examples/sample_syscc/chaincode.yaml | 29 + examples/sample_syscc/interfaces/appinit.cci | 10 + ...rg.hyperledger.chaincode.system.sample.cci | 23 + examples/sample_syscc/sample_syscc.go | 104 + images/readme-drawings.graffle | 965 ++++ images/typical-workflow.png | Bin 0 -> 221517 bytes lein | 396 ++ project.clj | 36 + resources/generators/golang.stg | 455 ++ resources/generators/proto.stg | 46 + .../org.hyperledger.chaintool.meta.cci | 35 + resources/parsers/interface/grammar.bnf | 67 + resources/parsers/interface/skip.bnf | 13 + resources/parsers/proto/grammar.bnf | 63 + resources/parsers/proto/skip.bnf | 13 + resources/proto/car.proto | 131 + src/chaintool/ast.clj | 33 + src/chaintool/build/core.clj | 22 + src/chaintool/build/interface.clj | 393 ++ src/chaintool/car/abi/Car.java | 4516 +++++++++++++++++ src/chaintool/car/ls.clj | 34 + src/chaintool/car/read.clj | 125 + src/chaintool/car/types.clj | 31 + src/chaintool/car/unpack.clj | 40 + src/chaintool/car/write.clj | 115 + src/chaintool/codecs.clj | 55 + src/chaintool/config/parser.clj | 28 + src/chaintool/config/util.clj | 42 + src/chaintool/core.clj | 179 + src/chaintool/inspect/core.clj | 116 + src/chaintool/platforms/api.clj | 23 + src/chaintool/platforms/core.clj | 31 + src/chaintool/platforms/golang/core.clj | 259 + src/chaintool/platforms/golang/system.clj | 81 + src/chaintool/platforms/golang/userspace.clj | 82 + src/chaintool/protobuf/generate.clj | 152 + src/chaintool/subcommands/build.clj | 28 + src/chaintool/subcommands/buildcar.clj | 39 + src/chaintool/subcommands/clean.clj | 23 + src/chaintool/subcommands/inspect.clj | 26 + src/chaintool/subcommands/ls.clj | 21 + src/chaintool/subcommands/package.clj | 35 + src/chaintool/subcommands/proto.clj | 32 + src/chaintool/subcommands/unpack.clj | 37 + src/chaintool/util.clj | 37 + .../meta/OrgHyperledgerChaintoolMeta.java | 3712 ++++++++++++++ test/chaintool/build/test_interface.clj | 161 + test/chaintool/platforms/golang/test_core.clj | 22 + .../platforms/golang/test_system.clj | 28 + test/chaintool/protobuf/test_generate.clj | 103 + 92 files changed, 15282 insertions(+) create mode 100644 .gitignore create mode 100644 .travis.yml create mode 100644 CHANGELOG.md create mode 100644 LICENSE create mode 100644 MAINTAINERS.txt create mode 100644 Makefile create mode 100644 README.md create mode 100644 documentation/platforms/golang/README.md create mode 100644 examples/example02/README.md create mode 100644 examples/example02/app/chaincode.yaml create mode 100755 examples/example02/app/src/chaincode/chaincode_example02.go create mode 100644 examples/example02/app/src/interfaces/appinit.cci create mode 100644 examples/example02/app/src/interfaces/org.hyperledger.chaincode.example02.cci create mode 100644 examples/example02/client/rest/cljs/Makefile create mode 100644 examples/example02/client/rest/cljs/appinit.proto create mode 100644 examples/example02/client/rest/cljs/org.hyperledger.chaincode.example02.proto create mode 100644 examples/example02/client/rest/cljs/project.clj create mode 100644 examples/example02/client/rest/cljs/src/example02/core.cljs create mode 100644 examples/example02/client/rest/cljs/src/example02/main.cljs create mode 100644 examples/example02/client/rest/cljs/src/example02/rpc.cljs create mode 100644 examples/example02/client/rest/nodejs/appinit.proto create mode 100644 examples/example02/client/rest/nodejs/index.js create mode 100644 examples/example02/client/rest/nodejs/org.hyperledger.chaincode.example02.proto create mode 100644 examples/example02/client/rest/nodejs/package.json create mode 100644 examples/example02/client/sdk/Makefile create mode 100644 examples/example02/client/sdk/appinit.proto create mode 100644 examples/example02/client/sdk/org.hyperledger.chaincode.example02.proto create mode 100644 examples/example02/client/sdk/project.clj create mode 100644 examples/example02/client/sdk/src/example02/core.cljs create mode 100644 examples/example02/client/sdk/src/example02/hlc/core.cljs create mode 100644 examples/example02/client/sdk/src/example02/hlc/user.cljs create mode 100644 examples/example02/client/sdk/src/example02/main.cljs create mode 100644 examples/example02/client/sdk/src/example02/rpc.cljs create mode 100644 examples/example02/client/sdk/src/example02/util.cljs create mode 100644 examples/invoker/chaincode.yaml create mode 100755 examples/invoker/src/chaincode/chaincode.go create mode 100644 examples/invoker/src/interfaces/appinit.cci create mode 100644 examples/invoker/src/interfaces/org.hyperledger.chaincode.example02.cci create mode 100644 examples/parameterless/chaincode.yaml create mode 100755 examples/parameterless/src/chaincode/main.go create mode 100644 examples/parameterless/src/interfaces/appinit.cci create mode 100644 examples/parameterless/src/interfaces/org.hyperledger.chaincode.example.parameterless.cci create mode 100644 examples/sample_syscc/chaincode.yaml create mode 100644 examples/sample_syscc/interfaces/appinit.cci create mode 100644 examples/sample_syscc/interfaces/org.hyperledger.chaincode.system.sample.cci create mode 100755 examples/sample_syscc/sample_syscc.go create mode 100644 images/readme-drawings.graffle create mode 100644 images/typical-workflow.png create mode 100755 lein create mode 100644 project.clj create mode 100755 resources/generators/golang.stg create mode 100644 resources/generators/proto.stg create mode 100644 resources/metadata/org.hyperledger.chaintool.meta.cci create mode 100644 resources/parsers/interface/grammar.bnf create mode 100644 resources/parsers/interface/skip.bnf create mode 100644 resources/parsers/proto/grammar.bnf create mode 100644 resources/parsers/proto/skip.bnf create mode 100644 resources/proto/car.proto create mode 100644 src/chaintool/ast.clj create mode 100644 src/chaintool/build/core.clj create mode 100644 src/chaintool/build/interface.clj create mode 100644 src/chaintool/car/abi/Car.java create mode 100644 src/chaintool/car/ls.clj create mode 100644 src/chaintool/car/read.clj create mode 100644 src/chaintool/car/types.clj create mode 100644 src/chaintool/car/unpack.clj create mode 100644 src/chaintool/car/write.clj create mode 100644 src/chaintool/codecs.clj create mode 100644 src/chaintool/config/parser.clj create mode 100644 src/chaintool/config/util.clj create mode 100644 src/chaintool/core.clj create mode 100644 src/chaintool/inspect/core.clj create mode 100644 src/chaintool/platforms/api.clj create mode 100644 src/chaintool/platforms/core.clj create mode 100644 src/chaintool/platforms/golang/core.clj create mode 100644 src/chaintool/platforms/golang/system.clj create mode 100644 src/chaintool/platforms/golang/userspace.clj create mode 100644 src/chaintool/protobuf/generate.clj create mode 100644 src/chaintool/subcommands/build.clj create mode 100644 src/chaintool/subcommands/buildcar.clj create mode 100644 src/chaintool/subcommands/clean.clj create mode 100644 src/chaintool/subcommands/inspect.clj create mode 100644 src/chaintool/subcommands/ls.clj create mode 100644 src/chaintool/subcommands/package.clj create mode 100644 src/chaintool/subcommands/proto.clj create mode 100644 src/chaintool/subcommands/unpack.clj create mode 100644 src/chaintool/util.clj create mode 100644 src/org/hyperledger/chaintool/meta/OrgHyperledgerChaintoolMeta.java create mode 100644 test/chaintool/build/test_interface.clj create mode 100644 test/chaintool/platforms/golang/test_core.clj create mode 100644 test/chaintool/platforms/golang/test_system.clj create mode 100644 test/chaintool/protobuf/test_generate.clj diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ca493ec --- /dev/null +++ b/.gitignore @@ -0,0 +1,12 @@ +/target +/lib +/classes +/checkouts +pom.xml +*.jar +*.class +.lein-deps-sum +.lein-failures +.lein-plugins +.idea +*.iml diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..0791305 --- /dev/null +++ b/.travis.yml @@ -0,0 +1 @@ +language: clojure diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..387a3b2 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,24 @@ +# Change Log +All notable changes to this project will be documented in this file. This change log follows the conventions of [keepachangelog.com](http://keepachangelog.com/). + +## [Unreleased][unreleased] +### Changed +- Add a new arity to `make-widget-async` to provide a different widget shape. + +## [0.1.1] - 2016-01-20 +### Changed +- Documentation on how to make the widgets. + +### Removed +- `make-widget-sync` - we're all async, all the time. + +### Fixed +- Fixed widget maker to keep working when daylight savings switches over. + +## 0.1.0 - 2016-01-20 +### Added +- Files from the new template. +- Widget maker public API - `make-widget-sync`. + +[unreleased]: https://github.com/your-name/obcc/compare/0.1.1...HEAD +[0.1.1]: https://github.com/your-name/obcc/compare/0.1.0...0.1.1 diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..d645695 --- /dev/null +++ b/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/MAINTAINERS.txt b/MAINTAINERS.txt new file mode 100644 index 0000000..9e64cbe --- /dev/null +++ b/MAINTAINERS.txt @@ -0,0 +1,3 @@ +Gregory Haskins +Eric Baur +Muralidharan Srinivasan diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..cc38e3f --- /dev/null +++ b/Makefile @@ -0,0 +1,37 @@ +NAME=chaintool +LEIN = $(shell which lein || echo ./lein) +BINDIR ?= /usr/local/bin +OUTPUT=target/$(NAME) +META=org.hyperledger.chaintool.meta + +SRCS += $(shell find src -type f) +SRCS += $(shell find resources -type f) + +PROTOS += $(shell find resources/proto -name "*.proto") +PROTOS += target/$(META).proto + +all: $(OUTPUT) + +$(OUTPUT): $(SRCS) Makefile project.clj + @$(LEIN) bin + +$(PREFIX)$(BINDIR): + mkdir -p $@ + +# Bootstrap! We use chaintool to build a .proto for chaintool. +# If HEAD will not build, an older release of chaintool may be +# used to generate this file by hand +target/$(META).proto: resources/metadata/$(META).cci $(OUTPUT) + $(OUTPUT) proto -o $@ $< + +proto: $(PROTOS) + protoc --java_out=./src $(PROTOS) + +install: $(OUTPUT) $(PREFIX)$(BINDIR) + cp $(OUTPUT) $(PREFIX)$(BINDIR) + +clean: + @echo "Cleaning up.." + @$(LEIN) clean + -@rm -rf target + -@rm -f *~ diff --git a/README.md b/README.md new file mode 100644 index 0000000..2a45a63 --- /dev/null +++ b/README.md @@ -0,0 +1,427 @@ +[![Build Status](https://travis-ci.org/hyperledger/fabric-chaintool.svg?branch=master)](https://travis-ci.org/hyperledger/fabric-chaintool) + +# chaintool - Hyperledger Chaincode Compiler + +## Introduction + +_chaintool_ is a toolchain to assist in various phases of [Hyperledger Fabric](https://github.com/hyperledger/fabric) chaincode development, such as compilation, test, packaging, and deployment. A chaincode app developer may express the interface in a highlevel protobuf structure and _chaintool_ will generate (1) the chaincode with appropriate method stubs and (2) package it for the user so it can be directly deployed. + +### Why? + +Current chaincode development is rather unstructured outside of the coarse-level callbacks for invoke or query passing a {function-name, argument-array} string-based tuple. The result of this is that input translation/validation is a manual, explicit, and likely fragile process in each chaincode function. Additionally, any potential chaincode consumer needs to study the chaincode source in order to ascertain its API. + +Consider that some chaincode applications may employ confidentiality to hide their source, while others may wish to employ alternative programming languages. This aside, chaincode deployment lifecycles may be long enough to require us to be aware of managing potential API incompatibilities between the chaincode and its clients. It starts to become clear that there are some advantages to allowing chaincode to express its API interfaces in a way that is independent from the underlying implementation/language and in a manner that supports some form of schema management. + +_chaintool_ helps in this regard by allowing applications to declare/consume one or more language neutral interface-definitions and package it with the project. It helps the developer by generating stub code in their chosen programming language that helps them implement and/or consume the interfaces declared. This means that external parties may introspect a given instance for its interface(s) in a language neutral manner without requiring access to and/or an ability to decipher the underlying code. It also means that we can use [protobufs](https://developers.google.com/protocol-buffers/) to help with various API features such as managing forwards/backwards compatibility, endian neutrality, basic type validation, etc in a largely transparent manner. + +_chaintool_ provides some other benefits too, such as consistent language-neutral packaging and chaincode hashing, which help to simplify both the hyperledger fabric implementation and developer burden. + +## Getting Started + +### Prerequisites + +- A Java JRE/JDK v1.7 (or higher) + +### Installation + + $ make install + +### Usage + +``` +$ chaintool -h +chaintool version: v0.7 + +Usage: chaintool [general-options] action [action-options] + +General Options: + -v, --version Print the version and exit + -h, --help + +Actions: + build -> Build the chaincode project + buildcar -> Build the chaincode project from a CAR file + clean -> Clean the chaincode project + package -> Package the chaincode into a CAR file for deployment + unpack -> Unpackage a CAR file + ls -> List the contents of a CAR file + proto -> Compiles a CCI file to a .proto + inspect -> Retrieves metadata from a running instance + +(run "chaintool -h" for action specific help) +``` +### Working with _chaintool_ + +The idiomatic way to use _chaintool_ is to treat it similar to other build tools such as Make, Maven, or Leiningen. That is, by default it expects to be executed from within your [project root](#project-structure). Subcommands such as _build_, _clean_, and _package_ fall into this category. You can run it outside of a project root by using the "-p" switch to these commands to inform _chaintool_ where your project root is when it is not the current directory. + +Other commands such as _buildcar_, _unpack_, and _ls_ are designed to operate against a Chaincode Archive (CAR) from a previous _package_ operation. These commands expect a path to a CAR file. + +In all cases, you may obtain subcommand specific help by invoking "chaintool _$subcommand_ -h". For example: + +``` +$ chaintool package -h +chaintool version: v0.7 + +Description: chaintool package - Package the chaincode into a CAR file for deployment + +Usage: chaintool package [options] + +Command Options: + -o, --output NAME path to the output destination + -c, --compress NAME gzip compression algorithm to use + -p, --path PATH ./ path to chaincode project + -h, --help +``` + +### Typical Workflow + +![typical-worflow](images/typical-workflow.png) + +### Subcommand Details + +#### chaintool build + +Builds your chaincode project into a executable. When used locally, _chaintool build_ allows a developer to verify that their project compiles without errors or warnings before deployment. Validating peers also each use _chaintool build_ to prepare a chaincode archive for execution on the actual blockchain. Developers achieve fidelity in chaincode development workflows because they have access to the same build environment that will eventually be used when their application is deployed. + +Various artifacts are emitted to ./build, depending on the platform. For [org.hyperledger.chaincode.golang](./documentation/platforms/golang/README.md): + +- ./build/src: stub, protobufs, etc +- ./build/deps: direct and transitive dependencies of your chaincode, as retrieved by "go get". NOTE: this option is likely to default to disabled in the future, since it is not a good idea for a validating peer to be pulling dependencies down. Rather, there should be some fixed number of dependencies that are implicitly included with the platform. For now, we pull things in dynamically. +- ./build/bin: the default location for the binary generated (override with -o) + +#### chaintool clean + +Cleans a chaincode project. This typically translates to removing the ./build directory, but platforms are free to define this as they see fit and may perform additional or alternative operations. + +#### chaintool package + +Packages the sourcecode, interfaces, chaincode.yaml, and other project data into a .car file suitable for deployment. Note that any artifacts generated by commands such as _build_ and _buildcar_ are _not_ included but rather will be rebuilt locally by each validating peer in the network. + +#### chaintool ls + +Displays the contents of an existing .car file. +``` +$ chaintool ls ./build/org.hyperledger.chaincode.example02-0.1-SNAPSHOT.car +|------+------------------------------------------+--------------------------------------------------------| +| Size | SHA1 | Path | +|------+------------------------------------------+--------------------------------------------------------| +| 438 | d28b22c7c30506af926dcb5bc8b946ac35ddac7f | chaincode.yaml | +| 3856 | 542d088197e1a46bc21326e67e5d84d2d2807283 | src/chaincode/chaincode_example02.go | +| 143 | 7305f65e18e4aab860b201d40916bb7adf97544f | src/interfaces/appinit.cci | +| 375 | 9492a1e96f380a97bba1f16f085fc70140154c65 | src/interfaces/org.hyperledger.chaincode.example02.cci | +|------+------------------------------------------+--------------------------------------------------------| +Platform: org.hyperledger.chaincode.golang version 1 +Digital Signature: none +Raw Data Size: 4812 bytes +Archive Size: 2371 bytes +Compression Alg: gzip +Chaincode SHA3: f7026e0675b22a9d78b9f7f0cb97c93165bdefedc86de97f00e76b506c707b4ddbdfe97ad702ad600eae518891b9f0f1c8cb9a8b29b83908c2f6d46a6bcf4ecd +``` + +#### chaintool unpack + +Unpacks a .car archive into the filesystem as a chaincode project. + +#### chaintool buildcar + +Combines _unpack_ with _build_ by utilizing a temporary directory. This allows a project to be built from a .car file without explicitly unpacking it first, as a convenience. + +#### chaintool proto + +Compiles a .cci file into a .proto file, suitable for developing clients using standard protobuf-based tooling. + +#### chaintool inspect + +Retrieves [metadata](#metadata) from a running instance, optionally saving the interface definitions to a local directory. + +``` +$ chaintool inspect -n mycc +Connecting to http://localhost:3000/chaincode +|---------------------+--------------------------------------------| +| Fact | Value | +|---------------------+--------------------------------------------| +| Application Name | org.hyperledger.chaincode.example02 | +| Application Version | 0.1-SNAPSHOT | +| Platform | org.hyperledger.chaincode.golang version 1 | +| Chaintool Version | 0.7 | +|---------------------+--------------------------------------------| +Exported Interfaces: + - appinit + - org.hyperledger.chaincode.example02 + +``` + +# Chaincode Application Development + +## Project Structure + +Like many modern build tools, _chaintool_ is opinionated. It expects a specific structure to your project as follows: + +- [chaincode.yaml](./examples/example02/app/chaincode.yaml) in the top-level directory of your project (discussed below) +- a chaincode entry-point in ./src/chaincode ([example](./examples/example02/app/src/chaincode/chaincode_example02.go)) +- interface files in ./src/interfaces ([example](./examples/example02/app/src/interfaces/org.hyperledger.chaincode.example02.cci)) + - every project must define an appinit interface ./src/interfaces/appinit.cci ([example](./examples/example02/app/src/interfaces/appinit.cci)) + +### chaincode.yaml + +_chaincode.yaml_ is the central configuration file for a given chaintool-managed chaincode project. An example looks like this: + +``` +# ---------------------------------- +# chaincode example02 +# ---------------------------------- +# +# Copyright (C) 2016 - Hyperledger +# All rights reserved +# + +Schema: 1 +Name: org.hyperledger.chaincode.example02 +Version: 0.1-SNAPSHOT + +Platform: + Name: org.hyperledger.chaincode.golang + Version: 1 + +Provides: [self] # 'self' is a keyword that means there should be $name.cci (e.g. org.hyperledger.chaincode.example02.cci) +``` + +All chaincode.yaml should minimally contain: + +- schema +- project name/version +- platform +- interface declarations (provides/consumes) + +#### Schema +This helps to relay compatibility with the structures used in the chaincode.yaml itself. At the time of writing, it should be "1". + +#### Project name/version + +This is something that should uniquely identify your chaincode project for human/UX consumption. It is generally advised that a DNS name of some kind be incorporated to promote global uniqueness. Note that the Hyperledger subsystem in general does not interpret these names in any meaningful way other than for display purposes. + +#### Platform + +It is here that a chaincode may declare the compatibility/conformity to a specific platform. The idea is to promote extensibility (e.g. other platforms may be added in the future) and also compatility (e.g. platform X, version Y may mean something very specifically about the type of chaincode language supported, the ABI for any peripheral libraries, etc). It is analogous to the notion that java 1.7 is a different ABI than java 1.8, etc. At the time of writing, the only supported platform is org.hyperledger.chaincode.golang version 1. More platforms may be added in the future. + +##### Adding platforms + +The only core requirement is that both _chaintool_ and the chosen Hyperledger network are in agreement to support said platform. The details of implementing this are "coming soon". + +#### Interface Declarations + +Interfaces (as included in ./src/interfaces) may be in one or two categories: Provided or Consumed. _Provided_ means that the chaincode implements the interface and supports having clients or other chaincode invoke methods as declared. Likewise, _consumed_ indicates that the chaincode expects to perform inter-chaincode invoke/query operations to a disparate chaincode instance that provides the interface. It is perfectly fine (though perhaps uncommon) for a chaincode to both provide and consume a given interface (such as for proxy contracts which may accept operations in a polymorphic manner before passing operations on to a concrete instance). + +Both Provides and Consumes are expressed as an array of 1 or more entries. For example: + +``` +Provides: [org.hyperledger.chaincode.example02, org.hyperledger.chaincode.example03] +Consumes: [org.hyperledger.chaincode.example02] +``` + +If there aren't any interfaces in a particular category, the entry may be omitted. Note that a chaincode that doesn't provide any interfaces doesn't sound particularly useful, however. Therefore, it is expected that every project will include at least a Provides clause. + +##### "self" + +The keyword _self_ may be used as shorthand for an interface that shares the same name as the project (for instance, the org.hyperledger.chaincode.example02 project surfacing the org.hyperledger.chaincode.example02.cci interface), as a convenience. It is idiomatic for a project to name its primary interfaces after itself, and therefore this shortcut is expected to be commonly used. Example: + +``` +Provides: [self] +``` + +### Chaincode + +The opinionated portion of chaincode path solely applies to the entry-point for your application. Other paths for non-entry point code are generally fine if you are using a language that supports namespaces, etc. For instance, the org.hyperledger.chaincode.golang platform assumes a $GOPATH of ./src and tries to build "chaincode" (via $GOPATH/src/chaincode). However, if your chaincode uses go imports such as: + +```golang +import ( + "foo" + "bar/baz" +) +``` + +placed in ./src/foo and ./src/bar/baz respectively, they will be discovered perfectly fine. + +### Interfaces + +An interface is a file ending in .cci (Chaincode Interface) that defines a language neutral definition for various RPC-like functions that a given chaincode instance supports. An chaincode instance may in fact support many different interfaces at one time. This is convenient for creating a type of polymorphism within a network of chaincode instances. + +Each .cci file is meant to represent an interface contract for compatibility. Items declared within a .cci file have provisions (similar to protobuf indices) for mutating structures over time that do not break forwards or backwards compatibility. Changes to a given interface should only be done in a manner which exploits this compatibility mechanism. If for some reason it is mandated that compatibility _must_ be broken, the name of the interface should be changed. + +#### Interface names + +The name of the .cci file has direct meaning to the ABI: the name of the file will be translated into ABI tokens on the wire. This was intentionally chosen so that the filesystem itself (under ./src/interfaces) takes a role in ensuring that only one interface of a particular type is in use within a project at any given time. Likewise, if a project wishes to import and consume an interface from a different project, it is imperative that the filename be retained across both projects or the endpoints will be inadvertently namespace-isolated from one another. To put it another way, do not rename .cci files on import! + +Perhaps even more importantly, interface ABI needs to be globally managed. Therefore it is advised to name .cci files in a way that is globally unique. A UUID would suffice, at the expense of being somewhat difficult to humans to deal with. Therefore, it is advised to name interfaces using DNS names as in the examples provided here. + +#### Definition + +Each interface definition loosely adheres to a protobuf-ish syntax. This was intentional, as the .cci file is actually translated into an intermediate .proto file before being handed to protoc to do the real work. The reason we did not just use protobuf syntax directly was because it was felt there were a few areas of the protobuf grammar that were suboptimal w.r.t. chaincode definition. Consider an example .cci: + +``` +message PaymentParams { + string partySrc = 1; + string partyDst = 2; + int32 amount = 3; +} + +message Entity { + string id = 1; +} + +message BalanceResult { + int32 balance = 1; +} + +transactions { + void MakePayment(PaymentParams) = 1; + void DeleteAccount(Entity) = 2; +} + +queries { + BalanceResult CheckBalance(Entity) = 1; +} +``` + +The _message_ definitions are almost 1:1 with protobuf grammar. The largest divergence is w.r.t. the _transactions_ and _queries_ sections. These two are similar to one another as well as to the notion of service/rpc in protobuf grammar. The reason we diverged is for a few different reasons: + +- Chaincode has a strong delineation between and invoke and a query, and it was important for the parser to be able to understand the breakdown so that the proper code could be emitted +- It was felt that the lack of "field indices" in the protobuf service/rpc grammar was a large shortcoming in ABI compatibility. Therefore, the grammar used here retains the notion of indices even for function calls. + +The main purpose of the grammar is to define RPC functions. For reasons of ABI stability, it was decided that all RPCs will have the following properties: +- Be indexed (e.g. ABI depends on index stability, not function name) +- Accept only 0 or 1 _message_ as input and return only 0 (via _void_) or 1 message as output +- We rely on the message definitions for further ABI stability. + +#### "Appinit" interface + +Every project has an implicit interface: appinit.cci. This interface is intended to define the "init" or constructor function for a given chaincode. It is also generally assumed to be not something that needs to be shared with other projects in the same manner that application-level interfaces might, thus we are not concerned about "appinit.cci" name conflicting in the way we care about other interfaces. + +The interface expected to define a message "Init" with no RPCs. This message will be assumed to be the argument to the chaincode constructor. + +# Interacting With Chaintool Managed Applications + +## Protocol + +_chaintool_ tunnels its protobuf-based protocol into the standard chaincode protocol already defined. + +### Input Protocol + +The standard protocol consists of a single "function" string, and an array of string "args". This protobuf schema for the standard chaincode protocol is: +``` +message ChaincodeInput { + + string function = 1; + repeated string args = 2; + +} +``` +Chaintool deterministically maps transactions/queries declared within a CCI to an [encoded function name](#function-encoding), and expects the corresponding input parameter to be a base64 encoded protobuf message as the first and only arg string. + +Example: +``` +{"function":"org.hyperledger.chaincode.example02/query/1","args":["CgNmb28="]}} +``` + +#### Function Encoding + +Function naming follows the convention *interface-name/method-type/method-index*. For instance, invoking *MakePayment* from our [example](./examples/example02/app/src/interfaces/org.hyperledger.chaincode.example02.cci) would be *org.hyperledger.chaintool.example02/txn/1*. Because its transaction #1 in the org.hyperledger.chaintool.example02 interface. + +##### Method Types + +There are two types of methods: transactions and queries. We therefore have two values in the function name that correspond to the underlying method type: + +- "txn" - transactions +- "query" - queries + +### Output Protocol + +Standard chaincode protocol allows chaincode applications to return a string to a caller. Chaintool managed applications will encode this string with a base64 encoded protobuf structure (when applicable). + +### Protobuf "hints" + +The .proto file generated from *chaintool* (such as *chaintool proto*) contains hints to help developers understand the protocol. For instance, see the comments at the bottom of this .proto generated from example02: + +``` +// +// Generated by chaintool. DO NOT EDIT!! +// + +syntax = "proto3"; + +package org.hyperledger.chaincode.example02; + +message BalanceResult { + int32 balance = 1; +} + +message Entity { + string id = 1; +} + +message PaymentParams { + string partySrc = 1; + string partyDst = 2; + int32 amount = 3; +} + +// +// Available RPC functions exported by this interface +// +// void MakePayment(PaymentParams) -> org.hyperledger.chaincode.example02/txn/1 +// void DeleteAccount(Entity) -> org.hyperledger.chaincode.example02/txn/2 +// BalanceResult CheckBalance(Entity) -> org.hyperledger.chaincode.example02/query/1 +``` +## Metadata + +Every chaincode application built with chaintool includes metadata which may be queried with _chaintool inspect_. This metadata contains various details about a running application, such as enumerating the interfaces surfaced by the endpoint. The caller may optionally request to download the CCI schemas for these interfaces to facilitate application-specific client interaction. + +### Details + +Chaintool emits a shadow interface _org.hyperledger.chaintool.meta_ that supports meta queries in every application built with chaintool. This interface has the following CCI at the time of writing: +``` +message InterfaceDescriptor { + string name = 1; + bytes data = 2; +} + +message Interfaces { + repeated InterfaceDescriptor descriptors = 1; +} + +message GetInterfacesParams { + bool IncludeContent = 1; +} + +message GetInterfaceParams { + string name = 1; +} + +message GetFactsParams { +} + +message Facts { + message Fact { + string name = 1; + string value = 2; + } + + repeated Fact facts = 1; +} + +queries { + Interfaces GetInterfaces(GetInterfacesParams) = 1; + InterfaceDescriptor GetInterface(GetInterfaceParams) = 2; + Facts GetFacts(GetFactsParams) = 3; +} +``` +This means that clients may optionally interact with this CCI using the same protocol discussed above to learn further details about the running application. This includes obtaining the CCI specifications of the application which may be consumed in other projects. Alternatively, users may simply use the _chaintool inspect_ command to obtain the desired information. + +# Examples +Explore our [examples](./examples) or visit the [documentation for example02](./examples/example02/README.md) + +# Platforms + +The following is a list of the currently supported chaincode platforms +* [org.hyperledger.chaincode.golang](./documentation/platforms/golang/README.md) - The canonical platform for chaincode development, expressed as a chaintool managed superset. +* org.hyperledger.chaincode.system - A special variant of [org.hyperledger.chaincode.golang](./documentation/platforms/golang/README.md) designed for system-chaincode development as an extension of the hyperledger fabric. This platform is implicitly golang based and notably not compiled as system chaincode is compiled as part of the fabric build. diff --git a/documentation/platforms/golang/README.md b/documentation/platforms/golang/README.md new file mode 100644 index 0000000..d3236ec --- /dev/null +++ b/documentation/platforms/golang/README.md @@ -0,0 +1,115 @@ +# Hyperledger GO Language Chaincode Platform +The Hyperledger framework provides support for chaincode written in the Go language. The Hyperledger validating peer provide a complete execution environment for Go programs. This README describes the Go platform-specific interface code that chaintool generates from the language neutral interface definitions and specifies the conventions applications written in Go must adhere to in order to execute in the Hyperledger Go environment. Basic familarity with the structure and function of chaintool as described in the top level README file is assumed. +## Environment +Any invocation of 'chaintool build*' will automatically synthesize the correct value for the $GOPATH environment variable based on the current value of the variable and the path of your chaincode project tree. Your chaincode project tree need _not_ be located within the directory hierarchy defined by the current value of $GOPATH. The 'chaintool build' command will ensures that the build correctly includes Go code from following paths (where $PROJECT_ROOT is the root directory of your application chaincode.) +* $PROJECT_ROOT/build/deps + - Direct and transitive dependencies of your application as retrieved by _go get_. (Please note: it is highly unlikely that production Hyperledger peers will use _go get_ to resolve dependencies. This use of _go get_ is an artifact of ongoing Hyperledger development; reducing development friction as the platform dependencies are refined. Operationally all dependencies will be explicit. +* $PROJECT_ROOT/build + - Root directory of the default location for compiler generated artifacts. +* $PROJECT_ROOT + - Root directory for your application source files. Typically all application code is stored under $PROJECT_ROOT/src/chaincode. +* current $GOPATH as set in the environment. + +## Chaincode Integration +### Entry-point +Your chaincode entry-point _func main()_ should be placed in a file stored in a directory under $PROJECT_ROOT/src/chaincode/. The function should be part of a package called "chaincode". Other packages may be placed in files stored in other locations in the $PROJECT_ROOT directory hierarchy and may be imported by your entry-point module using standard golang mechanisms. (The typical Go convention is to place source files in directories rooted at $PROJECT_ROOT/src). Any Go files that are stored under $PROJECT_ROOT/src will be included in the final CAR package. +### Imports +In addition to any packages imported as part of your application logic your chaincode will import packages from four other locations. +* hyperledger/ccs - "chaincode support" + - generated "stub" code produced by the chaintool compiler + +* hyperledger/cci/... - "chaincode interface" + - Go code which implements the interfaces defined in the application's .cci files including the required appinit.cci. The functions are placed in a package the name of which is generated from the name of the .cci file. The path to these files is likewise generated from the name of the .cci file. For example code generated from a file named "com.foo.bar.cci" is placed in the package "bar" under the path $PROJECT_ROOT/src/hyperledger/cci/com/foo/bar + +* github.com/golang/protobuf/proto - google protocol buffer support + - Go implementation of Google Protocol Buffers. Protocol Buffers are used by the chaintool generated code to encode messages used by chaincode. + +* github.com/hyperledger/fabric/core/chaincode/shim - generic Hyperledger chaincode support + - Common Go language support for required chaincode operations. + +Here's the import section required for the 'example02' sample chaincode. This application includes "org.hyperledger.chaincode.example02.cci" and "project.cci" located in $PROJECT_ROOT/src/interfaces/. +``` +import ( + "hyperledger/ccs" + "hyperledger/cci/appinit" + "hyperledger/cci/org/hyperledger/chaincode/example02" + + "github.com/golang/protobuf/proto" + "github.com/hyperledger/fabric/core/chaincode/shim" +) +``` +### Hooks and Registration +Each chaincode application must call ccs.Start() to register itself as chaincode with the peer. The ccs.Start() function takes a map of interface names to interface implementations expressed as pointers compatible with the CCInterface specification. This interface is generated by the compiler and placed within the interface specific stub (e.g. $PROJECT_ROOT/build/src/hyperledger/cci/appinit/server-stub.go) . It is the application programmer's responsibility to provide an implementation for each interface declared as provided in the chaincode.yaml, plus the implicit appinit.cci. + +It is idiomatic to create one implementation structure (e.g. "ChaincodeExample", as shown below) to handle all interfaces. However, for special circumstances such as function-name collisions between interfaces, the caller may wish to dispatch certain interfaces to different handlers. +``` +type ChaincodeExample struct { +} + +... + +func main() { + self := &ChaincodeExample{} + + // Our one instance implements both Transactions and Queries functions for all interfaces + interfaces := ccs.Interfaces { + "org.hyperledger.chaincode.example02": self, + "appinit": self, + } + + err := ccs.Start(interfaces) + if err != nil { + fmt.Printf("Error starting example chaincode: %s", err) + } +} +``` + +### Callbacks +For each interface declared in the _provided_ section of the application configuration the application programmer must provide implementations for all the functions specified in the respective _transactions_ or _queries_ declarations. There is generally a 1:1 mapping between the CCI declaration and the required function signature in your code. For instance, the following CCI declaration: +``` +queries { + BalanceResult CheckBalance(Entity) = 1; +} +``` +requires a function signature that looks like: +``` +func (t *ChaincodeExample) CheckBalance(stub *shim.ChaincodeStub, param *example02.Entity) (*example02.BalanceResult, error) {} +``` +Every callback requires a shim.ChaincodeStub pointer as its first parameter, followed by an input parameter and return parameter as declared in the interface definition. Functions that return _void_ simply return a single _error_ rather than _(type, error)_. +## Generated Code File Structure +### Overview +All generated code is placed in directories rooted at $PROJECT_ROOT/build which, as mentioned earlier, is implicitly included in the $GOPATH. Interfaces are emitted to $PROJECT_ROOT/build/src/hyperledger/cci/..., and general chaincode support stubs are emitted to $PROJECT_ROOT/build/src/hyperledger/ccs. +``` +build/src/ +└── hyperledger + ├── cci + │   ├── appinit + │   │   ├── interface.pb.go + │   │   ├── interface.proto + │   │   └── server-stub.go + │   └── org + │   └── hyperledger + │   ├── chaincode + │   │   └── example02 + │   │   ├── interface.pb.go + │   │   ├── interface.proto + │   │   └── server-stub.go + │   └── chaintool + │   └── meta + │   ├── interface.pb.go + │   ├── interface.proto + │   └── server-stub.go + └── ccs + ├── api + │   └── api.go + ├── entrypoint.go + └── metadata.go +``` +### Interfaces +The chaintool compiler generates up to four artifact types per declared interface: +* interface.proto - The google protobuf definition derived from the corresponding .cci definition. +* interface.pb.go - The compiled protobuf definition, as emitted by _protoc --go_out_. +* server-stub.go - The server-side stub for a provided interface. +* client-stub.go - The client-side stub for a consumed interface. + +### Stubs diff --git a/examples/example02/README.md b/examples/example02/README.md new file mode 100644 index 0000000..931beab --- /dev/null +++ b/examples/example02/README.md @@ -0,0 +1,191 @@ +# Example02 +## Introduction +This directory contains an implementation of the chaincode application called "example02" as found in the hyperledger fabric distribution. The application has been ported to chaintool to demonstrate the features, capabilities, and techniques for working with chaintool based development. +## Directory Layout +``` +├── README.md +├── app +│   ├── app.iml +│   ├── chaincode.yaml +│   └── src +│   ├── chaincode +│   │   └── chaincode_example02.go +│   └── interfaces +│   ├── appinit.cci +│   └── org.hyperledger.chaincode.example02.cci +└── client + ├── rest + │   ├── cljs + │   │   ├── Makefile + │   │   ├── appinit.proto + │   │   ├── org.hyperledger.chaincode.example02.proto + │   │   ├── project.clj + │   │   └── src + │   │   └── example02 + │   │   ├── core.cljs + │   │   ├── main.cljs + │   │   └── rpc.cljs + │   └── nodejs + │   ├── appinit.proto + │   ├── index.js + │   ├── org.hyperledger.chaincode.example02.proto + │   └── package.json + └── sdk + ├── Makefile + ├── appinit.proto + ├── org.hyperledger.chaincode.example02.proto + ├── project.clj + └── src + └── example02 + ├── core.cljs + ├── hlc + │   ├── core.cljs + │   └── user.cljs + ├── main.cljs + ├── rpc.cljs + └── util.cljs +``` +* app - contains a org.hyperledger.chaincode.golang platform based chaincode application. + * This is the code deployed to the blockchain +* client - client applications for interacting with the chaincode application + * rest - REST api based clients + * nodejs - A simple demonstration of using nodejs+REST. + * cljs - A complete client for example02 over REST written in ClojureScript + * sdk - SDK based client, written in ClojureScript + +## Deploying and interacting with the example02 +### Step 1 - Fabric environment +You will need a functioning peer that has chaintool v0.7 or higher available in the $PATH. You may check the version of chaintool you have with 'chaintool -h'. Once confirmed, start the peer with _peer node start_ as you normally would. It is advised to keep the configuration as simple as possible (1 VP, no security, noops consensus) + +### Step 2 - Package the chaincode application +Run 'chaintool package' from the app folder, noting the CAR output path +``` +$ cd app +$ chaintool package +Writing CAR to: /Users/ghaskins/sandbox/git/chaintool/examples/example02/app/build/org.hyperledger.chaincode.example02-0.1-SNAPSHOT.car +Using path ./ ["src" "chaincode.yaml"] +|------+------------------------------------------+--------------------------------------------------------| +| Size | SHA1 | Path | +|------+------------------------------------------+--------------------------------------------------------| +| 438 | d28b22c7c30506af926dcb5bc8b946ac35ddac7f | chaincode.yaml | +| 3856 | 542d088197e1a46bc21326e67e5d84d2d2807283 | src/chaincode/chaincode_example02.go | +| 143 | 7305f65e18e4aab860b201d40916bb7adf97544f | src/interfaces/appinit.cci | +| 375 | 9492a1e96f380a97bba1f16f085fc70140154c65 | src/interfaces/org.hyperledger.chaincode.example02.cci | +|------+------------------------------------------+--------------------------------------------------------| +Platform: org.hyperledger.chaincode.golang version 1 +Digital Signature: none +Raw Data Size: 4812 bytes +Archive Size: 2371 bytes +Compression Alg: gzip +Chaincode SHA3: f7026e0675b22a9d78b9f7f0cb97c93165bdefedc86de97f00e76b506c707b4ddbdfe97ad702ad600eae518891b9f0f1c8cb9a8b29b83908c2f6d46a6bcf4ecd +``` +#### Note: +The _chaintool package_ command is designed to package for deployment, not development. If you started your node with _peer node start --peer-chaincodedev_, run _chaintool build_ instead. This is analogous to building non-chaintool chaincode using _go build_. The output will be placed in the _app/build/bin/_ directory. +### Step 3 - Compile the client +Run 'make' from the client/rest/cljs folder +``` +$ make +lein npm install +example02@0.1.0-SNAPSHOT /Users/ghaskins/sandbox/git/chaintool/examples/example02/client/rest/cljs +├─┬ protobufjs@5.0.1 +│ ├─┬ ascli@1.0.0 +│ │ ├── colour@0.7.1 +│ │ └── optjs@3.2.2 +│ ├─┬ bytebuffer@5.0.1 +│ │ └── long@3.1.0 +│ ├─┬ glob@5.0.15 +│ │ ├─┬ inflight@1.0.4 +│ │ │ └── wrappy@1.0.1 +│ │ ├── inherits@2.0.1 +│ │ ├─┬ minimatch@3.0.0 +│ │ │ └─┬ brace-expansion@1.1.4 +│ │ │ ├── balanced-match@0.4.1 +│ │ │ └── concat-map@0.0.1 +│ │ ├── once@1.3.3 +│ │ └── path-is-absolute@1.0.0 +│ └─┬ yargs@3.32.0 +│ ├── camelcase@2.1.1 +│ ├─┬ cliui@3.2.0 +│ │ ├─┬ strip-ansi@3.0.1 +│ │ │ └── ansi-regex@2.0.0 +│ │ └── wrap-ansi@2.0.0 +│ ├── decamelize@1.2.0 +│ ├─┬ os-locale@1.4.0 +│ │ └─┬ lcid@1.0.0 +│ │ └── invert-kv@1.0.0 +│ ├─┬ string-width@1.0.1 +│ │ ├─┬ code-point-at@1.0.0 +│ │ │ └── number-is-nan@1.0.0 +│ │ └── is-fullwidth-code-point@1.0.0 +│ ├── window-size@0.1.4 +│ └── y18n@3.2.1 +└─┬ source-map-support@0.4.0 + └─┬ source-map@0.1.32 + └── amdefine@1.0.0 + +lein cljsbuild once +Compiling ClojureScript... +Compiling "out/example02.js" from ["src"]... +Successfully compiled "out/example02.js" in 3.075 seconds. +Compilation complete: use "node out/example02.js --help" for execution instructions +``` +This will generate a nodejs application in _out/example02.js_. You may run it with --help to get a command summary. +``` +$ node out/example02.js --help +Usage: example02 [options] + +Options Summary: + --host HOST localhost Host name + --port PORT 3000 Port number + -p, --path PATH Path/URL to the chaincode (deploy only, mutually exclsive with -n) + -n, --name NAME Name of the chaincode (mutually exclusive with -p) + -c, --command CMD check-balance One of [deploy make-payment delete-account check-balance] + -a, --args ARGS JSON formatted arguments to submit + -h, --help +``` +### Step 4 - Deploy the CAR +We can deploy the CAR we packaged in Step 2 using the "-c deploy" feature of the client. We specify the path the CAR with -p and args with -a. + +``` +$ node ./out/example02.js -c deploy -p /fqp/to/app.car --port 5000 --args '{"partyA":{"entity":"a", "value":100}, "partyB":{"entity":"b", "value":100}}' +``` +This will return something that looks like: +``` +Response: {:result {:status OK, :message a9114852d11579bb6000abd7b2d3b25403aa7ff4f365a80ab2382a1616a066cddacefd3422c62337ba1b5eda2b2f4f04f5a2e3dbd411159db188d6946e83a95b}} +``` +Note the hash that is returned in the {:result {:message}}, as this is your chaincode instance ID or "name". + +#### Note: +-p must be a fully qualified path since it is passed to the VP as is. Future versions of the tool/peer may allow inline data, TBD. + +-a is expected to be a JSON structure that matches the protobuf definition for the request in particular. In this case, we are deploying so we are interested in the _Init_ message within the appinit.proto. + +#####If you started your node with _peer node start --peer-chaincodedev_, deploy your chaintool build like you would with non-chaintool chaincode. +``` +$ CORE_CHAINCODE_ID_NAME=org.hyperledger.chaincode.example02 CORE_PEER_ADDRESS=0.0.0.0:30303 ./app/build/bin/org.hyperledger.chaincode.example02-0.1-SNAPSHOT +$ node ./out/example02.js -c deploy -n org.hyperledger.chaincode.example02 --port 5000 --args '{"partyA":{"entity":"a", "value":100}, "partyB":{"entity":"b", "value":100}}' +``` + +#### Where did the .proto files come from? +_chaintool proto_ was used to generate .proto files from the .cci files defined in ./app/src/interfaces +### Step 5 - Query our current balances +We can use "-n $hash -c check-balance" to check the balance of one of our accounts +``` +$ node ./out/example02.js -n a9114....946e83a95b --port 5000 -c check-balance --args '{"id":"a"}' +``` +This should return with +``` +Success: Balance = 100 +``` +We can repeat the process with id "b". Likewise, we can confirm that the system should return an error for any ids besides "a" or "b". +#### Note: +If you started your node with _peer node start --peer-chaincodedev_, change the hash (_a9114....946e83a95b_) to the name you chose in Step 4. +``` +$ node ./out/example02.js -n org.hyperledger.chaincode.example02 --port 5000 -c check-balance --args '{"id":"a"}' +``` +### Step 6 - Make a Payment +Now lets transfer 10 tokens from a to b. +``` +$ node ./out/example02.js -n a9114....946e83a95b --port 5000 -c make-payment --args '{ "partySrc": "a", "partyDst": "b", "amount": 10}' +``` +You should be able to repeat the query in Step 5 and confirm that a now holds 90 tokens while b holds 110. diff --git a/examples/example02/app/chaincode.yaml b/examples/example02/app/chaincode.yaml new file mode 100644 index 0000000..9a8ba57 --- /dev/null +++ b/examples/example02/app/chaincode.yaml @@ -0,0 +1,18 @@ + +# ---------------------------------- +# chaincode example02 +# ---------------------------------- +# +# Copyright (C) 2016 - Hyperledger +# All rights reserved +# + +Schema: 1 +Name: org.hyperledger.chaincode.example02 +Version: 0.1-SNAPSHOT + +Platform: + Name: org.hyperledger.chaincode.golang + Version: 1 + +Provides: [self] # 'self' is a keyword that means there should be $name.cci (e.g. org.hyperledger.chaincode.example02.cci) diff --git a/examples/example02/app/src/chaincode/chaincode_example02.go b/examples/example02/app/src/chaincode/chaincode_example02.go new file mode 100755 index 0000000..41964c2 --- /dev/null +++ b/examples/example02/app/src/chaincode/chaincode_example02.go @@ -0,0 +1,152 @@ +/* +Licensed to the Apache Software Foundation (ASF) under one +or more contributor license agreements. See the NOTICE file +distributed with this work for additional information +regarding copyright ownership. The ASF licenses this file +to you under the Apache License, Version 2.0 (the +"License"); you may not use this file except in compliance +with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, +software distributed under the License is distributed on an +"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +KIND, either express or implied. See the License for the +specific language governing permissions and limitations +under the License. +*/ + +package main + +import ( + "errors" + "fmt" + "strconv" + + "hyperledger/cci/appinit" + "hyperledger/cci/org/hyperledger/chaincode/example02" + "hyperledger/ccs" + + "github.com/golang/protobuf/proto" + "github.com/hyperledger/fabric/core/chaincode/shim" +) + +type ChaincodeExample struct { +} + +// Called to initialize the chaincode +func (t *ChaincodeExample) Init(stub *shim.ChaincodeStub, param *appinit.Init) error { + + var err error + + fmt.Printf("Aval = %d, Bval = %d\n", param.PartyA.Value, param.PartyB.Value) + + // Write the state to the ledger + err = t.PutState(stub, param.PartyA) + if err != nil { + return err + } + + err = t.PutState(stub, param.PartyB) + if err != nil { + return err + } + + return nil +} + +// Transaction makes payment of X units from A to B +func (t *ChaincodeExample) MakePayment(stub *shim.ChaincodeStub, param *example02.PaymentParams) error { + + var err error + + // Get the state from the ledger + src, err := t.GetState(stub, param.PartySrc) + if err != nil { + return err + } + + dst, err := t.GetState(stub, param.PartyDst) + if err != nil { + return err + } + + // Perform the execution + X := int(param.Amount) + src = src - X + dst = dst + X + fmt.Printf("Aval = %d, Bval = %d\n", src, dst) + + // Write the state back to the ledger + err = stub.PutState(param.PartySrc, []byte(strconv.Itoa(src))) + if err != nil { + return err + } + + err = stub.PutState(param.PartyDst, []byte(strconv.Itoa(dst))) + if err != nil { + return err + } + + return nil +} + +// Deletes an entity from state +func (t *ChaincodeExample) DeleteAccount(stub *shim.ChaincodeStub, param *example02.Entity) error { + + // Delete the key from the state in ledger + err := stub.DelState(param.Id) + if err != nil { + return errors.New("Failed to delete state") + } + + return nil +} + +// Query callback representing the query of a chaincode +func (t *ChaincodeExample) CheckBalance(stub *shim.ChaincodeStub, param *example02.Entity) (*example02.BalanceResult, error) { + var err error + + // Get the state from the ledger + val, err := t.GetState(stub, param.Id) + if err != nil { + return nil, err + } + + fmt.Printf("Query Response: %d\n", val) + return &example02.BalanceResult{Balance: *proto.Int32(int32(val))}, nil +} + +func main() { + self := &ChaincodeExample{} + interfaces := ccs.Interfaces { + "org.hyperledger.chaincode.example02": self, + "appinit": self, + } + + err := ccs.Start(interfaces) // Our one instance implements both Transactions and Queries interfaces + if err != nil { + fmt.Printf("Error starting example chaincode: %s", err) + } +} + +//------------------------------------------------- +// Helpers +//------------------------------------------------- +func (t *ChaincodeExample) PutState(stub *shim.ChaincodeStub, party *appinit.Party) error { + return stub.PutState(party.Entity, []byte(strconv.Itoa(int(party.Value)))) +} + +func (t *ChaincodeExample) GetState(stub *shim.ChaincodeStub, entity string) (int, error) { + bytes, err := stub.GetState(entity) + if err != nil { + return 0, errors.New("Failed to get state") + } + if bytes == nil { + return 0, errors.New("Entity not found") + } + + val, _ := strconv.Atoi(string(bytes)) + return val, nil +} diff --git a/examples/example02/app/src/interfaces/appinit.cci b/examples/example02/app/src/interfaces/appinit.cci new file mode 100644 index 0000000..2d9e665 --- /dev/null +++ b/examples/example02/app/src/interfaces/appinit.cci @@ -0,0 +1,10 @@ + +message Party { + string entity = 1; + int32 value = 2; +} + +message Init { + Party partyA = 1; + Party partyB = 2; +} diff --git a/examples/example02/app/src/interfaces/org.hyperledger.chaincode.example02.cci b/examples/example02/app/src/interfaces/org.hyperledger.chaincode.example02.cci new file mode 100644 index 0000000..ad02021 --- /dev/null +++ b/examples/example02/app/src/interfaces/org.hyperledger.chaincode.example02.cci @@ -0,0 +1,23 @@ + +message PaymentParams { + string partySrc = 1; + string partyDst = 2; + int32 amount = 3; +} + +message Entity { + string id = 1; +} + +message BalanceResult { + int32 balance = 1; +} + +transactions { + void MakePayment(PaymentParams) = 1; + void DeleteAccount(Entity) = 2; +} + +queries { + BalanceResult CheckBalance(Entity) = 1; +} diff --git a/examples/example02/client/rest/cljs/Makefile b/examples/example02/client/rest/cljs/Makefile new file mode 100644 index 0000000..7d75171 --- /dev/null +++ b/examples/example02/client/rest/cljs/Makefile @@ -0,0 +1,17 @@ +SRCS = $(shell find src -type f) +LEIN = $(shell which lein || echo ../../../../../lein) + +all: client + +client: ./out/example02.js + +node_modules: project.clj + $(LEIN) npm install + +./out/example02.js: $(SRCS) node_modules Makefile + $(LEIN) cljsbuild once + @echo "Compilation complete: use \"node $@ --help\" for execution instructions" + +clean: + -@rm -rf ./out ||: + -@rm -rf node_modules ||: diff --git a/examples/example02/client/rest/cljs/appinit.proto b/examples/example02/client/rest/cljs/appinit.proto new file mode 100644 index 0000000..d92e13d --- /dev/null +++ b/examples/example02/client/rest/cljs/appinit.proto @@ -0,0 +1,19 @@ +// +// Generated by chaintool. DO NOT EDIT!! +// + +syntax = "proto3"; + +package appinit; + +message Init { + Party partyA = 1; + Party partyB = 2; +} + +message Party { + string entity = 1; + int32 value = 2; +} + + diff --git a/examples/example02/client/rest/cljs/org.hyperledger.chaincode.example02.proto b/examples/example02/client/rest/cljs/org.hyperledger.chaincode.example02.proto new file mode 100644 index 0000000..6a51ace --- /dev/null +++ b/examples/example02/client/rest/cljs/org.hyperledger.chaincode.example02.proto @@ -0,0 +1,29 @@ +// +// Generated by chaintool. DO NOT EDIT!! +// + +syntax = "proto3"; + +package org.hyperledger.chaincode.example02; + +message BalanceResult { + int32 balance = 1; +} + +message Entity { + string id = 1; +} + +message PaymentParams { + string partySrc = 1; + string partyDst = 2; + int32 amount = 3; +} + + +// +// Available RPC functions exported by this interface +// +// void MakePayment(PaymentParams) -> org.hyperledger.chaincode.example02/txn/1 +// void DeleteAccount(Entity) -> org.hyperledger.chaincode.example02/txn/2 +// BalanceResult CheckBalance(Entity) -> org.hyperledger.chaincode.example02/query/1 diff --git a/examples/example02/client/rest/cljs/project.clj b/examples/example02/client/rest/cljs/project.clj new file mode 100644 index 0000000..612798a --- /dev/null +++ b/examples/example02/client/rest/cljs/project.clj @@ -0,0 +1,24 @@ +(defproject example02 "0.1.0-SNAPSHOT" + :min-lein-version "2.0.0" + :description "Clojurescript client for chaintool version of example02" + :url "http://example.com/FIXME" + :dependencies [[org.clojure/clojure "1.8.0"] + [org.clojure/clojurescript "1.8.34"] + [org.clojure/tools.cli "0.3.3"]] + :jvm-opts ^:replace ["-Xmx1g" "-server"] + :plugins [[lein-npm "0.6.1"] + [lein-cljsbuild "1.1.3"]] + :npm {:dependencies [[source-map-support "0.4.0"] + [protobufjs "5.0.1"]]} + :source-paths ["src" "target/classes"] + :clean-targets ["out" "release"] + :target-path "target" + :cljsbuild {:builds [{:id "example02" + :source-paths ["src"] + :compiler {:output-to "out/example02.js" + :output-dir "out" + :source-map true + :optimizations :none + :target :nodejs + :main "example02.main" + :pretty-print true}}]}) diff --git a/examples/example02/client/rest/cljs/src/example02/core.cljs b/examples/example02/client/rest/cljs/src/example02/core.cljs new file mode 100644 index 0000000..6f37d99 --- /dev/null +++ b/examples/example02/client/rest/cljs/src/example02/core.cljs @@ -0,0 +1,43 @@ +(ns example02.core + (:require [cljs.nodejs :as nodejs] + [example02.rpc :as rpc])) + +(def pb (nodejs/require "protobufjs")) +(def builder (.newBuilder pb)) + +(defn- loadproto [name] + (do + (.loadProtoFile pb (str "./" name ".proto") builder) + (.build builder name))) + +(def init (loadproto "appinit")) +(def app (loadproto "org.hyperledger.chaincode.example02")) + +(defn deploy [{:keys [args] :as options}] + (rpc/deploy (assoc options + :func "init" + :args (init.Init. args) + :cb (fn [resp] (println "Response:" resp))))) + +(defn make-payment [{:keys [args] :as options}] + (rpc/invoke (assoc options + :func "org.hyperledger.chaincode.example02/txn/1" + :args (app.PaymentParams. args) + :cb (fn [resp] (println "Response:" resp))))) + +(defn delete-account [{:keys [args] :as options}] + (rpc/invoke (assoc options + :func "org.hyperledger.chaincode.example02/txn/2" + :args (app.Entity. args) + :cb (fn [resp] (println "Response:" resp))))) + +(defn check-balance [{:keys [args] :as options}] + (rpc/query (assoc options + :func "org.hyperledger.chaincode.example02/query/1" + :args (app.Entity. args) + :cb (fn [resp] + (if (= (->> resp :result :status) "OK") + (let [result (->> resp :result :message app.BalanceResult.decode64)] + (println "Success: Balance =" (.-balance result))) + ;; else + (println "Failure:" resp)))))) diff --git a/examples/example02/client/rest/cljs/src/example02/main.cljs b/examples/example02/client/rest/cljs/src/example02/main.cljs new file mode 100644 index 0000000..b0211c2 --- /dev/null +++ b/examples/example02/client/rest/cljs/src/example02/main.cljs @@ -0,0 +1,98 @@ +(ns example02.main + (:require [clojure.string :as string] + [cljs.nodejs :as nodejs] + [cljs.tools.cli :refer [parse-opts]] + [example02.core :as core])) + + +(nodejs/enable-util-print!) + +(def _commands + [["deploy" + {:fn core/deploy + :default-args #js {:partyA #js { + :entity "foo" + :value 100 + } + :partyB #js { + :entity "bar" + :value 100 + }}}] + ["make-payment" + {:fn core/make-payment + :default-args #js {:partySrc "foo" + :partyDst "bar" + :amount 10}}] + ["delete-account" + {:fn core/delete-account + :default-args #js {:id "foo"}}] + ["check-balance" + {:fn core/check-balance + :default-args #js {:id "foo"}}]]) + +(def commands (into {} _commands)) +(defn print-commands [] (->> commands keys vec print-str)) + +(def options + [[nil "--host HOST" "Host name" + :default "localhost"] + [nil "--port PORT" "Port number" + :default 5000 + :parse-fn #(js/parseInt %) + :validate [#(< 0 % 65536) "Must be a number between 0 and 65536"]] + ["-p" "--path PATH" "Path/URL to the chaincode (deploy only, mutually exclsive with -n)"] + ["-n" "--name NAME" "Name of the chaincode (mutually exclusive with -p)"] + ["-c" "--command CMD" (str "One of " (print-commands)) + :default "check-balance" + :validate [#(contains? commands %) (str "Supported commands: " (print-commands))]] + ["-a" "--args ARGS" "JSON formatted arguments to submit"] + ["-h" "--help"]]) + +(defn exit [status msg & rest] + (do + (apply println msg rest) + status)) + +(defn prep-usage [msg] (->> msg flatten (string/join \newline))) + +(defn usage [options-summary] + (prep-usage ["Usage: example02 [options]" + "" + "Options Summary:" + options-summary + "" + ])) + +(defn run [{:keys [path name command args] :as options}] + (let [desc (commands command) + _args (if (nil? args) (:default-args desc) (.parse js/JSON args))] + (cond + + (and (some? path) (some? name)) + (println "ERROR: -p and -n are mutually exclusive") + + (and (nil? path) (nil? name)) + (println "ERROR: Must specify either -p or -n") + + (and (some? path) (not= command "deploy")) + (println "ERROR: -p only valid with deploy command") + + :else + (let [id (if (some? path) #js {:path path} #js {:name name})] + (println (str "Running " command "(" (.stringify js/JSON _args) ")")) + ((:fn desc) (assoc options :id id :args _args)))))) + +(defn -main [& args] + (let [{:keys [options arguments errors summary]} (parse-opts args options)] + (cond + + (:help options) + (exit 0 (usage summary)) + + (not= errors nil) + (exit -1 "Error: " (string/join errors)) + + :else + (run options)))) + +(set! *main-cli-fn* -main) diff --git a/examples/example02/client/rest/cljs/src/example02/rpc.cljs b/examples/example02/client/rest/cljs/src/example02/rpc.cljs new file mode 100644 index 0000000..d1a7cad --- /dev/null +++ b/examples/example02/client/rest/cljs/src/example02/rpc.cljs @@ -0,0 +1,45 @@ +(ns example02.rpc + (:require [cljs.nodejs :as nodejs])) + +(def http (nodejs/require "http")) + +(defn- stringify [json] + (.stringify js/JSON json)) + +(defn- response-handler [cb resp] + (.setEncoding resp "utf8") + (.on resp "data" (fn [data] + (let [resp (js->clj (.parse js/JSON data) :keywordize-keys true)] + (cb (select-keys resp [:error :result])))))) + +(defn- post [{:keys [host port path method id func args cb]}] + (let [meta #js {:host host + :port port + :path path + :method "POST" + :headers #js {:Content-Type "application/json"}} + data (stringify + #js {:jsonrpc "2.0" + :method method + :params #js {:type 3 + :chaincodeID id + :ctorMsg #js {:function func + :args #js [(.toBase64 args)]}} + :id "1"}) + req (.request http meta (partial response-handler cb))] + + (println "HTTP POST:" (str "http://" host ":" port) "-" data) + (.write req data) + (.end req))) + +(defn- chaincode-post [args] + (post (assoc args :path "/chaincode"))) + +(defn deploy [args] + (chaincode-post (assoc args :method "deploy"))) + +(defn invoke [args] + (chaincode-post (assoc args :method "invoke"))) + +(defn query [args] + (chaincode-post (assoc args :method "query"))) diff --git a/examples/example02/client/rest/nodejs/appinit.proto b/examples/example02/client/rest/nodejs/appinit.proto new file mode 100644 index 0000000..d92e13d --- /dev/null +++ b/examples/example02/client/rest/nodejs/appinit.proto @@ -0,0 +1,19 @@ +// +// Generated by chaintool. DO NOT EDIT!! +// + +syntax = "proto3"; + +package appinit; + +message Init { + Party partyA = 1; + Party partyB = 2; +} + +message Party { + string entity = 1; + int32 value = 2; +} + + diff --git a/examples/example02/client/rest/nodejs/index.js b/examples/example02/client/rest/nodejs/index.js new file mode 100644 index 0000000..069ae30 --- /dev/null +++ b/examples/example02/client/rest/nodejs/index.js @@ -0,0 +1,101 @@ +var http = require('http'); +var pb = require("protobufjs"); + +var builder = pb.newBuilder({ convertFieldsToCamelCase: true }); + +pb.loadProtoFile("./appinit.proto", builder); +var init = builder.build("appinit"); + +pb.loadProtoFile("./org.hyperledger.chaincode.example02.proto", builder); +var app = builder.build("org.hyperledger.chaincode.example02"); + +function Deploy(id, params) { + + invoke('deploy', id, 'init', new init.Init(params), function(res) { + res.setEncoding('utf8'); + res.on('data', function (chunk) { + var resp = JSON.parse(chunk); + console.log('Response: ' + chunk); + }); + + }); +} + +function CheckBalance(id, params) { + + invoke('query', id, 'org.hyperledger.chaincode.example02/query/1', new app.Entity(params), function(res) { + res.setEncoding('utf8'); + res.on('data', function (chunk) { + var resp = JSON.parse(chunk); + if (resp.result.status == "OK") { + var result = app.BalanceResult.decode64(resp.result.message); + console.log("BalanceResult: " + result.balance); + } else { + console.log('ERROR: ' + chunk); + } + }); + + }); +} + +function invoke(method, id, func, args, cb) { + var post_data = JSON.stringify({ + 'jsonrpc': '2.0', + 'method': method, + 'params': { + 'type': 3, + 'chaincodeID': id, + 'ctorMsg': { + 'function': func, + 'args':[args.toBase64()] + } + }, + "id": 1 + }); + console.log(post_data); + post(post_data, '/chaincode', cb); +} + +function post(pdata, path, cb) { + var post_options = { + host: 'localhost', + port: '5000', + path: path, + method: 'POST', + headers: { + 'Content-Type': 'application/json' + } + }; + + var post_req = http.request(post_options, cb); + + // post the data + post_req.write(pdata); + post_req.end(); + +} + +Deploy( + { + 'name': 'mycc' + }, + { + 'partyA': { + 'entity': 'foo', + 'value': 100 + }, + 'partyB': { + 'entity': 'bar', + 'value': 100 + } + } +); + +CheckBalance( + { + 'name': 'mycc' + }, + { + "id": "foo" + } +); diff --git a/examples/example02/client/rest/nodejs/org.hyperledger.chaincode.example02.proto b/examples/example02/client/rest/nodejs/org.hyperledger.chaincode.example02.proto new file mode 100644 index 0000000..6a51ace --- /dev/null +++ b/examples/example02/client/rest/nodejs/org.hyperledger.chaincode.example02.proto @@ -0,0 +1,29 @@ +// +// Generated by chaintool. DO NOT EDIT!! +// + +syntax = "proto3"; + +package org.hyperledger.chaincode.example02; + +message BalanceResult { + int32 balance = 1; +} + +message Entity { + string id = 1; +} + +message PaymentParams { + string partySrc = 1; + string partyDst = 2; + int32 amount = 3; +} + + +// +// Available RPC functions exported by this interface +// +// void MakePayment(PaymentParams) -> org.hyperledger.chaincode.example02/txn/1 +// void DeleteAccount(Entity) -> org.hyperledger.chaincode.example02/txn/2 +// BalanceResult CheckBalance(Entity) -> org.hyperledger.chaincode.example02/query/1 diff --git a/examples/example02/client/rest/nodejs/package.json b/examples/example02/client/rest/nodejs/package.json new file mode 100644 index 0000000..4f2cb22 --- /dev/null +++ b/examples/example02/client/rest/nodejs/package.json @@ -0,0 +1,14 @@ +{ + "name": "protobuf", + "version": "1.0.0", + "description": "", + "main": "index.js", + "dependencies": { + "protobufjs":"5.0.1" + }, + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "author": "", + "license": "ISC" +} diff --git a/examples/example02/client/sdk/Makefile b/examples/example02/client/sdk/Makefile new file mode 100644 index 0000000..ce1a819 --- /dev/null +++ b/examples/example02/client/sdk/Makefile @@ -0,0 +1,18 @@ +SRCS = $(shell find src -type f) +LEIN = $(shell which lein || echo ../../../../lein) + +all: client + +client: ./out/example02.js + +node_modules: project.clj + $(LEIN) npm install + +./out/example02.js: $(SRCS) node_modules Makefile + $(LEIN) cljsbuild once + @echo "Compilation complete: use \"node $@ --help\" for execution instructions" + +clean: + -@rm -rf ./out ||: + -@rm -rf ./target ||: + -@rm -rf node_modules ||: diff --git a/examples/example02/client/sdk/appinit.proto b/examples/example02/client/sdk/appinit.proto new file mode 100644 index 0000000..d92e13d --- /dev/null +++ b/examples/example02/client/sdk/appinit.proto @@ -0,0 +1,19 @@ +// +// Generated by chaintool. DO NOT EDIT!! +// + +syntax = "proto3"; + +package appinit; + +message Init { + Party partyA = 1; + Party partyB = 2; +} + +message Party { + string entity = 1; + int32 value = 2; +} + + diff --git a/examples/example02/client/sdk/org.hyperledger.chaincode.example02.proto b/examples/example02/client/sdk/org.hyperledger.chaincode.example02.proto new file mode 100644 index 0000000..6a51ace --- /dev/null +++ b/examples/example02/client/sdk/org.hyperledger.chaincode.example02.proto @@ -0,0 +1,29 @@ +// +// Generated by chaintool. DO NOT EDIT!! +// + +syntax = "proto3"; + +package org.hyperledger.chaincode.example02; + +message BalanceResult { + int32 balance = 1; +} + +message Entity { + string id = 1; +} + +message PaymentParams { + string partySrc = 1; + string partyDst = 2; + int32 amount = 3; +} + + +// +// Available RPC functions exported by this interface +// +// void MakePayment(PaymentParams) -> org.hyperledger.chaincode.example02/txn/1 +// void DeleteAccount(Entity) -> org.hyperledger.chaincode.example02/txn/2 +// BalanceResult CheckBalance(Entity) -> org.hyperledger.chaincode.example02/query/1 diff --git a/examples/example02/client/sdk/project.clj b/examples/example02/client/sdk/project.clj new file mode 100644 index 0000000..de862bf --- /dev/null +++ b/examples/example02/client/sdk/project.clj @@ -0,0 +1,27 @@ +(defproject example02 "0.1.0-SNAPSHOT" + :description "FIXME: write this!" + :url "http://example.com/FIXME" + :dependencies [[org.clojure/clojure "1.8.0"] + [org.clojure/clojurescript "1.8.34"] + [org.clojure/tools.cli "0.3.3"] + [funcool/promesa "1.3.1"]] + :jvm-opts ^:replace ["-Xmx1g" "-server"] + :plugins [[lein-npm "0.6.1"] + [lein-cljsbuild "1.1.3"]] + :npm {:dependencies [[source-map-support "0.4.0"] + [protobufjs "5.0.1"] + [hlc "0.0.9"] + [mkdirp "0.5.1"] + [homedir "0.6.0"]]} + :source-paths ["src" "target/classes"] + :clean-targets ["out" "release"] + :target-path "target" + :cljsbuild {:builds [{:id "example02" + :source-paths ["src"] + :compiler {:output-to "out/example02.js" + :output-dir "out" + :source-map true + :optimizations :none + :target :nodejs + :main "example02.main" + :pretty-print true}}]}) diff --git a/examples/example02/client/sdk/src/example02/core.cljs b/examples/example02/client/sdk/src/example02/core.cljs new file mode 100644 index 0000000..e6531c9 --- /dev/null +++ b/examples/example02/client/sdk/src/example02/core.cljs @@ -0,0 +1,69 @@ +(ns example02.core + (:require [cljs.nodejs :as nodejs] + [example02.rpc :as rpc] + [example02.hlc.core :as hlc] + [example02.hlc.user :as hlc.user] + [example02.util :as util] + [promesa.core :as p :include-macros true])) + +(def pb (nodejs/require "protobufjs")) +(def homedir (nodejs/require "homedir")) + +(def builder (.newBuilder pb)) + +(defn- loadproto [name] + (do + (.loadProtoFile pb (str "./" name ".proto") builder) + (.build builder name))) + +(def init (loadproto "appinit")) +(def app (loadproto "org.hyperledger.chaincode.example02")) + +(defn connect [{:keys [path peer membersrvc username password]}] + (let [path (str (homedir) "/.hyperledger/client/kvstore")] + + ;; ensure our path is created + (util/mkdirp path) + + ;; configure the chain environment and log in + (p/alet [chain (p/await (hlc/new-chain "mychain")) + kvstore (p/await (hlc/new-file-kv-store path)) + + ;; configure the chain environment + _ (p/await (p/all [(hlc/set-kv-store chain kvstore) + (hlc/set-membersrvc-url chain membersrvc) + (hlc/add-peer chain peer)])) + + ;; login using the provided username/password + member (p/await (hlc/get-member chain username)) + _ (p/await (hlc.user/enroll member password))] + + {:chain chain :user member}))) + +(defn deploy [{:keys [args] :as options}] + (-> options + (assoc :func "init" + :args (init.Init. args)) + rpc/deploy + (p/then #(println "Success!")))) + +(defn make-payment [{:keys [args] :as options}] + (-> options + (assoc :func "org.hyperledger.chaincode.example02/txn/1" + :args (app.PaymentParams. args)) + rpc/invoke + (p/then #(println "Success!")))) + +(defn delete-account [{:keys [args] :as options}] + (-> options + (assoc :func "org.hyperledger.chaincode.example02/txn/2" + :args (app.Entity. args)) + rpc/invoke + (p/then #(println "Success!")))) + +(defn check-balance [{:keys [args] :as options}] + (-> options + (assoc :func "org.hyperledger.chaincode.example02/query/1" + :args (app.Entity. args)) + rpc/query + (p/then #(println "Success: Balance =" (->> % app.BalanceResult.decode64 .-balance))))) diff --git a/examples/example02/client/sdk/src/example02/hlc/core.cljs b/examples/example02/client/sdk/src/example02/hlc/core.cljs new file mode 100644 index 0000000..c19ec66 --- /dev/null +++ b/examples/example02/client/sdk/src/example02/hlc/core.cljs @@ -0,0 +1,38 @@ +(ns example02.hlc.core + (:require [cljs.nodejs :as nodejs] + [promesa.core :as p :include-macros true])) + +(def hlc (nodejs/require "hlc")) + +(defn new-chain [name] + (p/do* (.newChain hlc name))) + +(defn new-file-kv-store [path] + (p/do* (.newFileKeyValStore hlc path))) + +(defn set-kv-store [chain store] + (p/do* (.setKeyValStore chain store))) + +(defn set-membersrvc-url [chain url] + (p/do* (.setMemberServicesUrl chain url))) + +(defn add-peer [chain url] + (p/do* (.addPeer chain url))) + +(defn get-member [chain username] + (p/promise + (fn [resolve reject] + (.getMember chain username + (fn [err member] + (if err + (reject err) + (resolve member))))))) + +(defn register-and-enroll [chain request] + (p/promise + (fn [resolve reject] + (.registerAndEnroll chain request + (fn [err user] + (if err + (reject err) + (resolve user))))))) diff --git a/examples/example02/client/sdk/src/example02/hlc/user.cljs b/examples/example02/client/sdk/src/example02/hlc/user.cljs new file mode 100644 index 0000000..9e8afc5 --- /dev/null +++ b/examples/example02/client/sdk/src/example02/hlc/user.cljs @@ -0,0 +1,30 @@ +(ns example02.hlc.user + (:require [cljs.nodejs :as nodejs] + [promesa.core :as p :include-macros true])) + +(def hlc (nodejs/require "hlc")) + +(defn enroll [member password] + (p/promise + (fn [resolve reject] + (.enroll member password + (fn [err user] + (if err + (reject err) + (resolve :success))))))) + +(defn enrolled? [member] + (p/do* (.isEnrolled member))) + +(defn- post [func] + (p/promise + (fn [resolve reject] + (let [tx (func)] + (.on tx "complete" resolve) + (.on tx "error" reject))))) + +(defn invoke [user request] + (post #(.invoke user request))) + +(defn query [user request] + (post #(.query user request))) diff --git a/examples/example02/client/sdk/src/example02/main.cljs b/examples/example02/client/sdk/src/example02/main.cljs new file mode 100644 index 0000000..d484f2d --- /dev/null +++ b/examples/example02/client/sdk/src/example02/main.cljs @@ -0,0 +1,87 @@ +(ns example02.main + (:require [clojure.string :as string] + [cljs.nodejs :as nodejs] + [cljs.tools.cli :refer [parse-opts]] + [example02.core :as core] + [promesa.core :as p :include-macros true])) + +(nodejs/enable-util-print!) + +(def _commands + [["deploy" + {:fn core/deploy + :default-args #js {:partyA #js {:entity "foo" + :value 100} + :partyB #js {:entity "bar" + :value 100}}}] + ["make-payment" + {:fn core/make-payment + :default-args #js {:partySrc "foo" + :partyDst "bar" + :amount 10}}] + ["delete-account" + {:fn core/delete-account + :default-args #js {:id "foo"}}] + ["check-balance" + {:fn core/check-balance + :default-args #js {:id "foo"}}]]) + +(def commands (into {} _commands)) +(defn print-commands [] (->> commands keys vec print-str)) + +(def options + [[nil "--peer URL" "Peer URL" + :default "grpc://localhost:30303"] + [nil "--membersrvc URL" "Member services URL" + :default "grpc://localhost:50051"] + [nil "--username USER" "Username" + :default "test_user0"] + [nil "--password PASS" "Password" + :default "MS9qrN8hFjlE"] + ["-i" "--id ID" "ChaincodeID as a path/url/name"] + ["-c" "--command CMD" (str "One of " (print-commands)) + :default "check-balance" + :validate [#(contains? commands %) (str "Supported commands: " (print-commands))]] + ["-a" "--args ARGS" "JSON formatted arguments to submit"] + ["-h" "--help"]]) + +(defn exit [status msg & rest] + (do + (apply println msg rest) + status)) + +(defn prep-usage [msg] (->> msg flatten (string/join \newline))) + +(defn usage [options-summary] + (prep-usage ["Usage: example02 [options]" + "" + "Options Summary:" + options-summary + ""])) + +(defn -main [& args] + (let [{:keys [options arguments errors summary]} (parse-opts args options) + {:keys [id command args]} options] + (cond + + (:help options) + (exit 0 (usage summary)) + + (not= errors nil) + (exit -1 "Error: " (string/join errors)) + + (nil? id) + (exit -1 "Error: Must specify a chaincodeID") + + :else + (let [desc (commands command) + _args (if (nil? args) (:default-args desc) (.parse js/JSON args))] + + (p/alet [{:keys [chain user]} (p/await (core/connect options))] + + (println (str "Running " command "(" (.stringify js/JSON _args) ")")) + + ;; Run the subcommand funtion + ((:fn desc) (assoc options :id id :args _args :chain chain :user user))))))) + +(set! *main-cli-fn* -main) diff --git a/examples/example02/client/sdk/src/example02/rpc.cljs b/examples/example02/client/sdk/src/example02/rpc.cljs new file mode 100644 index 0000000..2559d33 --- /dev/null +++ b/examples/example02/client/sdk/src/example02/rpc.cljs @@ -0,0 +1,20 @@ +(ns example02.rpc + (:require [cljs.nodejs :as nodejs] + [example02.hlc.user :as hlc.user] + [promesa.core :as p :include-macros true])) + +(defn- post [method {:keys [user id func args] :as options}] + (let [request #js {:chaincodeID id + :fcn func + :args #js [(.toBase64 args)]}] + + (p/chain (method user request) str))) + +(defn deploy [args] + (post hlc.user/deploy args)) + +(defn invoke [args] + (post hlc.user/invoke args)) + +(defn query [args] + (post hlc.user/query args)) diff --git a/examples/example02/client/sdk/src/example02/util.cljs b/examples/example02/client/sdk/src/example02/util.cljs new file mode 100644 index 0000000..8cd257c --- /dev/null +++ b/examples/example02/client/sdk/src/example02/util.cljs @@ -0,0 +1,7 @@ +(ns example02.util + (:require [cljs.nodejs :as nodejs])) + +(def _mkdirp (nodejs/require "mkdirp")) + +(defn mkdirp [path] + (_mkdirp.sync path)) diff --git a/examples/invoker/chaincode.yaml b/examples/invoker/chaincode.yaml new file mode 100644 index 0000000..c0d2651 --- /dev/null +++ b/examples/invoker/chaincode.yaml @@ -0,0 +1,26 @@ + +# ----------------------------------------------------------------------- +# chaincode invoker +# ----------------------------------------------------------------------- +# +# Copyright (C) 2016 - Hyperledger +# All rights reserved +# +# This example demonstrates chaincode to chaincode invoke. This example +# consumes the services of our example02 chaincode +# + +Schema: 1 +Name: org.hyperledger.chaincode.example.invoker +Version: 0.1-SNAPSHOT + +Platform: + Name: org.hyperledger.chaincode.golang + Version: 1 + +Provides: [org.hyperledger.chaincode.example02] +Consumes: [org.hyperledger.chaincode.example02] + + + + diff --git a/examples/invoker/src/chaincode/chaincode.go b/examples/invoker/src/chaincode/chaincode.go new file mode 100755 index 0000000..2454fa4 --- /dev/null +++ b/examples/invoker/src/chaincode/chaincode.go @@ -0,0 +1,101 @@ +/* +Licensed to the Apache Software Foundation (ASF) under one +or more contributor license agreements. See the NOTICE file +distributed with this work for additional information +regarding copyright ownership. The ASF licenses this file +to you under the Apache License, Version 2.0 (the +"License"); you may not use this file except in compliance +with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, +software distributed under the License is distributed on an +"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +KIND, either express or implied. See the License for the +specific language governing permissions and limitations +under the License. +*/ + +package chaincode + +import ( + "fmt" + + "hyperledger/cci/appinit" + "hyperledger/cci/org/hyperledger/chaincode/example02" + "hyperledger/ccs" + + "github.com/hyperledger/fabric/core/chaincode/shim" +) + +type ChaincodeExample struct { +} + +// Called to initialize the chaincode +func (t *ChaincodeExample) Init(stub *shim.ChaincodeStub, param *appinit.Init) error { + + var err error + + // Write the state to the ledger + err = stub.PutState("ProxyAddress", []byte(param.Address)) + if err != nil { + return err + } + + return nil +} + +// Transaction makes payment of X units from A to B +func (t *ChaincodeExample) MakePayment(stub *shim.ChaincodeStub, param *example02.PaymentParams) error { + + var err error + + // Get the state from the ledger + addr, err := stub.GetState("ProxyAddress") + if err != nil { + return err + } + + return example02.MakePayment(stub, string(addr), param) +} + +// Deletes an entity from state +func (t *ChaincodeExample) DeleteAccount(stub *shim.ChaincodeStub, param *example02.Entity) error { + + var err error + + // Get the state from the ledger + addr, err := stub.GetState("ProxyAddress") + if err != nil { + return err + } + + return example02.DeleteAccount(stub, string(addr), param) +} + +// Query callback representing the query of a chaincode +func (t *ChaincodeExample) CheckBalance(stub *shim.ChaincodeStub, param *example02.Entity) (*example02.BalanceResult, error) { + + var err error + + // Get the state from the ledger + addr, err := stub.GetState("ProxyAddress") + if err != nil { + return nil, err + } + + return example02.CheckBalance(stub, string(addr), param) +} + +func main() { + self := &ChaincodeExample{} + interfaces := ccs.Interfaces { + "org.hyperledger.chaincode.example02": self, + "appinit": self, + } + err := ccs.Start(interfaces) // Our one instance implements both Transactions and Queries interfaces + if err != nil { + fmt.Printf("Error starting example chaincode: %s", err) + } +} diff --git a/examples/invoker/src/interfaces/appinit.cci b/examples/invoker/src/interfaces/appinit.cci new file mode 100644 index 0000000..8b673ea --- /dev/null +++ b/examples/invoker/src/interfaces/appinit.cci @@ -0,0 +1,4 @@ + +message Init { + string address = 1; +} diff --git a/examples/invoker/src/interfaces/org.hyperledger.chaincode.example02.cci b/examples/invoker/src/interfaces/org.hyperledger.chaincode.example02.cci new file mode 100644 index 0000000..ad02021 --- /dev/null +++ b/examples/invoker/src/interfaces/org.hyperledger.chaincode.example02.cci @@ -0,0 +1,23 @@ + +message PaymentParams { + string partySrc = 1; + string partyDst = 2; + int32 amount = 3; +} + +message Entity { + string id = 1; +} + +message BalanceResult { + int32 balance = 1; +} + +transactions { + void MakePayment(PaymentParams) = 1; + void DeleteAccount(Entity) = 2; +} + +queries { + BalanceResult CheckBalance(Entity) = 1; +} diff --git a/examples/parameterless/chaincode.yaml b/examples/parameterless/chaincode.yaml new file mode 100644 index 0000000..e6da711 --- /dev/null +++ b/examples/parameterless/chaincode.yaml @@ -0,0 +1,18 @@ +# ---------------------------------- +# chaincode example "parameterless" +# ---------------------------------- +# +# Copyright (C) 2016 - Hyperledger +# All rights reserved +# + +Schema: 1 +Name: org.hyperledger.chaincode.example.parameterless +Version: 0.1-SNAPSHOT + +Platform: + Name: org.hyperledger.chaincode.golang + Version: 1 + +Provides: [self] +Consumes: [org.hyperledger.chaincode.example.parameterless] diff --git a/examples/parameterless/src/chaincode/main.go b/examples/parameterless/src/chaincode/main.go new file mode 100755 index 0000000..f955cf8 --- /dev/null +++ b/examples/parameterless/src/chaincode/main.go @@ -0,0 +1,56 @@ +/* +Licensed to the Apache Software Foundation (ASF) under one +or more contributor license agreements. See the NOTICE file +distributed with this work for additional information +regarding copyright ownership. The ASF licenses this file +to you under the Apache License, Version 2.0 (the +"License"); you may not use this file except in compliance +with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, +software distributed under the License is distributed on an +"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +KIND, either express or implied. See the License for the +specific language governing permissions and limitations +under the License. +*/ + +package main + +import ( + "fmt" + + "hyperledger/cci/appinit" + app "hyperledger/cci/org/hyperledger/chaincode/example/parameterless" + "hyperledger/ccs" + + "github.com/hyperledger/fabric/core/chaincode/shim" +) + +type ChaincodeExample struct { +} + +// Called to initialize the chaincode +func (t *ChaincodeExample) Init(stub *shim.ChaincodeStub, param *appinit.Init) error { + + return nil +} + +func (t *ChaincodeExample) TestParameterless(stub *shim.ChaincodeStub) (*app.MyReturnType, error) { + return nil, nil +} + +func main() { + self := &ChaincodeExample{} + interfaces := ccs.Interfaces{ + "org.hyperledger.chaincode.example.parameterless": self, + "appinit": self, + } + + err := ccs.Start(interfaces) // Our one instance implements both Transactions and Queries interfaces + if err != nil { + fmt.Printf("Error starting example chaincode: %s", err) + } +} diff --git a/examples/parameterless/src/interfaces/appinit.cci b/examples/parameterless/src/interfaces/appinit.cci new file mode 100644 index 0000000..6278c85 --- /dev/null +++ b/examples/parameterless/src/interfaces/appinit.cci @@ -0,0 +1,2 @@ +message Init { +} diff --git a/examples/parameterless/src/interfaces/org.hyperledger.chaincode.example.parameterless.cci b/examples/parameterless/src/interfaces/org.hyperledger.chaincode.example.parameterless.cci new file mode 100644 index 0000000..7fa5a9c --- /dev/null +++ b/examples/parameterless/src/interfaces/org.hyperledger.chaincode.example.parameterless.cci @@ -0,0 +1,8 @@ + +message MyReturnType { + string foo = 1; +} + +queries { + MyReturnType TestParameterless() = 1; +} diff --git a/examples/sample_syscc/chaincode.yaml b/examples/sample_syscc/chaincode.yaml new file mode 100644 index 0000000..f3046b1 --- /dev/null +++ b/examples/sample_syscc/chaincode.yaml @@ -0,0 +1,29 @@ + +# ---------------------------------- +# chaincode example02 +# ---------------------------------- +# +# Copyright (C) 2016 - Hyperledger +# All rights reserved +# + +Schema: 1 +Name: org.hyperledger.chaincode.system.sample +Version: 0.1-SNAPSHOT + +Platform: + Name: org.hyperledger.chaincode.system + Version: 1 + +Provides: [self] # 'self' is a keyword that means there should be $name.cci (e.g. org.hyperledger.chaincode.system.sample.cci) + + + + + + + + + + + diff --git a/examples/sample_syscc/interfaces/appinit.cci b/examples/sample_syscc/interfaces/appinit.cci new file mode 100644 index 0000000..2d9e665 --- /dev/null +++ b/examples/sample_syscc/interfaces/appinit.cci @@ -0,0 +1,10 @@ + +message Party { + string entity = 1; + int32 value = 2; +} + +message Init { + Party partyA = 1; + Party partyB = 2; +} diff --git a/examples/sample_syscc/interfaces/org.hyperledger.chaincode.system.sample.cci b/examples/sample_syscc/interfaces/org.hyperledger.chaincode.system.sample.cci new file mode 100644 index 0000000..ad02021 --- /dev/null +++ b/examples/sample_syscc/interfaces/org.hyperledger.chaincode.system.sample.cci @@ -0,0 +1,23 @@ + +message PaymentParams { + string partySrc = 1; + string partyDst = 2; + int32 amount = 3; +} + +message Entity { + string id = 1; +} + +message BalanceResult { + int32 balance = 1; +} + +transactions { + void MakePayment(PaymentParams) = 1; + void DeleteAccount(Entity) = 2; +} + +queries { + BalanceResult CheckBalance(Entity) = 1; +} diff --git a/examples/sample_syscc/sample_syscc.go b/examples/sample_syscc/sample_syscc.go new file mode 100755 index 0000000..fd5b0d5 --- /dev/null +++ b/examples/sample_syscc/sample_syscc.go @@ -0,0 +1,104 @@ +/* +Licensed to the Apache Software Foundation (ASF) under one +or more contributor license agreements. See the NOTICE file +distributed with this work for additional information +regarding copyright ownership. The ASF licenses this file +to you under the Apache License, Version 2.0 (the +"License"); you may not use this file except in compliance +with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, +software distributed under the License is distributed on an +"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +KIND, either express or implied. See the License for the +specific language governing permissions and limitations +under the License. +*/ + +package sample_syscc + +import ( + "errors" + "github.com/hyperledger/fabric/core/chaincode/shim" +) + +// SampleSysCC example simple Chaincode implementation +type SampleSysCC struct { +} + +func (t *SampleSysCC) Init(stub *shim.ChaincodeStub, function string, args []string) ([]byte, error) { + var key, val string // Entities + + if len(args) != 2 { + return nil, errors.New("need 2 args (key and a value).") + } + + // Initialize the chaincode + key = args[0] + val = args[1] + // Write the state to the ledger + err := stub.PutState(key, []byte(val)) + if err != nil { + return nil, err + } + + return nil, nil +} + +// Transaction makes payment of X units from A to B +func (t *SampleSysCC) Invoke(stub *shim.ChaincodeStub, function string, args []string) ([]byte, error) { + var key, val string // Entities + + if len(args) != 2 { + return nil, errors.New("need 2 args (key and a value).") + } + + // Initialize the chaincode + key = args[0] + val = args[1] + + _, err := stub.GetState(key) + if err != nil { + jsonResp := "{\"Error\":\"Failed to get val for " + key + "\"}" + return nil, errors.New(jsonResp) + } + + // Write the state to the ledger + err = stub.PutState(key, []byte(val)) + if err != nil { + return nil, err + } + + return nil, nil +} + +// Query callback representing the query of a chaincode +func (t *SampleSysCC) Query(stub *shim.ChaincodeStub, function string, args []string) ([]byte, error) { + if function != "getval" { + return nil, errors.New("Invalid query function name. Expecting \"getval\"") + } + var key string // Entities + var err error + + if len(args) != 1 { + return nil, errors.New("Incorrect number of arguments. Expecting key to query") + } + + key = args[0] + + // Get the state from the ledger + valbytes, err := stub.GetState(key) + if err != nil { + jsonResp := "{\"Error\":\"Failed to get state for " + key + "\"}" + return nil, errors.New(jsonResp) + } + + if valbytes == nil { + jsonResp := "{\"Error\":\"Nil val for " + key + "\"}" + return nil, errors.New(jsonResp) + } + + return valbytes, nil +} diff --git a/images/readme-drawings.graffle b/images/readme-drawings.graffle new file mode 100644 index 0000000..ffecacf --- /dev/null +++ b/images/readme-drawings.graffle @@ -0,0 +1,965 @@ + + + + + ActiveLayerIndex + 0 + ApplicationVersion + + com.omnigroup.OmniGraffle + 139.18.0.187838 + + AutoAdjust + + BackgroundGraphic + + Bounds + {{0, 0}, {1151.9999694824219, 733}} + Class + SolidGraphic + ID + 2 + Style + + shadow + + Draws + NO + + stroke + + Draws + NO + + + + BaseZoom + 0 + CanvasOrigin + {0, 0} + ColumnAlign + 1 + ColumnSpacing + 36 + CreationDate + 2016-03-06 02:31:27 +0000 + Creator + Greg Haskins + DisplayScale + 1 0/72 in = 1.0000 in + GraphDocumentVersion + 8 + GraphicsList + + + Class + LineGraphic + Head + + ID + 31 + Info + 4 + + ID + 32 + Points + + {727.99955749511719, 142.00008831787113} + {749.99951171875, 142.00009918212891} + + Style + + stroke + + HeadArrow + FilledArrow + Legacy + + TailArrow + 0 + Width + 0.5 + + + Tail + + ID + 27 + + + + Bounds + {{749.99951171875, 124.00009918212891}, {90, 36}} + Class + ShapedGraphic + ID + 31 + Magnets + + {0, 1} + {0, -1} + {1, 0} + {-1, 0} + + Shape + RoundRect + Style + + fill + + FillType + 2 + GradientAngle + 90 + GradientColor + + b + 0.11315 + g + 0 + r + 1 + + + stroke + + Width + 0.5 + + + Text + + Text + {\rtf1\ansi\ansicpg1252\cocoartf1404\cocoasubrtf340 +\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} +{\colortbl;\red255\green255\blue255;} +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc + +\f0\fs20 \cf0 Stop} + VerticalPad + 0 + + + + Bounds + {{480.24801171459706, 130.50009918212891}, {28, 23}} + Class + ShapedGraphic + FitText + YES + Flow + Resize + FontInfo + + Color + + w + 0 + + Font + Helvetica + Size + 11 + + ID + 30 + Line + + ID + 28 + Position + 0.38245594501495361 + RotationType + 0 + + Shape + Rectangle + Style + + shadow + + Draws + NO + + stroke + + Draws + NO + Width + 0.5 + + + Text + + Text + {\rtf1\ansi\ansicpg1252\cocoartf1404\cocoasubrtf340 +\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} +{\colortbl;\red255\green255\blue255;} +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc + +\f0\fs22 \cf0 Yes} + + Wrap + NO + + + Class + LineGraphic + Head + + ID + 27 + Info + 4 + + ID + 29 + Points + + {615.99960327148438, 142.00009155273438} + {637.99955749511719, 142.00008831787113} + + Style + + stroke + + HeadArrow + FilledArrow + Legacy + + TailArrow + 0 + Width + 0.5 + + + Tail + + ID + 26 + Info + 3 + + + + Class + LineGraphic + Head + + ID + 26 + Info + 4 + + ID + 28 + Points + + {474.58368754386902, 142.00009918212891} + {525.99960327148438, 142.00009155273438} + + Style + + stroke + + HeadArrow + FilledArrow + Legacy + + TailArrow + 0 + Width + 0.5 + + + Tail + + ID + 3 + Info + 3 + + + + Bounds + {{637.99955749511719, 124.00008831787113}, {90, 36}} + Class + ShapedGraphic + ID + 27 + Magnets + + {0, 1} + {0, -1} + {1, 0} + {-1, 0} + + Shape + Rectangle + Style + + fill + + FillType + 2 + GradientAngle + 90 + GradientColor + + w + 0.666667 + + + stroke + + Width + 0.5 + + + Text + + Text + {\rtf1\ansi\ansicpg1252\cocoartf1404\cocoasubrtf340 +\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} +{\colortbl;\red255\green255\blue255;} +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc + +\f0\fs20 \cf0 fabric chaincode deploy} + VerticalPad + 0 + + + + Bounds + {{525.99960327148438, 124.00009155273438}, {90, 36}} + Class + ShapedGraphic + ID + 26 + Magnets + + {0, 1} + {0, -1} + {1, 0} + {-1, 0} + + Shape + Rectangle + Style + + fill + + FillType + 2 + GradientAngle + 90 + GradientColor + + b + 1 + g + 0.501525 + r + 0.201761 + + + stroke + + Width + 0.5 + + + Text + + Text + {\rtf1\ansi\ansicpg1252\cocoartf1404\cocoasubrtf340 +\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} +{\colortbl;\red255\green255\blue255;} +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc + +\f0\fs20 \cf0 chaintool package} + VerticalPad + 0 + + + + Class + LineGraphic + Head + + ID + 3 + + ID + 25 + Points + + {349.99996948242188, 142.00009155273438} + {384.58368754386902, 142.00009918212891} + + Style + + stroke + + HeadArrow + FilledArrow + Legacy + + TailArrow + 0 + Width + 0.5 + + + Tail + + ID + 20 + Info + 3 + + + + Class + LineGraphic + Head + + ID + 20 + + ID + 24 + Points + + {238, 142.00009155273438} + {259.99996948242188, 142.00009155273438} + + Style + + stroke + + HeadArrow + FilledArrow + Legacy + + TailArrow + 0 + Width + 0.5 + + + Tail + + ID + 19 + + + + Class + LineGraphic + Head + + ID + 19 + + ID + 23 + Points + + {126.0000305175781, 142.00009155273438} + {148, 142.00009155273438} + + Style + + stroke + + HeadArrow + FilledArrow + Legacy + + TailArrow + 0 + Width + 0.5 + + + Tail + + ID + 1 + + + + Bounds + {{417.08368754386902, 89.204975247199627}, {25, 23}} + Class + ShapedGraphic + FitText + YES + Flow + Resize + FontInfo + + Color + + w + 0 + + Font + Helvetica + Size + 11 + + ID + 22 + Line + + ID + 21 + Position + 0.070895515382289886 + RotationType + 0 + + Shape + Rectangle + Style + + shadow + + Draws + NO + + stroke + + Draws + NO + Width + 0.5 + + + Text + + Text + {\rtf1\ansi\ansicpg1252\cocoartf1404\cocoasubrtf340 +\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} +{\colortbl;\red255\green255\blue255;} +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc + +\f0\fs22 \cf0 No} + + Wrap + NO + + + Class + LineGraphic + Head + + ID + 19 + Info + 2 + + ID + 21 + OrthogonalBarAutomatic + + OrthogonalBarPoint + {0, 0} + OrthogonalBarPosition + -1 + Points + + {429.58368754386902, 124.00009918212891} + {349.99996948242188, 78} + {193, 124.00009155273438} + + Style + + stroke + + HeadArrow + FilledArrow + Legacy + + LineType + 2 + TailArrow + 0 + Width + 0.5 + + + Tail + + ID + 3 + + + + Bounds + {{384.58368754386902, 124.00009918212891}, {90, 36}} + Class + ShapedGraphic + ID + 3 + Magnets + + {0, 1} + {0, -1} + {1, 0} + {-1, 0} + + Shape + Diamond + Style + + fill + + FillType + 2 + GradientAngle + 90 + GradientColor + + b + 0.200498 + g + 0.831893 + r + 0.884035 + + + stroke + + Width + 0.5 + + + Text + + Text + {\rtf1\ansi\ansicpg1252\cocoartf1404\cocoasubrtf340 +\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} +{\colortbl;\red255\green255\blue255;} +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc + +\f0\fs20 \cf0 satisfied?} + VerticalPad + 0 + + + + Bounds + {{259.99996948242188, 124.00009155273438}, {90, 36}} + Class + ShapedGraphic + ID + 20 + Magnets + + {0, 1} + {0, -1} + {1, 0} + {-1, 0} + + Shape + Rectangle + Style + + fill + + FillType + 2 + GradientAngle + 90 + GradientColor + + b + 1 + g + 0.501525 + r + 0.201761 + + + stroke + + Width + 0.5 + + + Text + + Text + {\rtf1\ansi\ansicpg1252\cocoartf1404\cocoasubrtf340 +\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} +{\colortbl;\red255\green255\blue255;} +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc + +\f0\fs20 \cf0 chaintool build} + VerticalPad + 0 + + + + Bounds + {{148, 124.00009155273438}, {90, 36}} + Class + ShapedGraphic + ID + 19 + Magnets + + {0, 1} + {0, -1} + {1, 0} + {-1, 0} + + Shape + Rectangle + Style + + fill + + FillType + 2 + GradientAngle + 90 + GradientColor + + w + 0.666667 + + + stroke + + Width + 0.5 + + + Text + + Text + {\rtf1\ansi\ansicpg1252\cocoartf1404\cocoasubrtf340 +\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} +{\colortbl;\red255\green255\blue255;} +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc + +\f0\fs20 \cf0 edit code/project} + VerticalPad + 0 + + + + Bounds + {{36.000030517578125, 124.00009155273438}, {90, 36}} + Class + ShapedGraphic + ID + 1 + Magnets + + {0, 1} + {0, -1} + {1, 0} + {-1, 0} + + Shape + RoundRect + Style + + fill + + FillType + 2 + GradientAngle + 90 + GradientColor + + b + 0.305533 + g + 0.738432 + r + 0.349093 + + + stroke + + Width + 0.5 + + + Text + + Text + {\rtf1\ansi\ansicpg1252\cocoartf1404\cocoasubrtf340 +\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} +{\colortbl;\red255\green255\blue255;} +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc + +\f0\fs20 \cf0 Start} + VerticalPad + 0 + + + + GridInfo + + GuidesLocked + NO + GuidesVisible + YES + HPages + 2 + ImageCounter + 1 + KeepToScale + + Layers + + + Lock + NO + Name + Layer 1 + Print + YES + View + YES + + + LayoutInfo + + Animate + NO + circoMinDist + 18 + circoSeparation + 0.0 + layoutEngine + dot + neatoSeparation + 0.0 + twopiSeparation + 0.0 + + LinksVisible + NO + MagnetsVisible + NO + MasterSheets + + ModificationDate + 2016-04-06 19:48:49 +0000 + Modifier + Greg Haskins + NotesVisible + NO + Orientation + 2 + OriginVisible + NO + PageBreaks + YES + PrintInfo + + NSBottomMargin + + float + 41 + + NSHorizonalPagination + + coded + BAtzdHJlYW10eXBlZIHoA4QBQISEhAhOU051bWJlcgCEhAdOU1ZhbHVlAISECE5TT2JqZWN0AIWEASqEhAFxlwCG + + NSLeftMargin + + float + 18 + + NSPaperSize + + size + {611.99998474121094, 792} + + NSPrintReverseOrientation + + int + 0 + + NSRightMargin + + float + 18 + + NSTopMargin + + float + 18 + + + PrintOnePage + + ReadOnly + NO + RowAlign + 1 + RowSpacing + 36 + SheetTitle + typical workflow + SmartAlignmentGuidesActive + YES + SmartDistanceGuidesActive + YES + UniqueID + 1 + UseEntirePage + + VPages + 1 + WindowInfo + + CurrentSheet + 0 + ExpandedCanvases + + + name + typical workflow + + + Frame + {{28, 229}, {1199, 928}} + ListView + + OutlineWidth + 142 + RightSidebar + + ShowRuler + + Sidebar + + SidebarWidth + 120 + VisibleRegion + {{0, -12}, {1064, 758}} + Zoom + 1 + ZoomValues + + + typical workflow + 1 + 1 + + + + + diff --git a/images/typical-workflow.png b/images/typical-workflow.png new file mode 100644 index 0000000000000000000000000000000000000000..eb8ff34eafb63ed46725ec0722e1d8b8cb92306e GIT binary patch literal 221517 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 z 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

b1AKnGX%Mv`HcJsZqa2IY#|Z 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 literal 0 HcmV?d00001 diff --git a/lein b/lein new file mode 100755 index 0000000..105c682 --- /dev/null +++ b/lein @@ -0,0 +1,396 @@ +#!/usr/bin/env bash + +# Ensure this file is executable via `chmod a+x lein`, then place it +# somewhere on your $PATH, like ~/bin. The rest of Leiningen will be +# installed upon first run into the ~/.lein/self-installs directory. + +export LEIN_VERSION="2.6.1" + +case $LEIN_VERSION in + *SNAPSHOT) SNAPSHOT="YES" ;; + *) SNAPSHOT="NO" ;; +esac + +if [[ "$OSTYPE" == "cygwin" ]] || [[ "$OSTYPE" == "msys" ]]; then + delimiter=";" +else + delimiter=":" +fi + +if [[ "$OSTYPE" == "cygwin" ]]; then + cygwin=true +else + cygwin=false +fi + +function command_not_found { + >&2 echo "Leiningen coundn't find $1 in your \$PATH ($PATH), which is required." + exit 1 +} + +function make_native_path { + # ensure we have native paths + if $cygwin && [[ "$1" == /* ]]; then + echo -n "$(cygpath -wp "$1")" + elif [[ "$OSTYPE" == "msys" && "$1" == /?/* ]]; then + echo -n "$(sh -c "(cd $1 2 /dev/null + download_failed_message "$LEIN_URL" "$exit_code" + exit 1 + fi +} + +function check_root { + local -i user_id + # Thank you for the complexity, Solaris + if [ `uname` = "SunOS" -a -x /usr/xpg4/bin/id ]; then + user_id=$(/usr/xpg4/bin/id -u 2>/dev/null || echo 0) + else + user_id=$(id -u 2>/dev/null || echo 0) + fi + [ $user_id -eq 0 -a "$LEIN_ROOT" = "" ] && return 0 + return 1 +} + +if check_root; then + echo "WARNING: You're currently running as root; probably by accident." + echo "Press control-C to abort or Enter to continue as root." + echo "Set LEIN_ROOT to disable this warning." + read _ +fi + +NOT_FOUND=1 +ORIGINAL_PWD="$PWD" +while [ ! -r "$PWD/project.clj" ] && [ "$PWD" != "/" ] && [ $NOT_FOUND -ne 0 ] +do + cd .. + if [ "$(dirname "$PWD")" = "/" ]; then + NOT_FOUND=0 + cd "$ORIGINAL_PWD" + fi +done + +export LEIN_HOME="${LEIN_HOME:-"$HOME/.lein"}" + +for f in "/etc/leinrc" "$LEIN_HOME/leinrc" ".leinrc"; do + if [ -e "$f" ]; then + source "$f" + fi +done + +if $cygwin; then + export LEIN_HOME=$(cygpath -w "$LEIN_HOME") +fi + +LEIN_JAR="$LEIN_HOME/self-installs/leiningen-$LEIN_VERSION-standalone.jar" + +# normalize $0 on certain BSDs +if [ "$(dirname "$0")" = "." ]; then + SCRIPT="$(which "$(basename "$0")")" + if [ -z "$SCRIPT" ]; then + SCRIPT="$0" + fi +else + SCRIPT="$0" +fi + +# resolve symlinks to the script itself portably +while [ -h "$SCRIPT" ] ; do + ls=$(ls -ld "$SCRIPT") + link=$(expr "$ls" : '.*-> \(.*\)$') + if expr "$link" : '/.*' > /dev/null; then + SCRIPT="$link" + else + SCRIPT="$(dirname "$SCRIPT"$)/$link" + fi +done + +BIN_DIR="$(dirname "$SCRIPT")" + +export LEIN_JVM_OPTS="${LEIN_JVM_OPTS-"-XX:+TieredCompilation -XX:TieredStopAtLevel=1"}" + +# This needs to be defined before we call HTTP_CLIENT below +if [ "$HTTP_CLIENT" = "" ]; then + if type -p curl >/dev/null 2>&1; then + if [ "$https_proxy" != "" ]; then + CURL_PROXY="-x $https_proxy" + fi + HTTP_CLIENT="curl $CURL_PROXY -f -L -o" + else + HTTP_CLIENT="wget -O" + fi +fi + + +# When :eval-in :classloader we need more memory +grep -E -q '^\s*:eval-in\s+:classloader\s*$' project.clj 2> /dev/null && \ + export LEIN_JVM_OPTS="$LEIN_JVM_OPTS -Xms64m -Xmx512m" + +if [ -r "$BIN_DIR/../src/leiningen/version.clj" ]; then + # Running from source checkout + LEIN_DIR="$(dirname "$BIN_DIR")" + + # Need to use lein release to bootstrap the leiningen-core library (for aether) + if [ ! -r "$LEIN_DIR/leiningen-core/.lein-bootstrap" ]; then + echo "Leiningen is missing its dependencies." + echo "Please run \"lein bootstrap\" in the leiningen-core/ directory" + echo "with a stable release of Leiningen. See CONTRIBUTING.md for details." + exit 1 + fi + + # If project.clj for lein or leiningen-core changes, we must recalculate + LAST_PROJECT_CHECKSUM=$(cat "$LEIN_DIR/.lein-project-checksum" 2> /dev/null) + PROJECT_CHECKSUM=$(sum "$LEIN_DIR/project.clj" "$LEIN_DIR/leiningen-core/project.clj") + if [ "$PROJECT_CHECKSUM" != "$LAST_PROJECT_CHECKSUM" ]; then + if [ -r "$LEIN_DIR/.lein-classpath" ]; then + rm "$LEIN_DIR/.lein-classpath" + fi + fi + + # Use bin/lein to calculate its own classpath. + if [ ! -r "$LEIN_DIR/.lein-classpath" ] && [ "$1" != "classpath" ]; then + echo "Recalculating Leiningen's classpath." + ORIG_PWD="$PWD" + cd "$LEIN_DIR" + + LEIN_NO_USER_PROFILES=1 $0 classpath .lein-classpath + sum "$LEIN_DIR/project.clj" "$LEIN_DIR/leiningen-core/project.clj" > \ + .lein-project-checksum + cd "$ORIG_PWD" + fi + + mkdir -p "$LEIN_DIR/target/classes" + export LEIN_JVM_OPTS="$LEIN_JVM_OPTS -Dclojure.compile.path=$LEIN_DIR/target/classes" + add_path CLASSPATH "$LEIN_DIR/leiningen-core/src/" "$LEIN_DIR/leiningen-core/resources/" \ + "$LEIN_DIR/test:$LEIN_DIR/target/classes" "$LEIN_DIR/src" ":$LEIN_DIR/resources" + + if [ -r "$LEIN_DIR/.lein-classpath" ]; then + add_path CLASSPATH "$(cat "$LEIN_DIR/.lein-classpath" 2> /dev/null)" + else + add_path CLASSPATH "$(cat "$LEIN_DIR/leiningen-core/.lein-bootstrap" 2> /dev/null)" + fi +else # Not running from a checkout + add_path CLASSPATH "$LEIN_JAR" + + BOOTCLASSPATH="-Xbootclasspath/a:$LEIN_JAR" + + if [ ! -r "$LEIN_JAR" -a "$1" != "self-install" ]; then + self_install + fi +fi + +if [ ! -x "$JAVA_CMD" ] && ! type -f java >/dev/null +then + >&2 echo "Leiningen coundn't find 'java' executable, which is required." + >&2 echo "Please either set JAVA_CMD or put java (>=1.6) in your \$PATH ($PATH)." + exit 1 +fi + +export LEIN_JAVA_CMD="${LEIN_JAVA_CMD:-${JAVA_CMD:-java}}" + +if [[ -z "${DRIP_INIT+x}" && "$(basename "$LEIN_JAVA_CMD")" == *drip* ]]; then + export DRIP_INIT="$(printf -- '-e\n(require (quote leiningen.repl))')" + export DRIP_INIT_CLASS="clojure.main" +fi + +# Support $JAVA_OPTS for backwards-compatibility. +export JVM_OPTS="${JVM_OPTS:-"$JAVA_OPTS"}" + +# Handle jline issue with cygwin not propagating OSTYPE through java subprocesses: https://github.com/jline/jline2/issues/62 +cygterm=false +if $cygwin; then + case "$TERM" in + rxvt* | xterm* | vt*) cygterm=true ;; + esac +fi + +if $cygterm; then + LEIN_JVM_OPTS="$LEIN_JVM_OPTS -Djline.terminal=jline.UnixTerminal" + stty -icanon min 1 -echo > /dev/null 2>&1 +fi + +# TODO: investigate http://skife.org/java/unix/2011/06/20/really_executable_jars.html +# If you're packaging this for a package manager (.deb, homebrew, etc) +# you need to remove the self-install and upgrade functionality or see lein-pkg. +if [ "$1" = "self-install" ]; then + if [ -r "$BIN_DIR/../src/leiningen/version.clj" ]; then + echo "Running self-install from a checkout is not supported." + echo "See CONTRIBUTING.md for SNAPSHOT-specific build instructions." + exit 1 + fi + echo "Manual self-install is deprecated; it will run automatically when necessary." + self_install +elif [ "$1" = "upgrade" ] || [ "$1" = "downgrade" ]; then + if [ "$LEIN_DIR" != "" ]; then + echo "The upgrade task is not meant to be run from a checkout." + exit 1 + fi + if [ $SNAPSHOT = "YES" ]; then + echo "The upgrade task is only meant for stable releases." + echo "See the \"Bootstrapping\" section of CONTRIBUTING.md." + exit 1 + fi + if [ ! -w "$SCRIPT" ]; then + echo "You do not have permission to upgrade the installation in $SCRIPT" + exit 1 + else + TARGET_VERSION="${2:-stable}" + echo "The script at $SCRIPT will be upgraded to the latest $TARGET_VERSION version." + echo -n "Do you want to continue [Y/n]? " + read RESP + case "$RESP" in + y|Y|"") + echo + echo "Upgrading..." + TARGET="/tmp/lein-$$-upgrade" + if $cygwin; then + TARGET=$(cygpath -w "$TARGET") + fi + LEIN_SCRIPT_URL="https://github.com/technomancy/leiningen/raw/$TARGET_VERSION/bin/lein" + $HTTP_CLIENT "$TARGET" "$LEIN_SCRIPT_URL" + if [ $? == 0 ]; then + cmp -s "$TARGET" "$SCRIPT" + if [ $? == 0 ]; then + echo "Leiningen is already up-to-date." + fi + mv "$TARGET" "$SCRIPT" && chmod +x "$SCRIPT" + exec "$SCRIPT" version + else + download_failed_message "$LEIN_SCRIPT_URL" + fi;; + *) + echo "Aborted." + exit 1;; + esac + fi +else + if $cygwin; then + # When running on Cygwin, use Windows-style paths for java + ORIGINAL_PWD=$(cygpath -w "$ORIGINAL_PWD") + fi + + # apply context specific CLASSPATH entries + if [ -f .lein-classpath ]; then + add_path CLASSPATH "$(cat .lein-classpath)" + fi + + if [ -n "$DEBUG" ]; then + echo "Leiningen's classpath: $CLASSPATH" + fi + + if [ -r .lein-fast-trampoline ]; then + export LEIN_FAST_TRAMPOLINE='y' + fi + + if [ "$LEIN_FAST_TRAMPOLINE" != "" ] && [ -r project.clj ]; then + INPUTS="$* $(cat project.clj) $LEIN_VERSION $(test -f "$LEIN_HOME/profiles.clj" && cat "$LEIN_HOME/profiles.clj")" + + if command -v shasum >/dev/null 2>&1; then + SUM="shasum" + elif command -v sha1sum >/dev/null 2>&1; then + SUM="sha1sum" + else + command_not_found "sha1sum or shasum" + fi + + export INPUT_CHECKSUM=$(echo "$INPUTS" | $SUM | cut -f 1 -d " ") + # Just don't change :target-path in project.clj, mkay? + TRAMPOLINE_FILE="target/trampolines/$INPUT_CHECKSUM" + else + if hash mktemp 2>/dev/null; then + # Check if mktemp is available before using it + TRAMPOLINE_FILE="$(mktemp /tmp/lein-trampoline-XXXXXXXXXXXXX)" + else + TRAMPOLINE_FILE="/tmp/lein-trampoline-$$" + fi + trap "rm -f $TRAMPOLINE_FILE" EXIT + fi + + if $cygwin; then + TRAMPOLINE_FILE=$(cygpath -w "$TRAMPOLINE_FILE") + fi + + if [ "$INPUT_CHECKSUM" != "" ] && [ -r "$TRAMPOLINE_FILE" ]; then + if [ -n "$DEBUG" ]; then + echo "Fast trampoline with $TRAMPOLINE_FILE." + fi + exec sh -c "exec $(cat "$TRAMPOLINE_FILE")" + else + export TRAMPOLINE_FILE + "$LEIN_JAVA_CMD" \ + "${BOOTCLASSPATH[@]}" \ + -Dfile.encoding=UTF-8 \ + -Dmaven.wagon.http.ssl.easy=false \ + -Dmaven.wagon.rto=10000 \ + $LEIN_JVM_OPTS \ + -Dleiningen.original.pwd="$ORIGINAL_PWD" \ + -Dleiningen.script="$SCRIPT" \ + -classpath "$CLASSPATH" \ + clojure.main -m leiningen.core.main "$@" + + EXIT_CODE=$? + + if $cygterm ; then + stty icanon echo > /dev/null 2>&1 + fi + + ## TODO: [ -r "$TRAMPOLINE_FILE" ] may be redundant? A trampoline file + ## is always generated these days. + if [ -r "$TRAMPOLINE_FILE" ] && [ "$LEIN_TRAMPOLINE_WARMUP" = "" ]; then + TRAMPOLINE="$(cat "$TRAMPOLINE_FILE")" + if [ "$INPUT_CHECKSUM" = "" ]; then + rm "$TRAMPOLINE_FILE" + fi + if [ "$TRAMPOLINE" = "" ]; then + exit $EXIT_CODE + else + exec sh -c "exec $TRAMPOLINE" + fi + else + exit $EXIT_CODE + fi + fi +fi diff --git a/project.clj b/project.clj new file mode 100644 index 0000000..ba987ab --- /dev/null +++ b/project.clj @@ -0,0 +1,36 @@ +(defproject chaintool "0.8.0" + :description "hyperledger chaincode tool" + :url "https://github.com/ghaskins/chaintool" + :license {:name "Apache License" + :url "http://www.apache.org/licenses/LICENSE-2.0.txt"} + :min-lein-version "2.0.0" + :lein-release {:deploy-via :shell :shell ["true"]} + :javac-options ["-target" "1.7" "-source" "1.7"] + :java-source-paths ["src"] + :plugins [[lein-bin "0.3.5"]] + :dependencies [[org.clojure/clojure "1.8.0"] + [org.clojure/tools.cli "0.3.5"] + [org.clojure/algo.generic "0.1.2"] + [org.clojure/data.codec "0.1.0"] + [instaparse "1.4.2"] + [clojure-tools "1.1.3"] + [org.antlr/ST4 "4.0.8"] + [me.raynes/conch "0.8.0"] + [me.raynes/fs "1.4.6"] + [org.clojars.ghaskins/protobuf "0.2"] + [commons-io/commons-io "2.5"] + [org.tukaani/xz "1.5"] + [org.apache.commons/commons-compress "1.11"] + [com.github.jponge/lzma-java "1.3"] + [pandect "0.5.4"] + [doric "0.9.0"] + [circleci/clj-yaml "0.5.5"] + [slingshot "0.12.2"] + [clj-http "3.1.0"] + [cheshire "5.6.1"]] + :main ^:skip-aot chaintool.core + :bin {:name "chaintool" + :bin-path "target" + :bootclasspath true} + :target-path "target/%s" + :profiles {:uberjar {:aot :all}}) diff --git a/resources/generators/golang.stg b/resources/generators/golang.stg new file mode 100755 index 0000000..35a465e --- /dev/null +++ b/resources/generators/golang.stg @@ -0,0 +1,455 @@ +primary(base, system, provides) ::= +<< + +/* Generated by chaintool. DO NOT EDIT */ + +package ccs + +import ( + "errors" + "regexp" + "strconv" + + "github.com/hyperledger/fabric/core/system_chaincode/api" + "github.com/hyperledger/fabric/core/chaincode/shim" + "/ccs/api" +) + +type Interfaces map[string]interface{} +type Dispatchers map[string]api.Dispatcher + +type stubHandler struct { + dispatchers Dispatchers +} + +var txnre = regexp.MustCompile("([a-zA-Z0-9.]*)/txn/([0-9]*)") +var queryre = regexp.MustCompile("([a-zA-Z0-9.]*)/query/([0-9]*)") + +// Initialization function, called only once +func (self *stubHandler) Init(stub *shim.ChaincodeStub, function string, args []string) ([]byte, error) { + + if len(args) != 1 { + return nil, errors.New("Expected exactly one argument") + } + + if function != "init" { + return nil, errors.New("Function must be \"init\"") + } + + dispatcher, ok := self.dispatchers["appinit"] + if !ok { + return nil, errors.New("Interface not found") + } + + return dispatcher.DispatchTxn(stub, 1, args[0]) +} + +// Callback representing the invocation of a chaincode + + +// Callback representing the query of a chaincode + + +func (self *stubHandler) decodeFunction(re *regexp.Regexp, function string) (api.Dispatcher, int, error) { + + spec := re.FindAllStringSubmatch(function, -1) + if spec == nil { + return nil, 0, errors.New("Could not parse function name") + } + + dispatcher, ok := self.dispatchers[spec[0][1]] + if !ok { + return nil, 0, errors.New("Interface not found") + } + + index, err := strconv.Atoi(spec[0][2]) + if err != nil { + return nil, 0, errors.New("Could not convert function index") + } + + return dispatcher, index, nil +} + +func (self *stubHandler) addDispatcher(name string, intf interface{}) error { + + dispatcher, err := api.Create(name, intf) + if err != nil { + return err + } + + self.dispatchers[name] = dispatcher + return nil +} + +func Start(interfaces Interfaces) error { + + metadata := &ChaincodeMetaData{} + handler := &stubHandler{dispatchers: make(Dispatchers)} + + // Install our metadata impl first so that we give the user a chance to subclass and override + if err := handler.addDispatcher("org.hyperledger.chaintool.meta", metadata); err != nil { + return err + } + + // Install all of the declared interfaces + for name, intf := range interfaces { + if err := handler.addDispatcher(name, intf); err != nil { + return err + } + } + + + api.RegisterSysCC("", handler) + + err := shim.Start(handler) + if err != nil { + return err + } + + + return nil +} + +>> + +api() ::= +<< + +/* Generated by chaintool. DO NOT EDIT */ + +package api + +import ( + "errors" + "github.com/hyperledger/fabric/core/chaincode/shim" +) + +type Dispatcher interface { + DispatchTxn(stub *shim.ChaincodeStub, function int, params string) ([]byte, error) + DispatchQuery(stub *shim.ChaincodeStub, function int, params string) ([]byte, error) +} + +type Factory interface { + Create(intf interface{}) (Dispatcher, error) +} + +var factories = make(map[string]Factory) + +func Register(name string, factory Factory) error { + factories[name] = factory + return nil +} + +func Create(name string, intf interface{}) (Dispatcher, error) { + factory, ok := factories[name] + if !ok { + return nil, errors.New("Factory not found") + } + + return factory.Create(intf) +} +>> + +metafact(fact) ::= "&meta.Facts_Fact{Name: \"\", Value: \"\"}," + +metadata(facts, provides) ::= +<< + +package ccs + +import ( + "errors" + "github.com/hyperledger/fabric/core/chaincode/shim" + "hyperledger/cci/org/hyperledger/chaintool/meta" +) + +var interfaces = map[string][]byte { + ": []byte(""),}; separator="\n"> +} + +var facts = &meta.Facts { + Facts: []*meta.Facts_Fact { + }; separator="\n"> + }, +} + +type ChaincodeMetaData struct { +} + +func (self *ChaincodeMetaData) GetInterfaces(stub *shim.ChaincodeStub, params *meta.GetInterfacesParams) (*meta.Interfaces, error) { + + response := &meta.Interfaces{} + for name, data := range interfaces { + desc := &meta.InterfaceDescriptor{Name: name} + + if params.IncludeContent { + desc.Data = data + } + + response.Descriptors = append(response.Descriptors, desc) + } + + return response, nil +} + +func (self *ChaincodeMetaData) GetInterface(stub *shim.ChaincodeStub, params *meta.GetInterfaceParams) (*meta.InterfaceDescriptor, error) { + + intf, ok := interfaces[params.Name] + if !ok { + return nil, errors.New("Interface " + params.Name + " not found") + } + + return &meta.InterfaceDescriptor{Data: intf}, nil +} + +func (self *ChaincodeMetaData) GetFacts(stub *shim.ChaincodeStub, params *meta.GetFactsParams) (*meta.Facts, error) { + + return facts, nil +} +>> + +server(base, intf) ::= +<< + +/* Generated by chaintool. DO NOT EDIT */ + +package + +import ( + "github.com/golang/protobuf/proto" + "github.com/hyperledger/fabric/core/chaincode/shim" + "/ccs/api" + "encoding/base64" + "errors" +) + +type CCInterface interface { + + +} + + +type stubImpl struct { + intf CCInterface +} + +// Factory mechanics +type factoryImpl struct { +} + +func init() { + self := &factoryImpl{} + api.Register("", self) +} + +func (self *factoryImpl) Create(intf interface{}) (api.Dispatcher, error) { + return &stubImpl{intf: intf.(CCInterface)}, nil +} + +func (self *stubImpl) DispatchTxn(stub *shim.ChaincodeStub, function int, params string) ([]byte, error) { + // Handle different functions + switch { + + default: + return nil, errors.New("Received unknown function invocation") + } +} + +func (self *stubImpl) DispatchQuery(stub *shim.ChaincodeStub, function int, params string) ([]byte, error) { + // Handle different functions + switch { + + default: + return nil, errors.New("Received unknown function invocation") + } +} + +/* Server stubs */ + + + + +>> + +client(base, intf) ::= +<< + +/* Generated by chaintool. DO NOT EDIT */ + +package + +import ( + "github.com/golang/protobuf/proto" + "github.com/hyperledger/fabric/core/chaincode/shim" + "encoding/base64" +) + +/* Client stubs */ + + + + +>> + +compositename(txn, intf, func) ::= "\"/txnquery/\"" +implementservers(intf, functions) ::= " }; separator=\"\n\">" +implementclients(txn, intf, functions) ::= " }; separator=\"\n\">" +dispatchfunctions(txn, intf, functions) ::= " }; separator=\"\n\">" + +declarefunctions(intf, functions) ::= +<< +(*shim.ChaincodeStub, *) (*, error)error }; separator="\n"> +>> + +dispatchfunction(txn, intf, func) ::= +<< +case function == : + return self.proxy(stub, params) +>> + +implementhandler(txn) ::= +<< +func (self *stubHandler) InvokeQuery(stub *shim.ChaincodeStub, function string, args []string) ([]byte, error) { + + if len(args) != 1 { + return nil, errors.New("Expected exactly one argument") + } + + dispatcher, index, err := self.decodeFunction(txnrequeryre, function) + if err != nil { + return nil, err + } + + return dispatcher.DispatchTxnQuery(stub, index, args[0]) +} +>> + +implementserver(intf, func) ::= +<< + +func (self *stubImpl) proxy(stub *shim.ChaincodeStub, _params string) ([]byte, error) { + + var err error; + + + params := &{} + _pbinput, err := base64.StdEncoding.DecodeString(_params) + if (err != nil) { + return nil, err + } + err = proto.Unmarshal(_pbinput, params) + if (err != nil) { + return nil, err + } + + + result, err := err = self.intf.(stub, params) + if (err != nil) { + return nil, err + } + + + _pboutput, err := proto.Marshal(result) + if (err != nil) { + return nil, err + } + _result := base64.StdEncoding.EncodeToString(_pboutput) + return []byte(_result), nil + + return nil, nil + +} + +>> + +implementclient(txn, intf, func) ::= +<< + +func (stub *shim.ChaincodeStub, chaincodeName string, params *) <\\> +(*, error)error { + + args := make([]string, 1) + var err error + + + _pboutput, err := proto.Marshal(params) + if (err != nil) { + return nil, err + } + + args[0] = base64.StdEncoding.EncodeToString(_pboutput) + + + _result, err :=_, err = stub.InvokeQueryChaincode(chaincodeName, , args) + + + result := &{} + _pbinput, err := base64.StdEncoding.DecodeString(string(_result)) + if (err != nil) { + return nil, err + } + err = proto.Unmarshal(_pbinput, result) + if (err != nil) { + return nil, err + } + return result, nil + + return err + +} + +>> diff --git a/resources/generators/proto.stg b/resources/generators/proto.stg new file mode 100644 index 0000000..92a52ad --- /dev/null +++ b/resources/generators/proto.stg @@ -0,0 +1,46 @@ + +emitfield(field) ::= " = ;" + +emitmsg(msg) ::= +<< +message { + +} +>> + +emitenum(enum) ::= +<< +enum { + }; separator="\n"> +} +>> + +emitdef(def) ::= +<< + + + +>> + +emitdefs(defs) ::= "}; separator=\"\n\">" + +protobuf(package, definitions, functions) ::= +<< +// +// Generated by chaintool. DO NOT EDIT!! +// + +syntax = "proto3"; + +package ; + + + + +// +// Available RPC functions exported by this interface +// + + () -> }; separator="\n"> + +>> diff --git a/resources/metadata/org.hyperledger.chaintool.meta.cci b/resources/metadata/org.hyperledger.chaintool.meta.cci new file mode 100644 index 0000000..319d34c --- /dev/null +++ b/resources/metadata/org.hyperledger.chaintool.meta.cci @@ -0,0 +1,35 @@ + +message InterfaceDescriptor { + string name = 1; + bytes data = 2; +} + +message Interfaces { + repeated InterfaceDescriptor descriptors = 1; +} + +message GetInterfacesParams { + bool IncludeContent = 1; +} + +message GetInterfaceParams { + string name = 1; +} + +message GetFactsParams { +} + +message Facts { + message Fact { + string name = 1; + string value = 2; + } + + repeated Fact facts = 1; +} + +queries { + Interfaces GetInterfaces(GetInterfacesParams) = 1; + InterfaceDescriptor GetInterface(GetInterfaceParams) = 2; + Facts GetFacts(GetFactsParams) = 3; +} diff --git a/resources/parsers/interface/grammar.bnf b/resources/parsers/interface/grammar.bnf new file mode 100644 index 0000000..a3e6854 --- /dev/null +++ b/resources/parsers/interface/grammar.bnf @@ -0,0 +1,67 @@ + +interface ::= ( message | enum )* transactions? queries? + +message ::= <"message"> ident messageBody + +enum ::= <"enum"> ident <"{"> ( enumField | <";"> )* <"}"> + +enumField ::= enumName <"="> enumValue <";"> + ::= ident + ::= intLit + +transactions ::= <"transactions"> functions +queries ::= <"queries"> functions + + ::= <"{"> function* <"}"> +function ::= rettype functionName <"("> param? <")"> <"="> index <";"> +functionName := ident +rettype ::= ident +param ::= ident + +optionBody ::= ident ( "." ident )* "=" constant + + ::= <"{"> ( field | enum | message )* <"}"> + +field ::= modifier? type fieldName <"="> index ( <"["> fieldOption ( <","> fieldOption )* <"]"> )? <";"> + +fieldName ::= ident +fieldOption ::= optionBody | "default" "=" constant + +modifier ::= "required" | "repeated" + +type ::= scalar / userType + +scalar ::= "double" | "float" | "int32" | "int64" | "uint32" | "uint64" | "sint32" | "sint64" | "fixed32" | "fixed64" | "sfixed32" | "sfixed64" | "bool" | "string" | "bytes" + +userType ::= ( "."? ident )+ + +constant ::= ident | intLit | floatLit | strLit | boolLit + + ::= #"[A-Za-z_][\w_]*" + +camelIdent ::= #"[A-Z][\w_]*" + +index ::= intLit + + ::= decInt | hexInt | octInt + + ::= #"\d+" + + ::= #"0[xX]([A-Fa-f0-9])+" + + ::= #"0[0-7]+" + + ::= #"\d+(\.\d+)?([Ee][\+-]?\d+)?" + + ::= "true" | "false" + + ::= quote ( hexEscape | octEscape | charEscape )* quote + + ::= #"[\"']" + + ::= #"\\[Xx][A-Fa-f0-9]{1,2}" + + ::= #"\\0?[0-7]{1,3}" + + ::= #"\\[abfnrtv\\\?'\"]" + diff --git a/resources/parsers/interface/skip.bnf b/resources/parsers/interface/skip.bnf new file mode 100644 index 0000000..8a9fb65 --- /dev/null +++ b/resources/parsers/interface/skip.bnf @@ -0,0 +1,13 @@ + +skipper ::= (whitespace | blankline | ( wlcomment / comment))* + +whitespace ::= #"[ \t]" +blankline ::= #"^\n" +wlcomment ::= #'^' comment '\n' +comment ::= ('//' | '#') (!'\n' #'.')* + + + + + + diff --git a/resources/parsers/proto/grammar.bnf b/resources/parsers/proto/grammar.bnf new file mode 100644 index 0000000..627b0a8 --- /dev/null +++ b/resources/parsers/proto/grammar.bnf @@ -0,0 +1,63 @@ + +proto ::= syntax? package? ( message | enum )* + +syntax ::= <"syntax"> <"="> <"\""> ident <"\""><";"> +package ::= <"package"> packageName <";"> + +packageName ::= #"[A-Za-z_.]*" + +message ::= <"message"> ident messageBody + +enum ::= <"enum"> ident <"{"> ( enumField | <";"> )* <"}"> + +enumField ::= enumName <"="> enumValue <";"> + ::= ident + ::= intLit + +optionBody ::= ident ( "." ident )* "=" constant + + ::= <"{"> ( field | enum | message )* <"}"> + +field ::= modifier? type fieldName <"="> index ( <"["> fieldOption ( <","> fieldOption )* <"]"> )? <";"> + +fieldName ::= ident +fieldOption ::= optionBody | "default" "=" constant + +modifier ::= "required" | "repeated" + +type ::= scalar / userType + +scalar ::= "double" | "float" | "int32" | "int64" | "uint32" | "uint64" | "sint32" | "sint64" | "fixed32" | "fixed64" | "sfixed32" | "sfixed64" | "bool" | "string" | "bytes" + +userType ::= ( "."? ident )+ + +constant ::= ident | intLit | floatLit | strLit | boolLit + + ::= #"[A-Za-z_][\w_]*" + +camelIdent ::= #"[A-Z][\w_]*" + +index ::= intLit + + ::= decInt | hexInt | octInt + + ::= #"\d+" + + ::= #"0[xX]([A-Fa-f0-9])+" + + ::= #"0[0-7]+" + + ::= #"\d+(\.\d+)?([Ee][\+-]?\d+)?" + + ::= "true" | "false" + + ::= quote ( hexEscape | octEscape | charEscape )* quote + + ::= #"[\"']" + + ::= #"\\[Xx][A-Fa-f0-9]{1,2}" + + ::= #"\\0?[0-7]{1,3}" + + ::= #"\\[abfnrtv\\\?'\"]" + diff --git a/resources/parsers/proto/skip.bnf b/resources/parsers/proto/skip.bnf new file mode 100644 index 0000000..8a9fb65 --- /dev/null +++ b/resources/parsers/proto/skip.bnf @@ -0,0 +1,13 @@ + +skipper ::= (whitespace | blankline | ( wlcomment / comment))* + +whitespace ::= #"[ \t]" +blankline ::= #"^\n" +wlcomment ::= #'^' comment '\n' +comment ::= ('//' | '#') (!'\n' #'.')* + + + + + + diff --git a/resources/proto/car.proto b/resources/proto/car.proto new file mode 100644 index 0000000..198d7e4 --- /dev/null +++ b/resources/proto/car.proto @@ -0,0 +1,131 @@ +/* +Copyright London Stock Exchange Group 2016 All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + + +/* +************************************************************************************* + + We create a new archive format called CAR (chaincode archive) to package up + chaincode assets. Our first approach was to reuse an existing archive format/tooling + (e.g. tar, zip, etc). However, most had problems with determinisim. For instance, + tar injects things like UIDs and timestamps into the binary, which could result + in a different binary each time regardless of code content. + + The "ar" tool from binutils showed some promise with explicit support for determinism, + but its focus on elf containers seemed inappropriate. In the end, we realized it + might be more straightforward to leverage our existing investment in protobufs and + build our own custom format. It's not all that complicated anyway (famous last words). + + The current implementation is somewhat naive in that it assumes that the compressed + contents of the archive will have no problem fitting in memory and/or a single + protobuf object (defaults to 64MB max, I think). This is ok. For one, chaincode + packages by definition should strive to be as small as possible since they + need to be distributed around and persisted on the ledger. We certainly don't want to + encourage anyone to submit really huge applications by making it easy to package one + up ;). If this ever changes, the fundamental nature of protobufs should allow us + to be creative in enhancing the capabilities without breaking compatibility. + + ---- Schema ----- + + current definition {:magic "org.hyperledger.chaincode-archive" :version 1} + + A given archive file consists of two primary protobuf objects: + + [[delim] CompatibilityHeader, [delim] Archive] + + that are written with the java .writeDelimitedTo() (https://goo.gl/8NeMkT) function. + The delimimter is a simple size indicator, the specifications of which are left + as an exercise for the reader. The rest of the specification should be + understandable to someone fluent in protobuf definitions, as per below. + + A few notes: + + 1) Generally speaking, for a given {:magic :version} tuple, the + CompatibilityHeader should never, ever, ever be modified in a way that breaks + backwards/forward compatibility. It is, however, ok to extend it using standard + protobuf techniques should that ever be necessary. Most enhancements should be + done via the "features" facility. For example: + + features = ["org.hyperledger.car.enhancement23", "com.acme.gizmo.awesome"] + + may indicate that certain features are present. Components that understand + what that means may react to the presence of the feature flag. Those that + do not should be able to safely ignore it (generally relying on protobuf + techniques to avoid incongruent structures) + 2) If breaking compatibility is unvoidable, you _must_ modify either one or both + of the {:magic :version} tuple. Changing either one is a statment of gross + incompatibility with orthogonal version tuples. This is generally only done + in extreme circumstances as an alternative to leaving software with no + deterministic method to detect a problem. + 3) There is an intentional level of indirection between Archive and Payload to + facilitate ease in generating a comprehensive signature. Achive.payload is + expected to be the raw binary serialized form of Achive::Payload. + 4) The top-level Archive object should generally strive to remain as lightweight + as possible to encapsulate as many fields as possible under the signature + algorithm. + +*************************************************************************************** +*/ + +syntax = "proto2"; +package chaintool.car.abi; + +message CompatibilityHeader { + required string magic = 1; + required int32 version = 2; + repeated string features = 3; +} + +message Archive { + message Signature { + enum Type { + NONE = 1; + RSA = 2; + } + + optional Type type = 1; + optional string description = 2; + optional bytes data = 3; + } + + message Payload { + message Compression { + enum Type { + NONE = 1; + GZIP = 2; + LZMA = 3; + BZIP2 = 4; + XZ = 5; + } + + optional Type type = 1 [default = NONE]; + optional string description = 2; + } + + message Entries { + optional string path = 1; + optional uint64 size = 2; + optional string sha1 = 3; + optional bytes data = 16; + } + + optional Compression compression = 1; + repeated Entries entries = 16; + } + + optional Signature signature = 1; + optional bytes payload = 2; +} diff --git a/src/chaintool/ast.clj b/src/chaintool/ast.clj new file mode 100644 index 0000000..6be9212 --- /dev/null +++ b/src/chaintool/ast.clj @@ -0,0 +1,33 @@ +;; Copyright London Stock Exchange Group 2016 All Rights Reserved. +;; +;; Licensed under the Apache License, Version 2.0 (the "License"); +;; you may not use this file except in compliance with the License. +;; You may obtain a copy of the License at +;; +;; http://www.apache.org/licenses/LICENSE-2.0 +;; +;; Unless required by applicable law or agreed to in writing, software +;; distributed under the License is distributed on an "AS IS" BASIS, +;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +;; See the License for the specific language governing permissions and +;; limitations under the License. + +(ns chaintool.ast + (:require [clojure.zip :as zip]) + (:refer-clojure :exclude [find])) + +;;----------------------------------------------------------------- +;; find a specific element in the AST +;;----------------------------------------------------------------- +(defn find [term ast] + (loop [loc ast] + (cond + + (or (nil? loc) (zip/end? loc)) + nil + + (= (zip/node loc) term) + (zip/up loc) + + :else + (recur (zip/next loc))))) diff --git a/src/chaintool/build/core.clj b/src/chaintool/build/core.clj new file mode 100644 index 0000000..d063540 --- /dev/null +++ b/src/chaintool/build/core.clj @@ -0,0 +1,22 @@ +;; Copyright London Stock Exchange Group 2016 All Rights Reserved. +;; +;; Licensed under the Apache License, Version 2.0 (the "License"); +;; you may not use this file except in compliance with the License. +;; You may obtain a copy of the License at +;; +;; http://www.apache.org/licenses/LICENSE-2.0 +;; +;; Unless required by applicable law or agreed to in writing, software +;; distributed under the License is distributed on an "AS IS" BASIS, +;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +;; See the License for the specific language governing permissions and +;; limitations under the License. +(ns chaintool.build.core + (:require [chaintool.platforms.core :as platforms.core] + [chaintool.platforms.api :as platforms.api]) + (:refer-clojure :exclude [compile])) + +(defn compile [{:keys [config] :as params}] + (when-let [platform (platforms.core/find config)] + ;; generate platform output (shim, protobufs, etc) + (platforms.api/build platform params))) diff --git a/src/chaintool/build/interface.clj b/src/chaintool/build/interface.clj new file mode 100644 index 0000000..1d33952 --- /dev/null +++ b/src/chaintool/build/interface.clj @@ -0,0 +1,393 @@ +;; Copyright London Stock Exchange Group 2016 All Rights Reserved. +;; +;; Licensed under the Apache License, Version 2.0 (the "License"); +;; you may not use this file except in compliance with the License. +;; You may obtain a copy of the License at +;; +;; http://www.apache.org/licenses/LICENSE-2.0 +;; +;; Unless required by applicable law or agreed to in writing, software +;; distributed under the License is distributed on an "AS IS" BASIS, +;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +;; See the License for the specific language governing permissions and +;; limitations under the License. + +(ns chaintool.build.interface + (:require [chaintool.ast :as ast] + [chaintool.util :as util] + [clojure.java.io :as io] + [clojure.set :as set] + [clojure.string :as string] + [clojure.walk :as walk] + [clojure.zip :as zip] + [instaparse.core :as insta]) + (:refer-clojure :exclude [compile])) + +(def skipper (insta/parser (io/resource "parsers/interface/skip.bnf"))) +(def grammar (insta/parser (io/resource "parsers/interface/grammar.bnf") :auto-whitespace skipper)) + +(defn parse [intf] + (let [result (insta/add-line-and-column-info-to-metadata intf (grammar intf))] + (if (insta/failure? result) + (let [{:keys [line column text]} result] + (util/abort -1 (str "could not parse \"" text "\": line=" line " column=" column))) + (zip/vector-zip result)))) + +;;----------------------------------------------------------------- +;; retrieve all "provided" interfaces, adding the implicit +;; "appinit.cci" and translating "self" to the name of the project +;;----------------------------------------------------------------- +(defn getprovides [config] + (let [name (:Name config) + entries (:Provides config)] + (->> entries flatten (remove nil?) (walk/postwalk-replace {"self" name}) (cons "appinit") (into #{})))) + +(defn getconsumes [config] + (->> config :Consumes (remove nil?) (into #{}))) + +;;----------------------------------------------------------------- +;; aggregate all of the interfaces declared in the config +;;----------------------------------------------------------------- +(defn getinterfaces [config] + (into '() (set/union (getprovides config) (getconsumes config)))) + +;;----------------------------------------------------------------- +;; getX - helper functions to extract data from an interface AST +;;----------------------------------------------------------------- +(defn get-raw-attrs [ast] + (loop [loc (zip/right ast) attrs {}] + (if (nil? loc) + attrs + ;; else + (let [[k v] (zip/node loc)] + (recur (zip/right loc) (assoc attrs k v)))))) + +(defn getattrs [ast] + (let [{:keys [type] :as attrs} (get-raw-attrs ast) + [subType typeName] type] + ;; sythesize the subType/typeName fields + (merge attrs {:subType subType :typeName typeName}))) + +(defn get-index [ast] + (let [{:keys [index]} (getattrs ast)] + index)) + +(defn get-enum-index [ast] + (let [name (->> ast zip/right zip/node) + value (->> ast zip/right zip/right zip/node)] + value)) + +(defn getentries [ast] + (loop [loc ast fields {}] + (cond + + (nil? loc) + fields + + :else + (let [attrs (->> loc zip/down getattrs)] + (recur (zip/right loc) (assoc fields (:index attrs) attrs)))))) + +(defn get-definition-name [ast] + (->> ast zip/right zip/node)) + +(defn getmessage [ast] + (let [name (get-definition-name ast) + fields (getentries (->> ast zip/right zip/right))] + (vector name fields))) + +(defn getmessages [interface] + (into {} (loop [loc interface msgs '()] + (cond + + (or (nil? loc) (zip/end? loc)) + msgs + + :else + (let [node (zip/node loc)] + (recur (zip/next loc) + (if (= node :message) + (cons (getmessage loc) msgs) + msgs))))))) + +(defn getfunctions [ast] + (let [name (->> ast zip/down zip/node) + functions (getentries (->> ast zip/down zip/right))] + (vector name functions))) + +(defn getgeneric [ast term] + (if-let [results (ast/find term ast)] + (getfunctions results))) + +(defn gettransactions [ast] (getgeneric ast :transactions)) +(defn getqueries [ast] (getgeneric ast :queries)) +(defn getallfunctions [ast] (into {} (vector (gettransactions ast) (getqueries ast)))) + +(defn find-definition-in-local [name ast] + (let [start (zip/leftmost ast)] + (loop [loc (case (zip/node start) + ;; each :message entry looks like [:message $name fields...], + ;; so "start + right + right" gets the first field + :message (->> start zip/right zip/right) + + ;; each :interface entry looks like [:interface [:message] [:message] ...], + ;; so "start+right" gets the first msg + :interface (zip/right start) + + ;; otherwise, skip + nil)] + (cond + + ;; end of the line? + (nil? loc) + nil + + ;; name matches? + (= name (let [node (zip/down loc) + type (zip/node node)] + (when (or (= type :message) (= type :enum)) + (get-definition-name node)))) + true + + ;; otherwise, keep searching + :else + (recur (zip/right loc)))))) + +;;----------------------------------------------------------------- +;; get-lineno: get the line number for a given AST entry +;;----------------------------------------------------------------- +(defn get-lineno [ast] + ;; use the end-line since instaparse includes whitespace and the start-line is typically the previous line + (->> ast meta :instaparse.gll/end-line)) + +;;----------------------------------------------------------------- +;; error threading helpers +;;----------------------------------------------------------------- +(defn bind-error [f [val err]] + (if (nil? err) + (f val) + [nil err])) + +(defmacro err->> [val & fns] + (let [fns (for [f fns] `(bind-error ~f))] + `(->> [~val nil] + ~@fns))) + +;;----------------------------------------------------------------- +;; verify-XX - verify our interface is rational +;;----------------------------------------------------------------- +;; A sanely defined interface should ensure several things +;; +;; 1) All field types are either scalars or defined within the interface +;; following inner-to-outer scoping. +;; +;; 2) Indexes should never overlap +;; +;; 3) All functions reference either void, or reference a valid +;; top-level message for both return and/or input parameters +;;----------------------------------------------------------------- + +;;----------------------------------------------------------------- +;; verify-usertype: fields of type :userType need to reference an +;; in scope definition (:message or :enum). Therefore, we need to +;; walk our scope backwards to find if this usertype has been defined +;;----------------------------------------------------------------- +(defn verify-usertype [ast] + (let [{:keys [typeName fieldName type]} (getattrs ast)] + (loop [loc (zip/up ast)] + (cond + + (nil? loc) + [nil (str "line " (get-lineno type) ": type \"" typeName "\" for field \"" fieldName "\" is not defined")] + + (find-definition-in-local typeName loc) + [ast nil] + + :else + (recur (zip/up loc)))))) + +;;----------------------------------------------------------------- +;; verify-fieldtype: validate a field according to the type it is +;;----------------------------------------------------------------- +(defn verify-fieldtype [ast] + (let [{:keys [subType]} (getattrs ast)] + (case subType + :userType (verify-usertype ast) + :scalar [ast nil]))) + +;;----------------------------------------------------------------- +;; check-index-default: ensures our default index is 0 +;;----------------------------------------------------------------- +(defn check-index-default [index indices ast] + (if (and (empty? indices) (not (zero? index))) + (let [node (->> ast zip/up zip/node)] + [nil (str "line " (get-lineno node) ": default/first index must be 0")]) + ;; else + [ast nil])) + +;;----------------------------------------------------------------- +;; check-index-dups: ensures we do not have any duplicate indices +;;----------------------------------------------------------------- +(defn check-index-dups [index indices ast] + (if (contains? indices index) + (let [node (->> ast zip/up zip/node)] + [nil (str "line " (get-lineno node) ": duplicate index " index ", previously seen on line " (indices index))]) + ;; else + [ast nil])) + +;;----------------------------------------------------------------- +;; verify-field: ensure a field is valid by running various +;; verifications such as checking scope resolution for any custom +;; types, and ensuring our indices do not conflict +;;----------------------------------------------------------------- +(defn verify-msg-field [ast indices] + (let [[_ error] (err->> ast + verify-fieldtype + #(check-index-dups (get-index ast) indices %)) + lineno (->> ast zip/up zip/node get-lineno)] + (if (nil? error) + ;; add our index to the table + [(assoc indices (get-index ast) lineno) nil] + ;; else, stop on error + [indices error]))) + +;;----------------------------------------------------------------- +;; verify-enumfield: ensure a enum field is valid by running various +;; verifications such as checking for duplicate names and ensuring +;; our indices do not conflict +;;----------------------------------------------------------------- +(defn verify-enum-field [ast indices] + (let [index (->> ast get-enum-index Integer/parseInt) + [_ error] (err->> ast + #(check-index-default index indices %) + #(check-index-dups index indices %)) + lineno (->> ast zip/up zip/node get-lineno)] + (if (nil? error) + ;; add our index to the table + [(assoc indices index lineno) nil] + ;; else, stop on error + [indices error]))) + +;;----------------------------------------------------------------- +;; verify-message: verify the fields of a message by scanning through +;; all fields in the AST, skipping non :field types +;;----------------------------------------------------------------- +(defn verify-message [ast] + (let [name (get-definition-name ast)] + (loop [loc (->> ast zip/right zip/right) _indices {}] + (cond + + (nil? loc) + nil + + :else + (let [node (zip/down loc) + type (zip/node node) + [indices error] (if (= type :field) + (verify-msg-field node _indices) + [_indices nil])] + + (if (nil? error) + (recur (zip/right loc) indices) + error)))))) + +;;----------------------------------------------------------------- +;; verify-enum: ensure enum entries do not have any conflicting indices +;;----------------------------------------------------------------- +(defn verify-enum [ast] + (let [name (get-definition-name ast)] + (loop [loc (->> ast zip/right zip/right) _indices {}] + (cond + + (nil? loc) + nil + + :else + (let [node (zip/down loc) + type (zip/node node) + [indices error] (if (= type :enumField) + (verify-enum-field node _indices) + [_indices nil])] + + (if (nil? error) + (recur (zip/right loc) indices) + error)))))) + +;;----------------------------------------------------------------- +;; verify-intf: scan the entire interface and validate various +;; types we encounter +;;----------------------------------------------------------------- +(defn verify-intf [intf] + (loop [loc intf] + (cond + + (or (nil? loc) (zip/end? loc)) + nil + + :else + (let [node (zip/node loc)] + (if-let [error (case node + :message (verify-message loc) + :enum (verify-enum loc) + nil)] + error + (recur (zip/next loc))))))) + +;;----------------------------------------------------------------- +;; compileintf - Compile an interface to an AST. +;;----------------------------------------------------------------- +(defn compileintf + + ;; takes a path + interface name, maps it to a file, and compiles + ([path intf] + (println (str "[CCI] parse " intf)) + (let [path (io/file path (str intf ".cci")) + data (util/safe-slurp path)] + (compileintf {:path (.getCanonicalPath path) :data data}))) + + ;; pass the raw interface bytes in directly and compile to AST + ([{:keys [path data]}] + (let [ast (parse data)] + + (when-let [errors (verify-intf ast)] + (util/abort -1 (str "Errors parsing " path ": " (string/join errors)))) + + ;; return the AST + ast))) + +;;----------------------------------------------------------------- +;; returns true if the interface contains a message named "Init" +;;----------------------------------------------------------------- +(defn initmsg? [ast] + (let [msgs (getmessages ast)] + (if (msgs "Init") + true + false))) + +(defn verify-init [interfaces] + (let [ast (interfaces "appinit")] + (cond + + ;; We do not allow any explicit transactions or queries in the project interface + (or (ast/find :transactions ast) (ast/find :queries ast)) + (str "appinit.cci: illegal RPCs detected") + + ;; We cannot continue if the user didnt supply a message "Init" which will + ;; serve as the implicit parameter to our init function + (not (initmsg? ast)) + (str "appinit.cci: message Init{} not found") + + :else + nil))) + +;;----------------------------------------------------------------- +;; compile all applicable interfaces into a map of ASTs keyed by interface name +;;----------------------------------------------------------------- +(defn compile [path config] + (let [names (getinterfaces config) + interfaces (into {} (map #(vector % (compileintf path %)) names))] + + ;; sanity check the project interface + (if-let [err (verify-init interfaces)] + (util/abort -1 err) + interfaces))) diff --git a/src/chaintool/car/abi/Car.java b/src/chaintool/car/abi/Car.java new file mode 100644 index 0000000..d822789 --- /dev/null +++ b/src/chaintool/car/abi/Car.java @@ -0,0 +1,4516 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: resources/proto/car.proto + +package chaintool.car.abi; + +public final class Car { + private Car() {} + public static void registerAllExtensions( + com.google.protobuf.ExtensionRegistry registry) { + } + public interface CompatibilityHeaderOrBuilder extends + // @@protoc_insertion_point(interface_extends:chaintool.car.abi.CompatibilityHeader) + com.google.protobuf.MessageOrBuilder { + + /** + * required string magic = 1; + */ + boolean hasMagic(); + /** + * required string magic = 1; + */ + java.lang.String getMagic(); + /** + * required string magic = 1; + */ + com.google.protobuf.ByteString + getMagicBytes(); + + /** + * required int32 version = 2; + */ + boolean hasVersion(); + /** + * required int32 version = 2; + */ + int getVersion(); + + /** + * repeated string features = 3; + */ + com.google.protobuf.ProtocolStringList + getFeaturesList(); + /** + * repeated string features = 3; + */ + int getFeaturesCount(); + /** + * repeated string features = 3; + */ + java.lang.String getFeatures(int index); + /** + * repeated string features = 3; + */ + com.google.protobuf.ByteString + getFeaturesBytes(int index); + } + /** + * Protobuf type {@code chaintool.car.abi.CompatibilityHeader} + */ + public static final class CompatibilityHeader extends + com.google.protobuf.GeneratedMessage implements + // @@protoc_insertion_point(message_implements:chaintool.car.abi.CompatibilityHeader) + CompatibilityHeaderOrBuilder { + // Use CompatibilityHeader.newBuilder() to construct. + private CompatibilityHeader(com.google.protobuf.GeneratedMessage.Builder builder) { + super(builder); + } + private CompatibilityHeader() { + magic_ = ""; + version_ = 0; + features_ = com.google.protobuf.LazyStringArrayList.EMPTY; + } + + @java.lang.Override + public final com.google.protobuf.UnknownFieldSet + getUnknownFields() { + return this.unknownFields; + } + private CompatibilityHeader( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) { + this(); + int mutable_bitField0_ = 0; + com.google.protobuf.UnknownFieldSet.Builder unknownFields = + com.google.protobuf.UnknownFieldSet.newBuilder(); + try { + boolean done = false; + while (!done) { + int tag = input.readTag(); + switch (tag) { + case 0: + done = true; + break; + default: { + if (!parseUnknownField(input, unknownFields, + extensionRegistry, tag)) { + done = true; + } + break; + } + case 10: { + com.google.protobuf.ByteString bs = input.readBytes(); + bitField0_ |= 0x00000001; + magic_ = bs; + break; + } + case 16: { + bitField0_ |= 0x00000002; + version_ = input.readInt32(); + break; + } + case 26: { + com.google.protobuf.ByteString bs = input.readBytes(); + if (!((mutable_bitField0_ & 0x00000004) == 0x00000004)) { + features_ = new com.google.protobuf.LazyStringArrayList(); + mutable_bitField0_ |= 0x00000004; + } + features_.add(bs); + break; + } + } + } + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw new RuntimeException(e.setUnfinishedMessage(this)); + } catch (java.io.IOException e) { + throw new RuntimeException( + new com.google.protobuf.InvalidProtocolBufferException( + e.getMessage()).setUnfinishedMessage(this)); + } finally { + if (((mutable_bitField0_ & 0x00000004) == 0x00000004)) { + features_ = features_.getUnmodifiableView(); + } + this.unknownFields = unknownFields.build(); + makeExtensionsImmutable(); + } + } + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return chaintool.car.abi.Car.internal_static_chaintool_car_abi_CompatibilityHeader_descriptor; + } + + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return chaintool.car.abi.Car.internal_static_chaintool_car_abi_CompatibilityHeader_fieldAccessorTable + .ensureFieldAccessorsInitialized( + chaintool.car.abi.Car.CompatibilityHeader.class, chaintool.car.abi.Car.CompatibilityHeader.Builder.class); + } + + private int bitField0_; + public static final int MAGIC_FIELD_NUMBER = 1; + private volatile java.lang.Object magic_; + /** + * required string magic = 1; + */ + public boolean hasMagic() { + return ((bitField0_ & 0x00000001) == 0x00000001); + } + /** + * required string magic = 1; + */ + public java.lang.String getMagic() { + java.lang.Object ref = magic_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + if (bs.isValidUtf8()) { + magic_ = s; + } + return s; + } + } + /** + * required string magic = 1; + */ + public com.google.protobuf.ByteString + getMagicBytes() { + java.lang.Object ref = magic_; + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + magic_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + public static final int VERSION_FIELD_NUMBER = 2; + private int version_; + /** + * required int32 version = 2; + */ + public boolean hasVersion() { + return ((bitField0_ & 0x00000002) == 0x00000002); + } + /** + * required int32 version = 2; + */ + public int getVersion() { + return version_; + } + + public static final int FEATURES_FIELD_NUMBER = 3; + private com.google.protobuf.LazyStringList features_; + /** + * repeated string features = 3; + */ + public com.google.protobuf.ProtocolStringList + getFeaturesList() { + return features_; + } + /** + * repeated string features = 3; + */ + public int getFeaturesCount() { + return features_.size(); + } + /** + * repeated string features = 3; + */ + public java.lang.String getFeatures(int index) { + return features_.get(index); + } + /** + * repeated string features = 3; + */ + public com.google.protobuf.ByteString + getFeaturesBytes(int index) { + return features_.getByteString(index); + } + + private byte memoizedIsInitialized = -1; + public final boolean isInitialized() { + byte isInitialized = memoizedIsInitialized; + if (isInitialized == 1) return true; + if (isInitialized == 0) return false; + + if (!hasMagic()) { + memoizedIsInitialized = 0; + return false; + } + if (!hasVersion()) { + memoizedIsInitialized = 0; + return false; + } + memoizedIsInitialized = 1; + return true; + } + + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + if (((bitField0_ & 0x00000001) == 0x00000001)) { + com.google.protobuf.GeneratedMessage.writeString(output, 1, magic_); + } + if (((bitField0_ & 0x00000002) == 0x00000002)) { + output.writeInt32(2, version_); + } + for (int i = 0; i < features_.size(); i++) { + com.google.protobuf.GeneratedMessage.writeString(output, 3, features_.getRaw(i)); + } + unknownFields.writeTo(output); + } + + public int getSerializedSize() { + int size = memoizedSize; + if (size != -1) return size; + + size = 0; + if (((bitField0_ & 0x00000001) == 0x00000001)) { + size += com.google.protobuf.GeneratedMessage.computeStringSize(1, magic_); + } + if (((bitField0_ & 0x00000002) == 0x00000002)) { + size += com.google.protobuf.CodedOutputStream + .computeInt32Size(2, version_); + } + { + int dataSize = 0; + for (int i = 0; i < features_.size(); i++) { + dataSize += computeStringSizeNoTag(features_.getRaw(i)); + } + size += dataSize; + size += 1 * getFeaturesList().size(); + } + size += unknownFields.getSerializedSize(); + memoizedSize = size; + return size; + } + + private static final long serialVersionUID = 0L; + public static chaintool.car.abi.Car.CompatibilityHeader parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static chaintool.car.abi.Car.CompatibilityHeader parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static chaintool.car.abi.Car.CompatibilityHeader parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static chaintool.car.abi.Car.CompatibilityHeader parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static chaintool.car.abi.Car.CompatibilityHeader parseFrom(java.io.InputStream input) + throws java.io.IOException { + return PARSER.parseFrom(input); + } + public static chaintool.car.abi.Car.CompatibilityHeader parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return PARSER.parseFrom(input, extensionRegistry); + } + public static chaintool.car.abi.Car.CompatibilityHeader parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + return PARSER.parseDelimitedFrom(input); + } + public static chaintool.car.abi.Car.CompatibilityHeader parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return PARSER.parseDelimitedFrom(input, extensionRegistry); + } + public static chaintool.car.abi.Car.CompatibilityHeader parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return PARSER.parseFrom(input); + } + public static chaintool.car.abi.Car.CompatibilityHeader parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return PARSER.parseFrom(input, extensionRegistry); + } + + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder() { + return DEFAULT_INSTANCE.toBuilder(); + } + public static Builder newBuilder(chaintool.car.abi.Car.CompatibilityHeader prototype) { + return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); + } + public Builder toBuilder() { + return this == DEFAULT_INSTANCE + ? new Builder() : new Builder().mergeFrom(this); + } + + @java.lang.Override + protected Builder newBuilderForType( + com.google.protobuf.GeneratedMessage.BuilderParent parent) { + Builder builder = new Builder(parent); + return builder; + } + /** + * Protobuf type {@code chaintool.car.abi.CompatibilityHeader} + */ + public static final class Builder extends + com.google.protobuf.GeneratedMessage.Builder implements + // @@protoc_insertion_point(builder_implements:chaintool.car.abi.CompatibilityHeader) + chaintool.car.abi.Car.CompatibilityHeaderOrBuilder { + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return chaintool.car.abi.Car.internal_static_chaintool_car_abi_CompatibilityHeader_descriptor; + } + + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return chaintool.car.abi.Car.internal_static_chaintool_car_abi_CompatibilityHeader_fieldAccessorTable + .ensureFieldAccessorsInitialized( + chaintool.car.abi.Car.CompatibilityHeader.class, chaintool.car.abi.Car.CompatibilityHeader.Builder.class); + } + + // Construct using chaintool.car.abi.Car.CompatibilityHeader.newBuilder() + private Builder() { + maybeForceBuilderInitialization(); + } + + private Builder( + com.google.protobuf.GeneratedMessage.BuilderParent parent) { + super(parent); + maybeForceBuilderInitialization(); + } + private void maybeForceBuilderInitialization() { + if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) { + } + } + public Builder clear() { + super.clear(); + magic_ = ""; + bitField0_ = (bitField0_ & ~0x00000001); + version_ = 0; + bitField0_ = (bitField0_ & ~0x00000002); + features_ = com.google.protobuf.LazyStringArrayList.EMPTY; + bitField0_ = (bitField0_ & ~0x00000004); + return this; + } + + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return chaintool.car.abi.Car.internal_static_chaintool_car_abi_CompatibilityHeader_descriptor; + } + + public chaintool.car.abi.Car.CompatibilityHeader getDefaultInstanceForType() { + return chaintool.car.abi.Car.CompatibilityHeader.getDefaultInstance(); + } + + public chaintool.car.abi.Car.CompatibilityHeader build() { + chaintool.car.abi.Car.CompatibilityHeader result = buildPartial(); + if (!result.isInitialized()) { + throw newUninitializedMessageException(result); + } + return result; + } + + public chaintool.car.abi.Car.CompatibilityHeader buildPartial() { + chaintool.car.abi.Car.CompatibilityHeader result = new chaintool.car.abi.Car.CompatibilityHeader(this); + int from_bitField0_ = bitField0_; + int to_bitField0_ = 0; + if (((from_bitField0_ & 0x00000001) == 0x00000001)) { + to_bitField0_ |= 0x00000001; + } + result.magic_ = magic_; + if (((from_bitField0_ & 0x00000002) == 0x00000002)) { + to_bitField0_ |= 0x00000002; + } + result.version_ = version_; + if (((bitField0_ & 0x00000004) == 0x00000004)) { + features_ = features_.getUnmodifiableView(); + bitField0_ = (bitField0_ & ~0x00000004); + } + result.features_ = features_; + result.bitField0_ = to_bitField0_; + onBuilt(); + return result; + } + + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof chaintool.car.abi.Car.CompatibilityHeader) { + return mergeFrom((chaintool.car.abi.Car.CompatibilityHeader)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(chaintool.car.abi.Car.CompatibilityHeader other) { + if (other == chaintool.car.abi.Car.CompatibilityHeader.getDefaultInstance()) return this; + if (other.hasMagic()) { + bitField0_ |= 0x00000001; + magic_ = other.magic_; + onChanged(); + } + if (other.hasVersion()) { + setVersion(other.getVersion()); + } + if (!other.features_.isEmpty()) { + if (features_.isEmpty()) { + features_ = other.features_; + bitField0_ = (bitField0_ & ~0x00000004); + } else { + ensureFeaturesIsMutable(); + features_.addAll(other.features_); + } + onChanged(); + } + this.mergeUnknownFields(other.unknownFields); + onChanged(); + return this; + } + + public final boolean isInitialized() { + if (!hasMagic()) { + return false; + } + if (!hasVersion()) { + return false; + } + return true; + } + + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + chaintool.car.abi.Car.CompatibilityHeader parsedMessage = null; + try { + parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry); + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + parsedMessage = (chaintool.car.abi.Car.CompatibilityHeader) e.getUnfinishedMessage(); + throw e; + } finally { + if (parsedMessage != null) { + mergeFrom(parsedMessage); + } + } + return this; + } + private int bitField0_; + + private java.lang.Object magic_ = ""; + /** + * required string magic = 1; + */ + public boolean hasMagic() { + return ((bitField0_ & 0x00000001) == 0x00000001); + } + /** + * required string magic = 1; + */ + public java.lang.String getMagic() { + java.lang.Object ref = magic_; + if (!(ref instanceof java.lang.String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + if (bs.isValidUtf8()) { + magic_ = s; + } + return s; + } else { + return (java.lang.String) ref; + } + } + /** + * required string magic = 1; + */ + public com.google.protobuf.ByteString + getMagicBytes() { + java.lang.Object ref = magic_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + magic_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + * required string magic = 1; + */ + public Builder setMagic( + java.lang.String value) { + if (value == null) { + throw new NullPointerException(); + } + bitField0_ |= 0x00000001; + magic_ = value; + onChanged(); + return this; + } + /** + * required string magic = 1; + */ + public Builder clearMagic() { + bitField0_ = (bitField0_ & ~0x00000001); + magic_ = getDefaultInstance().getMagic(); + onChanged(); + return this; + } + /** + * required string magic = 1; + */ + public Builder setMagicBytes( + com.google.protobuf.ByteString value) { + if (value == null) { + throw new NullPointerException(); + } + bitField0_ |= 0x00000001; + magic_ = value; + onChanged(); + return this; + } + + private int version_ ; + /** + * required int32 version = 2; + */ + public boolean hasVersion() { + return ((bitField0_ & 0x00000002) == 0x00000002); + } + /** + * required int32 version = 2; + */ + public int getVersion() { + return version_; + } + /** + * required int32 version = 2; + */ + public Builder setVersion(int value) { + bitField0_ |= 0x00000002; + version_ = value; + onChanged(); + return this; + } + /** + * required int32 version = 2; + */ + public Builder clearVersion() { + bitField0_ = (bitField0_ & ~0x00000002); + version_ = 0; + onChanged(); + return this; + } + + private com.google.protobuf.LazyStringList features_ = com.google.protobuf.LazyStringArrayList.EMPTY; + private void ensureFeaturesIsMutable() { + if (!((bitField0_ & 0x00000004) == 0x00000004)) { + features_ = new com.google.protobuf.LazyStringArrayList(features_); + bitField0_ |= 0x00000004; + } + } + /** + * repeated string features = 3; + */ + public com.google.protobuf.ProtocolStringList + getFeaturesList() { + return features_.getUnmodifiableView(); + } + /** + * repeated string features = 3; + */ + public int getFeaturesCount() { + return features_.size(); + } + /** + * repeated string features = 3; + */ + public java.lang.String getFeatures(int index) { + return features_.get(index); + } + /** + * repeated string features = 3; + */ + public com.google.protobuf.ByteString + getFeaturesBytes(int index) { + return features_.getByteString(index); + } + /** + * repeated string features = 3; + */ + public Builder setFeatures( + int index, java.lang.String value) { + if (value == null) { + throw new NullPointerException(); + } + ensureFeaturesIsMutable(); + features_.set(index, value); + onChanged(); + return this; + } + /** + * repeated string features = 3; + */ + public Builder addFeatures( + java.lang.String value) { + if (value == null) { + throw new NullPointerException(); + } + ensureFeaturesIsMutable(); + features_.add(value); + onChanged(); + return this; + } + /** + * repeated string features = 3; + */ + public Builder addAllFeatures( + java.lang.Iterable values) { + ensureFeaturesIsMutable(); + com.google.protobuf.AbstractMessageLite.Builder.addAll( + values, features_); + onChanged(); + return this; + } + /** + * repeated string features = 3; + */ + public Builder clearFeatures() { + features_ = com.google.protobuf.LazyStringArrayList.EMPTY; + bitField0_ = (bitField0_ & ~0x00000004); + onChanged(); + return this; + } + /** + * repeated string features = 3; + */ + public Builder addFeaturesBytes( + com.google.protobuf.ByteString value) { + if (value == null) { + throw new NullPointerException(); + } + ensureFeaturesIsMutable(); + features_.add(value); + onChanged(); + return this; + } + + // @@protoc_insertion_point(builder_scope:chaintool.car.abi.CompatibilityHeader) + } + + // @@protoc_insertion_point(class_scope:chaintool.car.abi.CompatibilityHeader) + private static final chaintool.car.abi.Car.CompatibilityHeader DEFAULT_INSTANCE; + static { + DEFAULT_INSTANCE = new chaintool.car.abi.Car.CompatibilityHeader(); + } + + public static chaintool.car.abi.Car.CompatibilityHeader getDefaultInstance() { + return DEFAULT_INSTANCE; + } + + @java.lang.Deprecated public static final com.google.protobuf.Parser + PARSER = new com.google.protobuf.AbstractParser() { + public CompatibilityHeader parsePartialFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + try { + return new CompatibilityHeader(input, extensionRegistry); + } catch (RuntimeException e) { + if (e.getCause() instanceof + com.google.protobuf.InvalidProtocolBufferException) { + throw (com.google.protobuf.InvalidProtocolBufferException) + e.getCause(); + } + throw e; + } + } + }; + + public static com.google.protobuf.Parser parser() { + return PARSER; + } + + @java.lang.Override + public com.google.protobuf.Parser getParserForType() { + return PARSER; + } + + public chaintool.car.abi.Car.CompatibilityHeader getDefaultInstanceForType() { + return DEFAULT_INSTANCE; + } + + } + + public interface ArchiveOrBuilder extends + // @@protoc_insertion_point(interface_extends:chaintool.car.abi.Archive) + com.google.protobuf.MessageOrBuilder { + + /** + * optional .chaintool.car.abi.Archive.Signature signature = 1; + */ + boolean hasSignature(); + /** + * optional .chaintool.car.abi.Archive.Signature signature = 1; + */ + chaintool.car.abi.Car.Archive.Signature getSignature(); + /** + * optional .chaintool.car.abi.Archive.Signature signature = 1; + */ + chaintool.car.abi.Car.Archive.SignatureOrBuilder getSignatureOrBuilder(); + + /** + * optional bytes payload = 2; + */ + boolean hasPayload(); + /** + * optional bytes payload = 2; + */ + com.google.protobuf.ByteString getPayload(); + } + /** + * Protobuf type {@code chaintool.car.abi.Archive} + */ + public static final class Archive extends + com.google.protobuf.GeneratedMessage implements + // @@protoc_insertion_point(message_implements:chaintool.car.abi.Archive) + ArchiveOrBuilder { + // Use Archive.newBuilder() to construct. + private Archive(com.google.protobuf.GeneratedMessage.Builder builder) { + super(builder); + } + private Archive() { + payload_ = com.google.protobuf.ByteString.EMPTY; + } + + @java.lang.Override + public final com.google.protobuf.UnknownFieldSet + getUnknownFields() { + return this.unknownFields; + } + private Archive( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) { + this(); + int mutable_bitField0_ = 0; + com.google.protobuf.UnknownFieldSet.Builder unknownFields = + com.google.protobuf.UnknownFieldSet.newBuilder(); + try { + boolean done = false; + while (!done) { + int tag = input.readTag(); + switch (tag) { + case 0: + done = true; + break; + default: { + if (!parseUnknownField(input, unknownFields, + extensionRegistry, tag)) { + done = true; + } + break; + } + case 10: { + chaintool.car.abi.Car.Archive.Signature.Builder subBuilder = null; + if (((bitField0_ & 0x00000001) == 0x00000001)) { + subBuilder = signature_.toBuilder(); + } + signature_ = input.readMessage(chaintool.car.abi.Car.Archive.Signature.parser(), extensionRegistry); + if (subBuilder != null) { + subBuilder.mergeFrom(signature_); + signature_ = subBuilder.buildPartial(); + } + bitField0_ |= 0x00000001; + break; + } + case 18: { + bitField0_ |= 0x00000002; + payload_ = input.readBytes(); + break; + } + } + } + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw new RuntimeException(e.setUnfinishedMessage(this)); + } catch (java.io.IOException e) { + throw new RuntimeException( + new com.google.protobuf.InvalidProtocolBufferException( + e.getMessage()).setUnfinishedMessage(this)); + } finally { + this.unknownFields = unknownFields.build(); + makeExtensionsImmutable(); + } + } + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return chaintool.car.abi.Car.internal_static_chaintool_car_abi_Archive_descriptor; + } + + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return chaintool.car.abi.Car.internal_static_chaintool_car_abi_Archive_fieldAccessorTable + .ensureFieldAccessorsInitialized( + chaintool.car.abi.Car.Archive.class, chaintool.car.abi.Car.Archive.Builder.class); + } + + public interface SignatureOrBuilder extends + // @@protoc_insertion_point(interface_extends:chaintool.car.abi.Archive.Signature) + com.google.protobuf.MessageOrBuilder { + + /** + * optional .chaintool.car.abi.Archive.Signature.Type type = 1; + */ + boolean hasType(); + /** + * optional .chaintool.car.abi.Archive.Signature.Type type = 1; + */ + chaintool.car.abi.Car.Archive.Signature.Type getType(); + + /** + * optional string description = 2; + */ + boolean hasDescription(); + /** + * optional string description = 2; + */ + java.lang.String getDescription(); + /** + * optional string description = 2; + */ + com.google.protobuf.ByteString + getDescriptionBytes(); + + /** + * optional bytes data = 3; + */ + boolean hasData(); + /** + * optional bytes data = 3; + */ + com.google.protobuf.ByteString getData(); + } + /** + * Protobuf type {@code chaintool.car.abi.Archive.Signature} + */ + public static final class Signature extends + com.google.protobuf.GeneratedMessage implements + // @@protoc_insertion_point(message_implements:chaintool.car.abi.Archive.Signature) + SignatureOrBuilder { + // Use Signature.newBuilder() to construct. + private Signature(com.google.protobuf.GeneratedMessage.Builder builder) { + super(builder); + } + private Signature() { + type_ = 1; + description_ = ""; + data_ = com.google.protobuf.ByteString.EMPTY; + } + + @java.lang.Override + public final com.google.protobuf.UnknownFieldSet + getUnknownFields() { + return this.unknownFields; + } + private Signature( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) { + this(); + int mutable_bitField0_ = 0; + com.google.protobuf.UnknownFieldSet.Builder unknownFields = + com.google.protobuf.UnknownFieldSet.newBuilder(); + try { + boolean done = false; + while (!done) { + int tag = input.readTag(); + switch (tag) { + case 0: + done = true; + break; + default: { + if (!parseUnknownField(input, unknownFields, + extensionRegistry, tag)) { + done = true; + } + break; + } + case 8: { + int rawValue = input.readEnum(); + chaintool.car.abi.Car.Archive.Signature.Type value = chaintool.car.abi.Car.Archive.Signature.Type.valueOf(rawValue); + if (value == null) { + unknownFields.mergeVarintField(1, rawValue); + } else { + bitField0_ |= 0x00000001; + type_ = rawValue; + } + break; + } + case 18: { + com.google.protobuf.ByteString bs = input.readBytes(); + bitField0_ |= 0x00000002; + description_ = bs; + break; + } + case 26: { + bitField0_ |= 0x00000004; + data_ = input.readBytes(); + break; + } + } + } + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw new RuntimeException(e.setUnfinishedMessage(this)); + } catch (java.io.IOException e) { + throw new RuntimeException( + new com.google.protobuf.InvalidProtocolBufferException( + e.getMessage()).setUnfinishedMessage(this)); + } finally { + this.unknownFields = unknownFields.build(); + makeExtensionsImmutable(); + } + } + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return chaintool.car.abi.Car.internal_static_chaintool_car_abi_Archive_Signature_descriptor; + } + + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return chaintool.car.abi.Car.internal_static_chaintool_car_abi_Archive_Signature_fieldAccessorTable + .ensureFieldAccessorsInitialized( + chaintool.car.abi.Car.Archive.Signature.class, chaintool.car.abi.Car.Archive.Signature.Builder.class); + } + + /** + * Protobuf enum {@code chaintool.car.abi.Archive.Signature.Type} + */ + public enum Type + implements com.google.protobuf.ProtocolMessageEnum { + /** + * NONE = 1; + */ + NONE(0, 1), + /** + * RSA = 2; + */ + RSA(1, 2), + ; + + /** + * NONE = 1; + */ + public static final int NONE_VALUE = 1; + /** + * RSA = 2; + */ + public static final int RSA_VALUE = 2; + + + public final int getNumber() { + return value; + } + + public static Type valueOf(int value) { + switch (value) { + case 1: return NONE; + case 2: return RSA; + default: return null; + } + } + + public static com.google.protobuf.Internal.EnumLiteMap + internalGetValueMap() { + return internalValueMap; + } + private static final com.google.protobuf.Internal.EnumLiteMap< + Type> internalValueMap = + new com.google.protobuf.Internal.EnumLiteMap() { + public Type findValueByNumber(int number) { + return Type.valueOf(number); + } + }; + + public final com.google.protobuf.Descriptors.EnumValueDescriptor + getValueDescriptor() { + return getDescriptor().getValues().get(index); + } + public final com.google.protobuf.Descriptors.EnumDescriptor + getDescriptorForType() { + return getDescriptor(); + } + public static final com.google.protobuf.Descriptors.EnumDescriptor + getDescriptor() { + return chaintool.car.abi.Car.Archive.Signature.getDescriptor().getEnumTypes().get(0); + } + + private static final Type[] VALUES = values(); + + public static Type valueOf( + com.google.protobuf.Descriptors.EnumValueDescriptor desc) { + if (desc.getType() != getDescriptor()) { + throw new java.lang.IllegalArgumentException( + "EnumValueDescriptor is not for this type."); + } + return VALUES[desc.getIndex()]; + } + + private final int index; + private final int value; + + private Type(int index, int value) { + this.index = index; + this.value = value; + } + + // @@protoc_insertion_point(enum_scope:chaintool.car.abi.Archive.Signature.Type) + } + + private int bitField0_; + public static final int TYPE_FIELD_NUMBER = 1; + private int type_; + /** + * optional .chaintool.car.abi.Archive.Signature.Type type = 1; + */ + public boolean hasType() { + return ((bitField0_ & 0x00000001) == 0x00000001); + } + /** + * optional .chaintool.car.abi.Archive.Signature.Type type = 1; + */ + public chaintool.car.abi.Car.Archive.Signature.Type getType() { + chaintool.car.abi.Car.Archive.Signature.Type result = chaintool.car.abi.Car.Archive.Signature.Type.valueOf(type_); + return result == null ? chaintool.car.abi.Car.Archive.Signature.Type.NONE : result; + } + + public static final int DESCRIPTION_FIELD_NUMBER = 2; + private volatile java.lang.Object description_; + /** + * optional string description = 2; + */ + public boolean hasDescription() { + return ((bitField0_ & 0x00000002) == 0x00000002); + } + /** + * optional string description = 2; + */ + public java.lang.String getDescription() { + java.lang.Object ref = description_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + if (bs.isValidUtf8()) { + description_ = s; + } + return s; + } + } + /** + * optional string description = 2; + */ + public com.google.protobuf.ByteString + getDescriptionBytes() { + java.lang.Object ref = description_; + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + description_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + public static final int DATA_FIELD_NUMBER = 3; + private com.google.protobuf.ByteString data_; + /** + * optional bytes data = 3; + */ + public boolean hasData() { + return ((bitField0_ & 0x00000004) == 0x00000004); + } + /** + * optional bytes data = 3; + */ + public com.google.protobuf.ByteString getData() { + return data_; + } + + private byte memoizedIsInitialized = -1; + public final boolean isInitialized() { + byte isInitialized = memoizedIsInitialized; + if (isInitialized == 1) return true; + if (isInitialized == 0) return false; + + memoizedIsInitialized = 1; + return true; + } + + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + if (((bitField0_ & 0x00000001) == 0x00000001)) { + output.writeEnum(1, type_); + } + if (((bitField0_ & 0x00000002) == 0x00000002)) { + com.google.protobuf.GeneratedMessage.writeString(output, 2, description_); + } + if (((bitField0_ & 0x00000004) == 0x00000004)) { + output.writeBytes(3, data_); + } + unknownFields.writeTo(output); + } + + public int getSerializedSize() { + int size = memoizedSize; + if (size != -1) return size; + + size = 0; + if (((bitField0_ & 0x00000001) == 0x00000001)) { + size += com.google.protobuf.CodedOutputStream + .computeEnumSize(1, type_); + } + if (((bitField0_ & 0x00000002) == 0x00000002)) { + size += com.google.protobuf.GeneratedMessage.computeStringSize(2, description_); + } + if (((bitField0_ & 0x00000004) == 0x00000004)) { + size += com.google.protobuf.CodedOutputStream + .computeBytesSize(3, data_); + } + size += unknownFields.getSerializedSize(); + memoizedSize = size; + return size; + } + + private static final long serialVersionUID = 0L; + public static chaintool.car.abi.Car.Archive.Signature parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static chaintool.car.abi.Car.Archive.Signature parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static chaintool.car.abi.Car.Archive.Signature parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static chaintool.car.abi.Car.Archive.Signature parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static chaintool.car.abi.Car.Archive.Signature parseFrom(java.io.InputStream input) + throws java.io.IOException { + return PARSER.parseFrom(input); + } + public static chaintool.car.abi.Car.Archive.Signature parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return PARSER.parseFrom(input, extensionRegistry); + } + public static chaintool.car.abi.Car.Archive.Signature parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + return PARSER.parseDelimitedFrom(input); + } + public static chaintool.car.abi.Car.Archive.Signature parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return PARSER.parseDelimitedFrom(input, extensionRegistry); + } + public static chaintool.car.abi.Car.Archive.Signature parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return PARSER.parseFrom(input); + } + public static chaintool.car.abi.Car.Archive.Signature parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return PARSER.parseFrom(input, extensionRegistry); + } + + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder() { + return DEFAULT_INSTANCE.toBuilder(); + } + public static Builder newBuilder(chaintool.car.abi.Car.Archive.Signature prototype) { + return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); + } + public Builder toBuilder() { + return this == DEFAULT_INSTANCE + ? new Builder() : new Builder().mergeFrom(this); + } + + @java.lang.Override + protected Builder newBuilderForType( + com.google.protobuf.GeneratedMessage.BuilderParent parent) { + Builder builder = new Builder(parent); + return builder; + } + /** + * Protobuf type {@code chaintool.car.abi.Archive.Signature} + */ + public static final class Builder extends + com.google.protobuf.GeneratedMessage.Builder implements + // @@protoc_insertion_point(builder_implements:chaintool.car.abi.Archive.Signature) + chaintool.car.abi.Car.Archive.SignatureOrBuilder { + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return chaintool.car.abi.Car.internal_static_chaintool_car_abi_Archive_Signature_descriptor; + } + + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return chaintool.car.abi.Car.internal_static_chaintool_car_abi_Archive_Signature_fieldAccessorTable + .ensureFieldAccessorsInitialized( + chaintool.car.abi.Car.Archive.Signature.class, chaintool.car.abi.Car.Archive.Signature.Builder.class); + } + + // Construct using chaintool.car.abi.Car.Archive.Signature.newBuilder() + private Builder() { + maybeForceBuilderInitialization(); + } + + private Builder( + com.google.protobuf.GeneratedMessage.BuilderParent parent) { + super(parent); + maybeForceBuilderInitialization(); + } + private void maybeForceBuilderInitialization() { + if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) { + } + } + public Builder clear() { + super.clear(); + type_ = 1; + bitField0_ = (bitField0_ & ~0x00000001); + description_ = ""; + bitField0_ = (bitField0_ & ~0x00000002); + data_ = com.google.protobuf.ByteString.EMPTY; + bitField0_ = (bitField0_ & ~0x00000004); + return this; + } + + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return chaintool.car.abi.Car.internal_static_chaintool_car_abi_Archive_Signature_descriptor; + } + + public chaintool.car.abi.Car.Archive.Signature getDefaultInstanceForType() { + return chaintool.car.abi.Car.Archive.Signature.getDefaultInstance(); + } + + public chaintool.car.abi.Car.Archive.Signature build() { + chaintool.car.abi.Car.Archive.Signature result = buildPartial(); + if (!result.isInitialized()) { + throw newUninitializedMessageException(result); + } + return result; + } + + public chaintool.car.abi.Car.Archive.Signature buildPartial() { + chaintool.car.abi.Car.Archive.Signature result = new chaintool.car.abi.Car.Archive.Signature(this); + int from_bitField0_ = bitField0_; + int to_bitField0_ = 0; + if (((from_bitField0_ & 0x00000001) == 0x00000001)) { + to_bitField0_ |= 0x00000001; + } + result.type_ = type_; + if (((from_bitField0_ & 0x00000002) == 0x00000002)) { + to_bitField0_ |= 0x00000002; + } + result.description_ = description_; + if (((from_bitField0_ & 0x00000004) == 0x00000004)) { + to_bitField0_ |= 0x00000004; + } + result.data_ = data_; + result.bitField0_ = to_bitField0_; + onBuilt(); + return result; + } + + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof chaintool.car.abi.Car.Archive.Signature) { + return mergeFrom((chaintool.car.abi.Car.Archive.Signature)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(chaintool.car.abi.Car.Archive.Signature other) { + if (other == chaintool.car.abi.Car.Archive.Signature.getDefaultInstance()) return this; + if (other.hasType()) { + setType(other.getType()); + } + if (other.hasDescription()) { + bitField0_ |= 0x00000002; + description_ = other.description_; + onChanged(); + } + if (other.hasData()) { + setData(other.getData()); + } + this.mergeUnknownFields(other.unknownFields); + onChanged(); + return this; + } + + public final boolean isInitialized() { + return true; + } + + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + chaintool.car.abi.Car.Archive.Signature parsedMessage = null; + try { + parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry); + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + parsedMessage = (chaintool.car.abi.Car.Archive.Signature) e.getUnfinishedMessage(); + throw e; + } finally { + if (parsedMessage != null) { + mergeFrom(parsedMessage); + } + } + return this; + } + private int bitField0_; + + private int type_ = 1; + /** + * optional .chaintool.car.abi.Archive.Signature.Type type = 1; + */ + public boolean hasType() { + return ((bitField0_ & 0x00000001) == 0x00000001); + } + /** + * optional .chaintool.car.abi.Archive.Signature.Type type = 1; + */ + public chaintool.car.abi.Car.Archive.Signature.Type getType() { + chaintool.car.abi.Car.Archive.Signature.Type result = chaintool.car.abi.Car.Archive.Signature.Type.valueOf(type_); + return result == null ? chaintool.car.abi.Car.Archive.Signature.Type.NONE : result; + } + /** + * optional .chaintool.car.abi.Archive.Signature.Type type = 1; + */ + public Builder setType(chaintool.car.abi.Car.Archive.Signature.Type value) { + if (value == null) { + throw new NullPointerException(); + } + bitField0_ |= 0x00000001; + type_ = value.getNumber(); + onChanged(); + return this; + } + /** + * optional .chaintool.car.abi.Archive.Signature.Type type = 1; + */ + public Builder clearType() { + bitField0_ = (bitField0_ & ~0x00000001); + type_ = 1; + onChanged(); + return this; + } + + private java.lang.Object description_ = ""; + /** + * optional string description = 2; + */ + public boolean hasDescription() { + return ((bitField0_ & 0x00000002) == 0x00000002); + } + /** + * optional string description = 2; + */ + public java.lang.String getDescription() { + java.lang.Object ref = description_; + if (!(ref instanceof java.lang.String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + if (bs.isValidUtf8()) { + description_ = s; + } + return s; + } else { + return (java.lang.String) ref; + } + } + /** + * optional string description = 2; + */ + public com.google.protobuf.ByteString + getDescriptionBytes() { + java.lang.Object ref = description_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + description_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + * optional string description = 2; + */ + public Builder setDescription( + java.lang.String value) { + if (value == null) { + throw new NullPointerException(); + } + bitField0_ |= 0x00000002; + description_ = value; + onChanged(); + return this; + } + /** + * optional string description = 2; + */ + public Builder clearDescription() { + bitField0_ = (bitField0_ & ~0x00000002); + description_ = getDefaultInstance().getDescription(); + onChanged(); + return this; + } + /** + * optional string description = 2; + */ + public Builder setDescriptionBytes( + com.google.protobuf.ByteString value) { + if (value == null) { + throw new NullPointerException(); + } + bitField0_ |= 0x00000002; + description_ = value; + onChanged(); + return this; + } + + private com.google.protobuf.ByteString data_ = com.google.protobuf.ByteString.EMPTY; + /** + * optional bytes data = 3; + */ + public boolean hasData() { + return ((bitField0_ & 0x00000004) == 0x00000004); + } + /** + * optional bytes data = 3; + */ + public com.google.protobuf.ByteString getData() { + return data_; + } + /** + * optional bytes data = 3; + */ + public Builder setData(com.google.protobuf.ByteString value) { + if (value == null) { + throw new NullPointerException(); + } + bitField0_ |= 0x00000004; + data_ = value; + onChanged(); + return this; + } + /** + * optional bytes data = 3; + */ + public Builder clearData() { + bitField0_ = (bitField0_ & ~0x00000004); + data_ = getDefaultInstance().getData(); + onChanged(); + return this; + } + + // @@protoc_insertion_point(builder_scope:chaintool.car.abi.Archive.Signature) + } + + // @@protoc_insertion_point(class_scope:chaintool.car.abi.Archive.Signature) + private static final chaintool.car.abi.Car.Archive.Signature DEFAULT_INSTANCE; + static { + DEFAULT_INSTANCE = new chaintool.car.abi.Car.Archive.Signature(); + } + + public static chaintool.car.abi.Car.Archive.Signature getDefaultInstance() { + return DEFAULT_INSTANCE; + } + + @java.lang.Deprecated public static final com.google.protobuf.Parser + PARSER = new com.google.protobuf.AbstractParser() { + public Signature parsePartialFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + try { + return new Signature(input, extensionRegistry); + } catch (RuntimeException e) { + if (e.getCause() instanceof + com.google.protobuf.InvalidProtocolBufferException) { + throw (com.google.protobuf.InvalidProtocolBufferException) + e.getCause(); + } + throw e; + } + } + }; + + public static com.google.protobuf.Parser parser() { + return PARSER; + } + + @java.lang.Override + public com.google.protobuf.Parser getParserForType() { + return PARSER; + } + + public chaintool.car.abi.Car.Archive.Signature getDefaultInstanceForType() { + return DEFAULT_INSTANCE; + } + + } + + public interface PayloadOrBuilder extends + // @@protoc_insertion_point(interface_extends:chaintool.car.abi.Archive.Payload) + com.google.protobuf.MessageOrBuilder { + + /** + * optional .chaintool.car.abi.Archive.Payload.Compression compression = 1; + */ + boolean hasCompression(); + /** + * optional .chaintool.car.abi.Archive.Payload.Compression compression = 1; + */ + chaintool.car.abi.Car.Archive.Payload.Compression getCompression(); + /** + * optional .chaintool.car.abi.Archive.Payload.Compression compression = 1; + */ + chaintool.car.abi.Car.Archive.Payload.CompressionOrBuilder getCompressionOrBuilder(); + + /** + * repeated .chaintool.car.abi.Archive.Payload.Entries entries = 16; + */ + java.util.List + getEntriesList(); + /** + * repeated .chaintool.car.abi.Archive.Payload.Entries entries = 16; + */ + chaintool.car.abi.Car.Archive.Payload.Entries getEntries(int index); + /** + * repeated .chaintool.car.abi.Archive.Payload.Entries entries = 16; + */ + int getEntriesCount(); + /** + * repeated .chaintool.car.abi.Archive.Payload.Entries entries = 16; + */ + java.util.List + getEntriesOrBuilderList(); + /** + * repeated .chaintool.car.abi.Archive.Payload.Entries entries = 16; + */ + chaintool.car.abi.Car.Archive.Payload.EntriesOrBuilder getEntriesOrBuilder( + int index); + } + /** + * Protobuf type {@code chaintool.car.abi.Archive.Payload} + */ + public static final class Payload extends + com.google.protobuf.GeneratedMessage implements + // @@protoc_insertion_point(message_implements:chaintool.car.abi.Archive.Payload) + PayloadOrBuilder { + // Use Payload.newBuilder() to construct. + private Payload(com.google.protobuf.GeneratedMessage.Builder builder) { + super(builder); + } + private Payload() { + entries_ = java.util.Collections.emptyList(); + } + + @java.lang.Override + public final com.google.protobuf.UnknownFieldSet + getUnknownFields() { + return this.unknownFields; + } + private Payload( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) { + this(); + int mutable_bitField0_ = 0; + com.google.protobuf.UnknownFieldSet.Builder unknownFields = + com.google.protobuf.UnknownFieldSet.newBuilder(); + try { + boolean done = false; + while (!done) { + int tag = input.readTag(); + switch (tag) { + case 0: + done = true; + break; + default: { + if (!parseUnknownField(input, unknownFields, + extensionRegistry, tag)) { + done = true; + } + break; + } + case 10: { + chaintool.car.abi.Car.Archive.Payload.Compression.Builder subBuilder = null; + if (((bitField0_ & 0x00000001) == 0x00000001)) { + subBuilder = compression_.toBuilder(); + } + compression_ = input.readMessage(chaintool.car.abi.Car.Archive.Payload.Compression.parser(), extensionRegistry); + if (subBuilder != null) { + subBuilder.mergeFrom(compression_); + compression_ = subBuilder.buildPartial(); + } + bitField0_ |= 0x00000001; + break; + } + case 130: { + if (!((mutable_bitField0_ & 0x00000002) == 0x00000002)) { + entries_ = new java.util.ArrayList(); + mutable_bitField0_ |= 0x00000002; + } + entries_.add(input.readMessage(chaintool.car.abi.Car.Archive.Payload.Entries.parser(), extensionRegistry)); + break; + } + } + } + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw new RuntimeException(e.setUnfinishedMessage(this)); + } catch (java.io.IOException e) { + throw new RuntimeException( + new com.google.protobuf.InvalidProtocolBufferException( + e.getMessage()).setUnfinishedMessage(this)); + } finally { + if (((mutable_bitField0_ & 0x00000002) == 0x00000002)) { + entries_ = java.util.Collections.unmodifiableList(entries_); + } + this.unknownFields = unknownFields.build(); + makeExtensionsImmutable(); + } + } + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return chaintool.car.abi.Car.internal_static_chaintool_car_abi_Archive_Payload_descriptor; + } + + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return chaintool.car.abi.Car.internal_static_chaintool_car_abi_Archive_Payload_fieldAccessorTable + .ensureFieldAccessorsInitialized( + chaintool.car.abi.Car.Archive.Payload.class, chaintool.car.abi.Car.Archive.Payload.Builder.class); + } + + public interface CompressionOrBuilder extends + // @@protoc_insertion_point(interface_extends:chaintool.car.abi.Archive.Payload.Compression) + com.google.protobuf.MessageOrBuilder { + + /** + * optional .chaintool.car.abi.Archive.Payload.Compression.Type type = 1 [default = NONE]; + */ + boolean hasType(); + /** + * optional .chaintool.car.abi.Archive.Payload.Compression.Type type = 1 [default = NONE]; + */ + chaintool.car.abi.Car.Archive.Payload.Compression.Type getType(); + + /** + * optional string description = 2; + */ + boolean hasDescription(); + /** + * optional string description = 2; + */ + java.lang.String getDescription(); + /** + * optional string description = 2; + */ + com.google.protobuf.ByteString + getDescriptionBytes(); + } + /** + * Protobuf type {@code chaintool.car.abi.Archive.Payload.Compression} + */ + public static final class Compression extends + com.google.protobuf.GeneratedMessage implements + // @@protoc_insertion_point(message_implements:chaintool.car.abi.Archive.Payload.Compression) + CompressionOrBuilder { + // Use Compression.newBuilder() to construct. + private Compression(com.google.protobuf.GeneratedMessage.Builder builder) { + super(builder); + } + private Compression() { + type_ = 1; + description_ = ""; + } + + @java.lang.Override + public final com.google.protobuf.UnknownFieldSet + getUnknownFields() { + return this.unknownFields; + } + private Compression( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) { + this(); + int mutable_bitField0_ = 0; + com.google.protobuf.UnknownFieldSet.Builder unknownFields = + com.google.protobuf.UnknownFieldSet.newBuilder(); + try { + boolean done = false; + while (!done) { + int tag = input.readTag(); + switch (tag) { + case 0: + done = true; + break; + default: { + if (!parseUnknownField(input, unknownFields, + extensionRegistry, tag)) { + done = true; + } + break; + } + case 8: { + int rawValue = input.readEnum(); + chaintool.car.abi.Car.Archive.Payload.Compression.Type value = chaintool.car.abi.Car.Archive.Payload.Compression.Type.valueOf(rawValue); + if (value == null) { + unknownFields.mergeVarintField(1, rawValue); + } else { + bitField0_ |= 0x00000001; + type_ = rawValue; + } + break; + } + case 18: { + com.google.protobuf.ByteString bs = input.readBytes(); + bitField0_ |= 0x00000002; + description_ = bs; + break; + } + } + } + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw new RuntimeException(e.setUnfinishedMessage(this)); + } catch (java.io.IOException e) { + throw new RuntimeException( + new com.google.protobuf.InvalidProtocolBufferException( + e.getMessage()).setUnfinishedMessage(this)); + } finally { + this.unknownFields = unknownFields.build(); + makeExtensionsImmutable(); + } + } + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return chaintool.car.abi.Car.internal_static_chaintool_car_abi_Archive_Payload_Compression_descriptor; + } + + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return chaintool.car.abi.Car.internal_static_chaintool_car_abi_Archive_Payload_Compression_fieldAccessorTable + .ensureFieldAccessorsInitialized( + chaintool.car.abi.Car.Archive.Payload.Compression.class, chaintool.car.abi.Car.Archive.Payload.Compression.Builder.class); + } + + /** + * Protobuf enum {@code chaintool.car.abi.Archive.Payload.Compression.Type} + */ + public enum Type + implements com.google.protobuf.ProtocolMessageEnum { + /** + * NONE = 1; + */ + NONE(0, 1), + /** + * GZIP = 2; + */ + GZIP(1, 2), + /** + * LZMA = 3; + */ + LZMA(2, 3), + /** + * BZIP2 = 4; + */ + BZIP2(3, 4), + /** + * XZ = 5; + */ + XZ(4, 5), + ; + + /** + * NONE = 1; + */ + public static final int NONE_VALUE = 1; + /** + * GZIP = 2; + */ + public static final int GZIP_VALUE = 2; + /** + * LZMA = 3; + */ + public static final int LZMA_VALUE = 3; + /** + * BZIP2 = 4; + */ + public static final int BZIP2_VALUE = 4; + /** + * XZ = 5; + */ + public static final int XZ_VALUE = 5; + + + public final int getNumber() { + return value; + } + + public static Type valueOf(int value) { + switch (value) { + case 1: return NONE; + case 2: return GZIP; + case 3: return LZMA; + case 4: return BZIP2; + case 5: return XZ; + default: return null; + } + } + + public static com.google.protobuf.Internal.EnumLiteMap + internalGetValueMap() { + return internalValueMap; + } + private static final com.google.protobuf.Internal.EnumLiteMap< + Type> internalValueMap = + new com.google.protobuf.Internal.EnumLiteMap() { + public Type findValueByNumber(int number) { + return Type.valueOf(number); + } + }; + + public final com.google.protobuf.Descriptors.EnumValueDescriptor + getValueDescriptor() { + return getDescriptor().getValues().get(index); + } + public final com.google.protobuf.Descriptors.EnumDescriptor + getDescriptorForType() { + return getDescriptor(); + } + public static final com.google.protobuf.Descriptors.EnumDescriptor + getDescriptor() { + return chaintool.car.abi.Car.Archive.Payload.Compression.getDescriptor().getEnumTypes().get(0); + } + + private static final Type[] VALUES = values(); + + public static Type valueOf( + com.google.protobuf.Descriptors.EnumValueDescriptor desc) { + if (desc.getType() != getDescriptor()) { + throw new java.lang.IllegalArgumentException( + "EnumValueDescriptor is not for this type."); + } + return VALUES[desc.getIndex()]; + } + + private final int index; + private final int value; + + private Type(int index, int value) { + this.index = index; + this.value = value; + } + + // @@protoc_insertion_point(enum_scope:chaintool.car.abi.Archive.Payload.Compression.Type) + } + + private int bitField0_; + public static final int TYPE_FIELD_NUMBER = 1; + private int type_; + /** + * optional .chaintool.car.abi.Archive.Payload.Compression.Type type = 1 [default = NONE]; + */ + public boolean hasType() { + return ((bitField0_ & 0x00000001) == 0x00000001); + } + /** + * optional .chaintool.car.abi.Archive.Payload.Compression.Type type = 1 [default = NONE]; + */ + public chaintool.car.abi.Car.Archive.Payload.Compression.Type getType() { + chaintool.car.abi.Car.Archive.Payload.Compression.Type result = chaintool.car.abi.Car.Archive.Payload.Compression.Type.valueOf(type_); + return result == null ? chaintool.car.abi.Car.Archive.Payload.Compression.Type.NONE : result; + } + + public static final int DESCRIPTION_FIELD_NUMBER = 2; + private volatile java.lang.Object description_; + /** + * optional string description = 2; + */ + public boolean hasDescription() { + return ((bitField0_ & 0x00000002) == 0x00000002); + } + /** + * optional string description = 2; + */ + public java.lang.String getDescription() { + java.lang.Object ref = description_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + if (bs.isValidUtf8()) { + description_ = s; + } + return s; + } + } + /** + * optional string description = 2; + */ + public com.google.protobuf.ByteString + getDescriptionBytes() { + java.lang.Object ref = description_; + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + description_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + private byte memoizedIsInitialized = -1; + public final boolean isInitialized() { + byte isInitialized = memoizedIsInitialized; + if (isInitialized == 1) return true; + if (isInitialized == 0) return false; + + memoizedIsInitialized = 1; + return true; + } + + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + if (((bitField0_ & 0x00000001) == 0x00000001)) { + output.writeEnum(1, type_); + } + if (((bitField0_ & 0x00000002) == 0x00000002)) { + com.google.protobuf.GeneratedMessage.writeString(output, 2, description_); + } + unknownFields.writeTo(output); + } + + public int getSerializedSize() { + int size = memoizedSize; + if (size != -1) return size; + + size = 0; + if (((bitField0_ & 0x00000001) == 0x00000001)) { + size += com.google.protobuf.CodedOutputStream + .computeEnumSize(1, type_); + } + if (((bitField0_ & 0x00000002) == 0x00000002)) { + size += com.google.protobuf.GeneratedMessage.computeStringSize(2, description_); + } + size += unknownFields.getSerializedSize(); + memoizedSize = size; + return size; + } + + private static final long serialVersionUID = 0L; + public static chaintool.car.abi.Car.Archive.Payload.Compression parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static chaintool.car.abi.Car.Archive.Payload.Compression parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static chaintool.car.abi.Car.Archive.Payload.Compression parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static chaintool.car.abi.Car.Archive.Payload.Compression parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static chaintool.car.abi.Car.Archive.Payload.Compression parseFrom(java.io.InputStream input) + throws java.io.IOException { + return PARSER.parseFrom(input); + } + public static chaintool.car.abi.Car.Archive.Payload.Compression parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return PARSER.parseFrom(input, extensionRegistry); + } + public static chaintool.car.abi.Car.Archive.Payload.Compression parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + return PARSER.parseDelimitedFrom(input); + } + public static chaintool.car.abi.Car.Archive.Payload.Compression parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return PARSER.parseDelimitedFrom(input, extensionRegistry); + } + public static chaintool.car.abi.Car.Archive.Payload.Compression parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return PARSER.parseFrom(input); + } + public static chaintool.car.abi.Car.Archive.Payload.Compression parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return PARSER.parseFrom(input, extensionRegistry); + } + + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder() { + return DEFAULT_INSTANCE.toBuilder(); + } + public static Builder newBuilder(chaintool.car.abi.Car.Archive.Payload.Compression prototype) { + return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); + } + public Builder toBuilder() { + return this == DEFAULT_INSTANCE + ? new Builder() : new Builder().mergeFrom(this); + } + + @java.lang.Override + protected Builder newBuilderForType( + com.google.protobuf.GeneratedMessage.BuilderParent parent) { + Builder builder = new Builder(parent); + return builder; + } + /** + * Protobuf type {@code chaintool.car.abi.Archive.Payload.Compression} + */ + public static final class Builder extends + com.google.protobuf.GeneratedMessage.Builder implements + // @@protoc_insertion_point(builder_implements:chaintool.car.abi.Archive.Payload.Compression) + chaintool.car.abi.Car.Archive.Payload.CompressionOrBuilder { + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return chaintool.car.abi.Car.internal_static_chaintool_car_abi_Archive_Payload_Compression_descriptor; + } + + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return chaintool.car.abi.Car.internal_static_chaintool_car_abi_Archive_Payload_Compression_fieldAccessorTable + .ensureFieldAccessorsInitialized( + chaintool.car.abi.Car.Archive.Payload.Compression.class, chaintool.car.abi.Car.Archive.Payload.Compression.Builder.class); + } + + // Construct using chaintool.car.abi.Car.Archive.Payload.Compression.newBuilder() + private Builder() { + maybeForceBuilderInitialization(); + } + + private Builder( + com.google.protobuf.GeneratedMessage.BuilderParent parent) { + super(parent); + maybeForceBuilderInitialization(); + } + private void maybeForceBuilderInitialization() { + if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) { + } + } + public Builder clear() { + super.clear(); + type_ = 1; + bitField0_ = (bitField0_ & ~0x00000001); + description_ = ""; + bitField0_ = (bitField0_ & ~0x00000002); + return this; + } + + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return chaintool.car.abi.Car.internal_static_chaintool_car_abi_Archive_Payload_Compression_descriptor; + } + + public chaintool.car.abi.Car.Archive.Payload.Compression getDefaultInstanceForType() { + return chaintool.car.abi.Car.Archive.Payload.Compression.getDefaultInstance(); + } + + public chaintool.car.abi.Car.Archive.Payload.Compression build() { + chaintool.car.abi.Car.Archive.Payload.Compression result = buildPartial(); + if (!result.isInitialized()) { + throw newUninitializedMessageException(result); + } + return result; + } + + public chaintool.car.abi.Car.Archive.Payload.Compression buildPartial() { + chaintool.car.abi.Car.Archive.Payload.Compression result = new chaintool.car.abi.Car.Archive.Payload.Compression(this); + int from_bitField0_ = bitField0_; + int to_bitField0_ = 0; + if (((from_bitField0_ & 0x00000001) == 0x00000001)) { + to_bitField0_ |= 0x00000001; + } + result.type_ = type_; + if (((from_bitField0_ & 0x00000002) == 0x00000002)) { + to_bitField0_ |= 0x00000002; + } + result.description_ = description_; + result.bitField0_ = to_bitField0_; + onBuilt(); + return result; + } + + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof chaintool.car.abi.Car.Archive.Payload.Compression) { + return mergeFrom((chaintool.car.abi.Car.Archive.Payload.Compression)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(chaintool.car.abi.Car.Archive.Payload.Compression other) { + if (other == chaintool.car.abi.Car.Archive.Payload.Compression.getDefaultInstance()) return this; + if (other.hasType()) { + setType(other.getType()); + } + if (other.hasDescription()) { + bitField0_ |= 0x00000002; + description_ = other.description_; + onChanged(); + } + this.mergeUnknownFields(other.unknownFields); + onChanged(); + return this; + } + + public final boolean isInitialized() { + return true; + } + + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + chaintool.car.abi.Car.Archive.Payload.Compression parsedMessage = null; + try { + parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry); + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + parsedMessage = (chaintool.car.abi.Car.Archive.Payload.Compression) e.getUnfinishedMessage(); + throw e; + } finally { + if (parsedMessage != null) { + mergeFrom(parsedMessage); + } + } + return this; + } + private int bitField0_; + + private int type_ = 1; + /** + * optional .chaintool.car.abi.Archive.Payload.Compression.Type type = 1 [default = NONE]; + */ + public boolean hasType() { + return ((bitField0_ & 0x00000001) == 0x00000001); + } + /** + * optional .chaintool.car.abi.Archive.Payload.Compression.Type type = 1 [default = NONE]; + */ + public chaintool.car.abi.Car.Archive.Payload.Compression.Type getType() { + chaintool.car.abi.Car.Archive.Payload.Compression.Type result = chaintool.car.abi.Car.Archive.Payload.Compression.Type.valueOf(type_); + return result == null ? chaintool.car.abi.Car.Archive.Payload.Compression.Type.NONE : result; + } + /** + * optional .chaintool.car.abi.Archive.Payload.Compression.Type type = 1 [default = NONE]; + */ + public Builder setType(chaintool.car.abi.Car.Archive.Payload.Compression.Type value) { + if (value == null) { + throw new NullPointerException(); + } + bitField0_ |= 0x00000001; + type_ = value.getNumber(); + onChanged(); + return this; + } + /** + * optional .chaintool.car.abi.Archive.Payload.Compression.Type type = 1 [default = NONE]; + */ + public Builder clearType() { + bitField0_ = (bitField0_ & ~0x00000001); + type_ = 1; + onChanged(); + return this; + } + + private java.lang.Object description_ = ""; + /** + * optional string description = 2; + */ + public boolean hasDescription() { + return ((bitField0_ & 0x00000002) == 0x00000002); + } + /** + * optional string description = 2; + */ + public java.lang.String getDescription() { + java.lang.Object ref = description_; + if (!(ref instanceof java.lang.String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + if (bs.isValidUtf8()) { + description_ = s; + } + return s; + } else { + return (java.lang.String) ref; + } + } + /** + * optional string description = 2; + */ + public com.google.protobuf.ByteString + getDescriptionBytes() { + java.lang.Object ref = description_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + description_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + * optional string description = 2; + */ + public Builder setDescription( + java.lang.String value) { + if (value == null) { + throw new NullPointerException(); + } + bitField0_ |= 0x00000002; + description_ = value; + onChanged(); + return this; + } + /** + * optional string description = 2; + */ + public Builder clearDescription() { + bitField0_ = (bitField0_ & ~0x00000002); + description_ = getDefaultInstance().getDescription(); + onChanged(); + return this; + } + /** + * optional string description = 2; + */ + public Builder setDescriptionBytes( + com.google.protobuf.ByteString value) { + if (value == null) { + throw new NullPointerException(); + } + bitField0_ |= 0x00000002; + description_ = value; + onChanged(); + return this; + } + + // @@protoc_insertion_point(builder_scope:chaintool.car.abi.Archive.Payload.Compression) + } + + // @@protoc_insertion_point(class_scope:chaintool.car.abi.Archive.Payload.Compression) + private static final chaintool.car.abi.Car.Archive.Payload.Compression DEFAULT_INSTANCE; + static { + DEFAULT_INSTANCE = new chaintool.car.abi.Car.Archive.Payload.Compression(); + } + + public static chaintool.car.abi.Car.Archive.Payload.Compression getDefaultInstance() { + return DEFAULT_INSTANCE; + } + + @java.lang.Deprecated public static final com.google.protobuf.Parser + PARSER = new com.google.protobuf.AbstractParser() { + public Compression parsePartialFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + try { + return new Compression(input, extensionRegistry); + } catch (RuntimeException e) { + if (e.getCause() instanceof + com.google.protobuf.InvalidProtocolBufferException) { + throw (com.google.protobuf.InvalidProtocolBufferException) + e.getCause(); + } + throw e; + } + } + }; + + public static com.google.protobuf.Parser parser() { + return PARSER; + } + + @java.lang.Override + public com.google.protobuf.Parser getParserForType() { + return PARSER; + } + + public chaintool.car.abi.Car.Archive.Payload.Compression getDefaultInstanceForType() { + return DEFAULT_INSTANCE; + } + + } + + public interface EntriesOrBuilder extends + // @@protoc_insertion_point(interface_extends:chaintool.car.abi.Archive.Payload.Entries) + com.google.protobuf.MessageOrBuilder { + + /** + * optional string path = 1; + */ + boolean hasPath(); + /** + * optional string path = 1; + */ + java.lang.String getPath(); + /** + * optional string path = 1; + */ + com.google.protobuf.ByteString + getPathBytes(); + + /** + * optional uint64 size = 2; + */ + boolean hasSize(); + /** + * optional uint64 size = 2; + */ + long getSize(); + + /** + * optional string sha1 = 3; + */ + boolean hasSha1(); + /** + * optional string sha1 = 3; + */ + java.lang.String getSha1(); + /** + * optional string sha1 = 3; + */ + com.google.protobuf.ByteString + getSha1Bytes(); + + /** + * optional bytes data = 16; + */ + boolean hasData(); + /** + * optional bytes data = 16; + */ + com.google.protobuf.ByteString getData(); + } + /** + * Protobuf type {@code chaintool.car.abi.Archive.Payload.Entries} + */ + public static final class Entries extends + com.google.protobuf.GeneratedMessage implements + // @@protoc_insertion_point(message_implements:chaintool.car.abi.Archive.Payload.Entries) + EntriesOrBuilder { + // Use Entries.newBuilder() to construct. + private Entries(com.google.protobuf.GeneratedMessage.Builder builder) { + super(builder); + } + private Entries() { + path_ = ""; + size_ = 0L; + sha1_ = ""; + data_ = com.google.protobuf.ByteString.EMPTY; + } + + @java.lang.Override + public final com.google.protobuf.UnknownFieldSet + getUnknownFields() { + return this.unknownFields; + } + private Entries( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) { + this(); + int mutable_bitField0_ = 0; + com.google.protobuf.UnknownFieldSet.Builder unknownFields = + com.google.protobuf.UnknownFieldSet.newBuilder(); + try { + boolean done = false; + while (!done) { + int tag = input.readTag(); + switch (tag) { + case 0: + done = true; + break; + default: { + if (!parseUnknownField(input, unknownFields, + extensionRegistry, tag)) { + done = true; + } + break; + } + case 10: { + com.google.protobuf.ByteString bs = input.readBytes(); + bitField0_ |= 0x00000001; + path_ = bs; + break; + } + case 16: { + bitField0_ |= 0x00000002; + size_ = input.readUInt64(); + break; + } + case 26: { + com.google.protobuf.ByteString bs = input.readBytes(); + bitField0_ |= 0x00000004; + sha1_ = bs; + break; + } + case 130: { + bitField0_ |= 0x00000008; + data_ = input.readBytes(); + break; + } + } + } + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw new RuntimeException(e.setUnfinishedMessage(this)); + } catch (java.io.IOException e) { + throw new RuntimeException( + new com.google.protobuf.InvalidProtocolBufferException( + e.getMessage()).setUnfinishedMessage(this)); + } finally { + this.unknownFields = unknownFields.build(); + makeExtensionsImmutable(); + } + } + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return chaintool.car.abi.Car.internal_static_chaintool_car_abi_Archive_Payload_Entries_descriptor; + } + + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return chaintool.car.abi.Car.internal_static_chaintool_car_abi_Archive_Payload_Entries_fieldAccessorTable + .ensureFieldAccessorsInitialized( + chaintool.car.abi.Car.Archive.Payload.Entries.class, chaintool.car.abi.Car.Archive.Payload.Entries.Builder.class); + } + + private int bitField0_; + public static final int PATH_FIELD_NUMBER = 1; + private volatile java.lang.Object path_; + /** + * optional string path = 1; + */ + public boolean hasPath() { + return ((bitField0_ & 0x00000001) == 0x00000001); + } + /** + * optional string path = 1; + */ + public java.lang.String getPath() { + java.lang.Object ref = path_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + if (bs.isValidUtf8()) { + path_ = s; + } + return s; + } + } + /** + * optional string path = 1; + */ + public com.google.protobuf.ByteString + getPathBytes() { + java.lang.Object ref = path_; + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + path_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + public static final int SIZE_FIELD_NUMBER = 2; + private long size_; + /** + * optional uint64 size = 2; + */ + public boolean hasSize() { + return ((bitField0_ & 0x00000002) == 0x00000002); + } + /** + * optional uint64 size = 2; + */ + public long getSize() { + return size_; + } + + public static final int SHA1_FIELD_NUMBER = 3; + private volatile java.lang.Object sha1_; + /** + * optional string sha1 = 3; + */ + public boolean hasSha1() { + return ((bitField0_ & 0x00000004) == 0x00000004); + } + /** + * optional string sha1 = 3; + */ + public java.lang.String getSha1() { + java.lang.Object ref = sha1_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + if (bs.isValidUtf8()) { + sha1_ = s; + } + return s; + } + } + /** + * optional string sha1 = 3; + */ + public com.google.protobuf.ByteString + getSha1Bytes() { + java.lang.Object ref = sha1_; + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + sha1_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + public static final int DATA_FIELD_NUMBER = 16; + private com.google.protobuf.ByteString data_; + /** + * optional bytes data = 16; + */ + public boolean hasData() { + return ((bitField0_ & 0x00000008) == 0x00000008); + } + /** + * optional bytes data = 16; + */ + public com.google.protobuf.ByteString getData() { + return data_; + } + + private byte memoizedIsInitialized = -1; + public final boolean isInitialized() { + byte isInitialized = memoizedIsInitialized; + if (isInitialized == 1) return true; + if (isInitialized == 0) return false; + + memoizedIsInitialized = 1; + return true; + } + + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + if (((bitField0_ & 0x00000001) == 0x00000001)) { + com.google.protobuf.GeneratedMessage.writeString(output, 1, path_); + } + if (((bitField0_ & 0x00000002) == 0x00000002)) { + output.writeUInt64(2, size_); + } + if (((bitField0_ & 0x00000004) == 0x00000004)) { + com.google.protobuf.GeneratedMessage.writeString(output, 3, sha1_); + } + if (((bitField0_ & 0x00000008) == 0x00000008)) { + output.writeBytes(16, data_); + } + unknownFields.writeTo(output); + } + + public int getSerializedSize() { + int size = memoizedSize; + if (size != -1) return size; + + size = 0; + if (((bitField0_ & 0x00000001) == 0x00000001)) { + size += com.google.protobuf.GeneratedMessage.computeStringSize(1, path_); + } + if (((bitField0_ & 0x00000002) == 0x00000002)) { + size += com.google.protobuf.CodedOutputStream + .computeUInt64Size(2, size_); + } + if (((bitField0_ & 0x00000004) == 0x00000004)) { + size += com.google.protobuf.GeneratedMessage.computeStringSize(3, sha1_); + } + if (((bitField0_ & 0x00000008) == 0x00000008)) { + size += com.google.protobuf.CodedOutputStream + .computeBytesSize(16, data_); + } + size += unknownFields.getSerializedSize(); + memoizedSize = size; + return size; + } + + private static final long serialVersionUID = 0L; + public static chaintool.car.abi.Car.Archive.Payload.Entries parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static chaintool.car.abi.Car.Archive.Payload.Entries parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static chaintool.car.abi.Car.Archive.Payload.Entries parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static chaintool.car.abi.Car.Archive.Payload.Entries parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static chaintool.car.abi.Car.Archive.Payload.Entries parseFrom(java.io.InputStream input) + throws java.io.IOException { + return PARSER.parseFrom(input); + } + public static chaintool.car.abi.Car.Archive.Payload.Entries parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return PARSER.parseFrom(input, extensionRegistry); + } + public static chaintool.car.abi.Car.Archive.Payload.Entries parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + return PARSER.parseDelimitedFrom(input); + } + public static chaintool.car.abi.Car.Archive.Payload.Entries parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return PARSER.parseDelimitedFrom(input, extensionRegistry); + } + public static chaintool.car.abi.Car.Archive.Payload.Entries parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return PARSER.parseFrom(input); + } + public static chaintool.car.abi.Car.Archive.Payload.Entries parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return PARSER.parseFrom(input, extensionRegistry); + } + + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder() { + return DEFAULT_INSTANCE.toBuilder(); + } + public static Builder newBuilder(chaintool.car.abi.Car.Archive.Payload.Entries prototype) { + return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); + } + public Builder toBuilder() { + return this == DEFAULT_INSTANCE + ? new Builder() : new Builder().mergeFrom(this); + } + + @java.lang.Override + protected Builder newBuilderForType( + com.google.protobuf.GeneratedMessage.BuilderParent parent) { + Builder builder = new Builder(parent); + return builder; + } + /** + * Protobuf type {@code chaintool.car.abi.Archive.Payload.Entries} + */ + public static final class Builder extends + com.google.protobuf.GeneratedMessage.Builder implements + // @@protoc_insertion_point(builder_implements:chaintool.car.abi.Archive.Payload.Entries) + chaintool.car.abi.Car.Archive.Payload.EntriesOrBuilder { + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return chaintool.car.abi.Car.internal_static_chaintool_car_abi_Archive_Payload_Entries_descriptor; + } + + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return chaintool.car.abi.Car.internal_static_chaintool_car_abi_Archive_Payload_Entries_fieldAccessorTable + .ensureFieldAccessorsInitialized( + chaintool.car.abi.Car.Archive.Payload.Entries.class, chaintool.car.abi.Car.Archive.Payload.Entries.Builder.class); + } + + // Construct using chaintool.car.abi.Car.Archive.Payload.Entries.newBuilder() + private Builder() { + maybeForceBuilderInitialization(); + } + + private Builder( + com.google.protobuf.GeneratedMessage.BuilderParent parent) { + super(parent); + maybeForceBuilderInitialization(); + } + private void maybeForceBuilderInitialization() { + if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) { + } + } + public Builder clear() { + super.clear(); + path_ = ""; + bitField0_ = (bitField0_ & ~0x00000001); + size_ = 0L; + bitField0_ = (bitField0_ & ~0x00000002); + sha1_ = ""; + bitField0_ = (bitField0_ & ~0x00000004); + data_ = com.google.protobuf.ByteString.EMPTY; + bitField0_ = (bitField0_ & ~0x00000008); + return this; + } + + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return chaintool.car.abi.Car.internal_static_chaintool_car_abi_Archive_Payload_Entries_descriptor; + } + + public chaintool.car.abi.Car.Archive.Payload.Entries getDefaultInstanceForType() { + return chaintool.car.abi.Car.Archive.Payload.Entries.getDefaultInstance(); + } + + public chaintool.car.abi.Car.Archive.Payload.Entries build() { + chaintool.car.abi.Car.Archive.Payload.Entries result = buildPartial(); + if (!result.isInitialized()) { + throw newUninitializedMessageException(result); + } + return result; + } + + public chaintool.car.abi.Car.Archive.Payload.Entries buildPartial() { + chaintool.car.abi.Car.Archive.Payload.Entries result = new chaintool.car.abi.Car.Archive.Payload.Entries(this); + int from_bitField0_ = bitField0_; + int to_bitField0_ = 0; + if (((from_bitField0_ & 0x00000001) == 0x00000001)) { + to_bitField0_ |= 0x00000001; + } + result.path_ = path_; + if (((from_bitField0_ & 0x00000002) == 0x00000002)) { + to_bitField0_ |= 0x00000002; + } + result.size_ = size_; + if (((from_bitField0_ & 0x00000004) == 0x00000004)) { + to_bitField0_ |= 0x00000004; + } + result.sha1_ = sha1_; + if (((from_bitField0_ & 0x00000008) == 0x00000008)) { + to_bitField0_ |= 0x00000008; + } + result.data_ = data_; + result.bitField0_ = to_bitField0_; + onBuilt(); + return result; + } + + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof chaintool.car.abi.Car.Archive.Payload.Entries) { + return mergeFrom((chaintool.car.abi.Car.Archive.Payload.Entries)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(chaintool.car.abi.Car.Archive.Payload.Entries other) { + if (other == chaintool.car.abi.Car.Archive.Payload.Entries.getDefaultInstance()) return this; + if (other.hasPath()) { + bitField0_ |= 0x00000001; + path_ = other.path_; + onChanged(); + } + if (other.hasSize()) { + setSize(other.getSize()); + } + if (other.hasSha1()) { + bitField0_ |= 0x00000004; + sha1_ = other.sha1_; + onChanged(); + } + if (other.hasData()) { + setData(other.getData()); + } + this.mergeUnknownFields(other.unknownFields); + onChanged(); + return this; + } + + public final boolean isInitialized() { + return true; + } + + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + chaintool.car.abi.Car.Archive.Payload.Entries parsedMessage = null; + try { + parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry); + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + parsedMessage = (chaintool.car.abi.Car.Archive.Payload.Entries) e.getUnfinishedMessage(); + throw e; + } finally { + if (parsedMessage != null) { + mergeFrom(parsedMessage); + } + } + return this; + } + private int bitField0_; + + private java.lang.Object path_ = ""; + /** + * optional string path = 1; + */ + public boolean hasPath() { + return ((bitField0_ & 0x00000001) == 0x00000001); + } + /** + * optional string path = 1; + */ + public java.lang.String getPath() { + java.lang.Object ref = path_; + if (!(ref instanceof java.lang.String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + if (bs.isValidUtf8()) { + path_ = s; + } + return s; + } else { + return (java.lang.String) ref; + } + } + /** + * optional string path = 1; + */ + public com.google.protobuf.ByteString + getPathBytes() { + java.lang.Object ref = path_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + path_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + * optional string path = 1; + */ + public Builder setPath( + java.lang.String value) { + if (value == null) { + throw new NullPointerException(); + } + bitField0_ |= 0x00000001; + path_ = value; + onChanged(); + return this; + } + /** + * optional string path = 1; + */ + public Builder clearPath() { + bitField0_ = (bitField0_ & ~0x00000001); + path_ = getDefaultInstance().getPath(); + onChanged(); + return this; + } + /** + * optional string path = 1; + */ + public Builder setPathBytes( + com.google.protobuf.ByteString value) { + if (value == null) { + throw new NullPointerException(); + } + bitField0_ |= 0x00000001; + path_ = value; + onChanged(); + return this; + } + + private long size_ ; + /** + * optional uint64 size = 2; + */ + public boolean hasSize() { + return ((bitField0_ & 0x00000002) == 0x00000002); + } + /** + * optional uint64 size = 2; + */ + public long getSize() { + return size_; + } + /** + * optional uint64 size = 2; + */ + public Builder setSize(long value) { + bitField0_ |= 0x00000002; + size_ = value; + onChanged(); + return this; + } + /** + * optional uint64 size = 2; + */ + public Builder clearSize() { + bitField0_ = (bitField0_ & ~0x00000002); + size_ = 0L; + onChanged(); + return this; + } + + private java.lang.Object sha1_ = ""; + /** + * optional string sha1 = 3; + */ + public boolean hasSha1() { + return ((bitField0_ & 0x00000004) == 0x00000004); + } + /** + * optional string sha1 = 3; + */ + public java.lang.String getSha1() { + java.lang.Object ref = sha1_; + if (!(ref instanceof java.lang.String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + if (bs.isValidUtf8()) { + sha1_ = s; + } + return s; + } else { + return (java.lang.String) ref; + } + } + /** + * optional string sha1 = 3; + */ + public com.google.protobuf.ByteString + getSha1Bytes() { + java.lang.Object ref = sha1_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + sha1_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + * optional string sha1 = 3; + */ + public Builder setSha1( + java.lang.String value) { + if (value == null) { + throw new NullPointerException(); + } + bitField0_ |= 0x00000004; + sha1_ = value; + onChanged(); + return this; + } + /** + * optional string sha1 = 3; + */ + public Builder clearSha1() { + bitField0_ = (bitField0_ & ~0x00000004); + sha1_ = getDefaultInstance().getSha1(); + onChanged(); + return this; + } + /** + * optional string sha1 = 3; + */ + public Builder setSha1Bytes( + com.google.protobuf.ByteString value) { + if (value == null) { + throw new NullPointerException(); + } + bitField0_ |= 0x00000004; + sha1_ = value; + onChanged(); + return this; + } + + private com.google.protobuf.ByteString data_ = com.google.protobuf.ByteString.EMPTY; + /** + * optional bytes data = 16; + */ + public boolean hasData() { + return ((bitField0_ & 0x00000008) == 0x00000008); + } + /** + * optional bytes data = 16; + */ + public com.google.protobuf.ByteString getData() { + return data_; + } + /** + * optional bytes data = 16; + */ + public Builder setData(com.google.protobuf.ByteString value) { + if (value == null) { + throw new NullPointerException(); + } + bitField0_ |= 0x00000008; + data_ = value; + onChanged(); + return this; + } + /** + * optional bytes data = 16; + */ + public Builder clearData() { + bitField0_ = (bitField0_ & ~0x00000008); + data_ = getDefaultInstance().getData(); + onChanged(); + return this; + } + + // @@protoc_insertion_point(builder_scope:chaintool.car.abi.Archive.Payload.Entries) + } + + // @@protoc_insertion_point(class_scope:chaintool.car.abi.Archive.Payload.Entries) + private static final chaintool.car.abi.Car.Archive.Payload.Entries DEFAULT_INSTANCE; + static { + DEFAULT_INSTANCE = new chaintool.car.abi.Car.Archive.Payload.Entries(); + } + + public static chaintool.car.abi.Car.Archive.Payload.Entries getDefaultInstance() { + return DEFAULT_INSTANCE; + } + + @java.lang.Deprecated public static final com.google.protobuf.Parser + PARSER = new com.google.protobuf.AbstractParser() { + public Entries parsePartialFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + try { + return new Entries(input, extensionRegistry); + } catch (RuntimeException e) { + if (e.getCause() instanceof + com.google.protobuf.InvalidProtocolBufferException) { + throw (com.google.protobuf.InvalidProtocolBufferException) + e.getCause(); + } + throw e; + } + } + }; + + public static com.google.protobuf.Parser parser() { + return PARSER; + } + + @java.lang.Override + public com.google.protobuf.Parser getParserForType() { + return PARSER; + } + + public chaintool.car.abi.Car.Archive.Payload.Entries getDefaultInstanceForType() { + return DEFAULT_INSTANCE; + } + + } + + private int bitField0_; + public static final int COMPRESSION_FIELD_NUMBER = 1; + private chaintool.car.abi.Car.Archive.Payload.Compression compression_; + /** + * optional .chaintool.car.abi.Archive.Payload.Compression compression = 1; + */ + public boolean hasCompression() { + return ((bitField0_ & 0x00000001) == 0x00000001); + } + /** + * optional .chaintool.car.abi.Archive.Payload.Compression compression = 1; + */ + public chaintool.car.abi.Car.Archive.Payload.Compression getCompression() { + return compression_ == null ? chaintool.car.abi.Car.Archive.Payload.Compression.getDefaultInstance() : compression_; + } + /** + * optional .chaintool.car.abi.Archive.Payload.Compression compression = 1; + */ + public chaintool.car.abi.Car.Archive.Payload.CompressionOrBuilder getCompressionOrBuilder() { + return compression_ == null ? chaintool.car.abi.Car.Archive.Payload.Compression.getDefaultInstance() : compression_; + } + + public static final int ENTRIES_FIELD_NUMBER = 16; + private java.util.List entries_; + /** + * repeated .chaintool.car.abi.Archive.Payload.Entries entries = 16; + */ + public java.util.List getEntriesList() { + return entries_; + } + /** + * repeated .chaintool.car.abi.Archive.Payload.Entries entries = 16; + */ + public java.util.List + getEntriesOrBuilderList() { + return entries_; + } + /** + * repeated .chaintool.car.abi.Archive.Payload.Entries entries = 16; + */ + public int getEntriesCount() { + return entries_.size(); + } + /** + * repeated .chaintool.car.abi.Archive.Payload.Entries entries = 16; + */ + public chaintool.car.abi.Car.Archive.Payload.Entries getEntries(int index) { + return entries_.get(index); + } + /** + * repeated .chaintool.car.abi.Archive.Payload.Entries entries = 16; + */ + public chaintool.car.abi.Car.Archive.Payload.EntriesOrBuilder getEntriesOrBuilder( + int index) { + return entries_.get(index); + } + + private byte memoizedIsInitialized = -1; + public final boolean isInitialized() { + byte isInitialized = memoizedIsInitialized; + if (isInitialized == 1) return true; + if (isInitialized == 0) return false; + + memoizedIsInitialized = 1; + return true; + } + + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + if (((bitField0_ & 0x00000001) == 0x00000001)) { + output.writeMessage(1, getCompression()); + } + for (int i = 0; i < entries_.size(); i++) { + output.writeMessage(16, entries_.get(i)); + } + unknownFields.writeTo(output); + } + + public int getSerializedSize() { + int size = memoizedSize; + if (size != -1) return size; + + size = 0; + if (((bitField0_ & 0x00000001) == 0x00000001)) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(1, getCompression()); + } + for (int i = 0; i < entries_.size(); i++) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(16, entries_.get(i)); + } + size += unknownFields.getSerializedSize(); + memoizedSize = size; + return size; + } + + private static final long serialVersionUID = 0L; + public static chaintool.car.abi.Car.Archive.Payload parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static chaintool.car.abi.Car.Archive.Payload parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static chaintool.car.abi.Car.Archive.Payload parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static chaintool.car.abi.Car.Archive.Payload parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static chaintool.car.abi.Car.Archive.Payload parseFrom(java.io.InputStream input) + throws java.io.IOException { + return PARSER.parseFrom(input); + } + public static chaintool.car.abi.Car.Archive.Payload parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return PARSER.parseFrom(input, extensionRegistry); + } + public static chaintool.car.abi.Car.Archive.Payload parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + return PARSER.parseDelimitedFrom(input); + } + public static chaintool.car.abi.Car.Archive.Payload parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return PARSER.parseDelimitedFrom(input, extensionRegistry); + } + public static chaintool.car.abi.Car.Archive.Payload parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return PARSER.parseFrom(input); + } + public static chaintool.car.abi.Car.Archive.Payload parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return PARSER.parseFrom(input, extensionRegistry); + } + + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder() { + return DEFAULT_INSTANCE.toBuilder(); + } + public static Builder newBuilder(chaintool.car.abi.Car.Archive.Payload prototype) { + return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); + } + public Builder toBuilder() { + return this == DEFAULT_INSTANCE + ? new Builder() : new Builder().mergeFrom(this); + } + + @java.lang.Override + protected Builder newBuilderForType( + com.google.protobuf.GeneratedMessage.BuilderParent parent) { + Builder builder = new Builder(parent); + return builder; + } + /** + * Protobuf type {@code chaintool.car.abi.Archive.Payload} + */ + public static final class Builder extends + com.google.protobuf.GeneratedMessage.Builder implements + // @@protoc_insertion_point(builder_implements:chaintool.car.abi.Archive.Payload) + chaintool.car.abi.Car.Archive.PayloadOrBuilder { + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return chaintool.car.abi.Car.internal_static_chaintool_car_abi_Archive_Payload_descriptor; + } + + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return chaintool.car.abi.Car.internal_static_chaintool_car_abi_Archive_Payload_fieldAccessorTable + .ensureFieldAccessorsInitialized( + chaintool.car.abi.Car.Archive.Payload.class, chaintool.car.abi.Car.Archive.Payload.Builder.class); + } + + // Construct using chaintool.car.abi.Car.Archive.Payload.newBuilder() + private Builder() { + maybeForceBuilderInitialization(); + } + + private Builder( + com.google.protobuf.GeneratedMessage.BuilderParent parent) { + super(parent); + maybeForceBuilderInitialization(); + } + private void maybeForceBuilderInitialization() { + if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) { + getCompressionFieldBuilder(); + getEntriesFieldBuilder(); + } + } + public Builder clear() { + super.clear(); + if (compressionBuilder_ == null) { + compression_ = null; + } else { + compressionBuilder_.clear(); + } + bitField0_ = (bitField0_ & ~0x00000001); + if (entriesBuilder_ == null) { + entries_ = java.util.Collections.emptyList(); + bitField0_ = (bitField0_ & ~0x00000002); + } else { + entriesBuilder_.clear(); + } + return this; + } + + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return chaintool.car.abi.Car.internal_static_chaintool_car_abi_Archive_Payload_descriptor; + } + + public chaintool.car.abi.Car.Archive.Payload getDefaultInstanceForType() { + return chaintool.car.abi.Car.Archive.Payload.getDefaultInstance(); + } + + public chaintool.car.abi.Car.Archive.Payload build() { + chaintool.car.abi.Car.Archive.Payload result = buildPartial(); + if (!result.isInitialized()) { + throw newUninitializedMessageException(result); + } + return result; + } + + public chaintool.car.abi.Car.Archive.Payload buildPartial() { + chaintool.car.abi.Car.Archive.Payload result = new chaintool.car.abi.Car.Archive.Payload(this); + int from_bitField0_ = bitField0_; + int to_bitField0_ = 0; + if (((from_bitField0_ & 0x00000001) == 0x00000001)) { + to_bitField0_ |= 0x00000001; + } + if (compressionBuilder_ == null) { + result.compression_ = compression_; + } else { + result.compression_ = compressionBuilder_.build(); + } + if (entriesBuilder_ == null) { + if (((bitField0_ & 0x00000002) == 0x00000002)) { + entries_ = java.util.Collections.unmodifiableList(entries_); + bitField0_ = (bitField0_ & ~0x00000002); + } + result.entries_ = entries_; + } else { + result.entries_ = entriesBuilder_.build(); + } + result.bitField0_ = to_bitField0_; + onBuilt(); + return result; + } + + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof chaintool.car.abi.Car.Archive.Payload) { + return mergeFrom((chaintool.car.abi.Car.Archive.Payload)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(chaintool.car.abi.Car.Archive.Payload other) { + if (other == chaintool.car.abi.Car.Archive.Payload.getDefaultInstance()) return this; + if (other.hasCompression()) { + mergeCompression(other.getCompression()); + } + if (entriesBuilder_ == null) { + if (!other.entries_.isEmpty()) { + if (entries_.isEmpty()) { + entries_ = other.entries_; + bitField0_ = (bitField0_ & ~0x00000002); + } else { + ensureEntriesIsMutable(); + entries_.addAll(other.entries_); + } + onChanged(); + } + } else { + if (!other.entries_.isEmpty()) { + if (entriesBuilder_.isEmpty()) { + entriesBuilder_.dispose(); + entriesBuilder_ = null; + entries_ = other.entries_; + bitField0_ = (bitField0_ & ~0x00000002); + entriesBuilder_ = + com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders ? + getEntriesFieldBuilder() : null; + } else { + entriesBuilder_.addAllMessages(other.entries_); + } + } + } + this.mergeUnknownFields(other.unknownFields); + onChanged(); + return this; + } + + public final boolean isInitialized() { + return true; + } + + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + chaintool.car.abi.Car.Archive.Payload parsedMessage = null; + try { + parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry); + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + parsedMessage = (chaintool.car.abi.Car.Archive.Payload) e.getUnfinishedMessage(); + throw e; + } finally { + if (parsedMessage != null) { + mergeFrom(parsedMessage); + } + } + return this; + } + private int bitField0_; + + private chaintool.car.abi.Car.Archive.Payload.Compression compression_ = null; + private com.google.protobuf.SingleFieldBuilder< + chaintool.car.abi.Car.Archive.Payload.Compression, chaintool.car.abi.Car.Archive.Payload.Compression.Builder, chaintool.car.abi.Car.Archive.Payload.CompressionOrBuilder> compressionBuilder_; + /** + * optional .chaintool.car.abi.Archive.Payload.Compression compression = 1; + */ + public boolean hasCompression() { + return ((bitField0_ & 0x00000001) == 0x00000001); + } + /** + * optional .chaintool.car.abi.Archive.Payload.Compression compression = 1; + */ + public chaintool.car.abi.Car.Archive.Payload.Compression getCompression() { + if (compressionBuilder_ == null) { + return compression_ == null ? chaintool.car.abi.Car.Archive.Payload.Compression.getDefaultInstance() : compression_; + } else { + return compressionBuilder_.getMessage(); + } + } + /** + * optional .chaintool.car.abi.Archive.Payload.Compression compression = 1; + */ + public Builder setCompression(chaintool.car.abi.Car.Archive.Payload.Compression value) { + if (compressionBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + compression_ = value; + onChanged(); + } else { + compressionBuilder_.setMessage(value); + } + bitField0_ |= 0x00000001; + return this; + } + /** + * optional .chaintool.car.abi.Archive.Payload.Compression compression = 1; + */ + public Builder setCompression( + chaintool.car.abi.Car.Archive.Payload.Compression.Builder builderForValue) { + if (compressionBuilder_ == null) { + compression_ = builderForValue.build(); + onChanged(); + } else { + compressionBuilder_.setMessage(builderForValue.build()); + } + bitField0_ |= 0x00000001; + return this; + } + /** + * optional .chaintool.car.abi.Archive.Payload.Compression compression = 1; + */ + public Builder mergeCompression(chaintool.car.abi.Car.Archive.Payload.Compression value) { + if (compressionBuilder_ == null) { + if (((bitField0_ & 0x00000001) == 0x00000001) && + compression_ != null && + compression_ != chaintool.car.abi.Car.Archive.Payload.Compression.getDefaultInstance()) { + compression_ = + chaintool.car.abi.Car.Archive.Payload.Compression.newBuilder(compression_).mergeFrom(value).buildPartial(); + } else { + compression_ = value; + } + onChanged(); + } else { + compressionBuilder_.mergeFrom(value); + } + bitField0_ |= 0x00000001; + return this; + } + /** + * optional .chaintool.car.abi.Archive.Payload.Compression compression = 1; + */ + public Builder clearCompression() { + if (compressionBuilder_ == null) { + compression_ = null; + onChanged(); + } else { + compressionBuilder_.clear(); + } + bitField0_ = (bitField0_ & ~0x00000001); + return this; + } + /** + * optional .chaintool.car.abi.Archive.Payload.Compression compression = 1; + */ + public chaintool.car.abi.Car.Archive.Payload.Compression.Builder getCompressionBuilder() { + bitField0_ |= 0x00000001; + onChanged(); + return getCompressionFieldBuilder().getBuilder(); + } + /** + * optional .chaintool.car.abi.Archive.Payload.Compression compression = 1; + */ + public chaintool.car.abi.Car.Archive.Payload.CompressionOrBuilder getCompressionOrBuilder() { + if (compressionBuilder_ != null) { + return compressionBuilder_.getMessageOrBuilder(); + } else { + return compression_ == null ? + chaintool.car.abi.Car.Archive.Payload.Compression.getDefaultInstance() : compression_; + } + } + /** + * optional .chaintool.car.abi.Archive.Payload.Compression compression = 1; + */ + private com.google.protobuf.SingleFieldBuilder< + chaintool.car.abi.Car.Archive.Payload.Compression, chaintool.car.abi.Car.Archive.Payload.Compression.Builder, chaintool.car.abi.Car.Archive.Payload.CompressionOrBuilder> + getCompressionFieldBuilder() { + if (compressionBuilder_ == null) { + compressionBuilder_ = new com.google.protobuf.SingleFieldBuilder< + chaintool.car.abi.Car.Archive.Payload.Compression, chaintool.car.abi.Car.Archive.Payload.Compression.Builder, chaintool.car.abi.Car.Archive.Payload.CompressionOrBuilder>( + getCompression(), + getParentForChildren(), + isClean()); + compression_ = null; + } + return compressionBuilder_; + } + + private java.util.List entries_ = + java.util.Collections.emptyList(); + private void ensureEntriesIsMutable() { + if (!((bitField0_ & 0x00000002) == 0x00000002)) { + entries_ = new java.util.ArrayList(entries_); + bitField0_ |= 0x00000002; + } + } + + private com.google.protobuf.RepeatedFieldBuilder< + chaintool.car.abi.Car.Archive.Payload.Entries, chaintool.car.abi.Car.Archive.Payload.Entries.Builder, chaintool.car.abi.Car.Archive.Payload.EntriesOrBuilder> entriesBuilder_; + + /** + * repeated .chaintool.car.abi.Archive.Payload.Entries entries = 16; + */ + public java.util.List getEntriesList() { + if (entriesBuilder_ == null) { + return java.util.Collections.unmodifiableList(entries_); + } else { + return entriesBuilder_.getMessageList(); + } + } + /** + * repeated .chaintool.car.abi.Archive.Payload.Entries entries = 16; + */ + public int getEntriesCount() { + if (entriesBuilder_ == null) { + return entries_.size(); + } else { + return entriesBuilder_.getCount(); + } + } + /** + * repeated .chaintool.car.abi.Archive.Payload.Entries entries = 16; + */ + public chaintool.car.abi.Car.Archive.Payload.Entries getEntries(int index) { + if (entriesBuilder_ == null) { + return entries_.get(index); + } else { + return entriesBuilder_.getMessage(index); + } + } + /** + * repeated .chaintool.car.abi.Archive.Payload.Entries entries = 16; + */ + public Builder setEntries( + int index, chaintool.car.abi.Car.Archive.Payload.Entries value) { + if (entriesBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + ensureEntriesIsMutable(); + entries_.set(index, value); + onChanged(); + } else { + entriesBuilder_.setMessage(index, value); + } + return this; + } + /** + * repeated .chaintool.car.abi.Archive.Payload.Entries entries = 16; + */ + public Builder setEntries( + int index, chaintool.car.abi.Car.Archive.Payload.Entries.Builder builderForValue) { + if (entriesBuilder_ == null) { + ensureEntriesIsMutable(); + entries_.set(index, builderForValue.build()); + onChanged(); + } else { + entriesBuilder_.setMessage(index, builderForValue.build()); + } + return this; + } + /** + * repeated .chaintool.car.abi.Archive.Payload.Entries entries = 16; + */ + public Builder addEntries(chaintool.car.abi.Car.Archive.Payload.Entries value) { + if (entriesBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + ensureEntriesIsMutable(); + entries_.add(value); + onChanged(); + } else { + entriesBuilder_.addMessage(value); + } + return this; + } + /** + * repeated .chaintool.car.abi.Archive.Payload.Entries entries = 16; + */ + public Builder addEntries( + int index, chaintool.car.abi.Car.Archive.Payload.Entries value) { + if (entriesBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + ensureEntriesIsMutable(); + entries_.add(index, value); + onChanged(); + } else { + entriesBuilder_.addMessage(index, value); + } + return this; + } + /** + * repeated .chaintool.car.abi.Archive.Payload.Entries entries = 16; + */ + public Builder addEntries( + chaintool.car.abi.Car.Archive.Payload.Entries.Builder builderForValue) { + if (entriesBuilder_ == null) { + ensureEntriesIsMutable(); + entries_.add(builderForValue.build()); + onChanged(); + } else { + entriesBuilder_.addMessage(builderForValue.build()); + } + return this; + } + /** + * repeated .chaintool.car.abi.Archive.Payload.Entries entries = 16; + */ + public Builder addEntries( + int index, chaintool.car.abi.Car.Archive.Payload.Entries.Builder builderForValue) { + if (entriesBuilder_ == null) { + ensureEntriesIsMutable(); + entries_.add(index, builderForValue.build()); + onChanged(); + } else { + entriesBuilder_.addMessage(index, builderForValue.build()); + } + return this; + } + /** + * repeated .chaintool.car.abi.Archive.Payload.Entries entries = 16; + */ + public Builder addAllEntries( + java.lang.Iterable values) { + if (entriesBuilder_ == null) { + ensureEntriesIsMutable(); + com.google.protobuf.AbstractMessageLite.Builder.addAll( + values, entries_); + onChanged(); + } else { + entriesBuilder_.addAllMessages(values); + } + return this; + } + /** + * repeated .chaintool.car.abi.Archive.Payload.Entries entries = 16; + */ + public Builder clearEntries() { + if (entriesBuilder_ == null) { + entries_ = java.util.Collections.emptyList(); + bitField0_ = (bitField0_ & ~0x00000002); + onChanged(); + } else { + entriesBuilder_.clear(); + } + return this; + } + /** + * repeated .chaintool.car.abi.Archive.Payload.Entries entries = 16; + */ + public Builder removeEntries(int index) { + if (entriesBuilder_ == null) { + ensureEntriesIsMutable(); + entries_.remove(index); + onChanged(); + } else { + entriesBuilder_.remove(index); + } + return this; + } + /** + * repeated .chaintool.car.abi.Archive.Payload.Entries entries = 16; + */ + public chaintool.car.abi.Car.Archive.Payload.Entries.Builder getEntriesBuilder( + int index) { + return getEntriesFieldBuilder().getBuilder(index); + } + /** + * repeated .chaintool.car.abi.Archive.Payload.Entries entries = 16; + */ + public chaintool.car.abi.Car.Archive.Payload.EntriesOrBuilder getEntriesOrBuilder( + int index) { + if (entriesBuilder_ == null) { + return entries_.get(index); } else { + return entriesBuilder_.getMessageOrBuilder(index); + } + } + /** + * repeated .chaintool.car.abi.Archive.Payload.Entries entries = 16; + */ + public java.util.List + getEntriesOrBuilderList() { + if (entriesBuilder_ != null) { + return entriesBuilder_.getMessageOrBuilderList(); + } else { + return java.util.Collections.unmodifiableList(entries_); + } + } + /** + * repeated .chaintool.car.abi.Archive.Payload.Entries entries = 16; + */ + public chaintool.car.abi.Car.Archive.Payload.Entries.Builder addEntriesBuilder() { + return getEntriesFieldBuilder().addBuilder( + chaintool.car.abi.Car.Archive.Payload.Entries.getDefaultInstance()); + } + /** + * repeated .chaintool.car.abi.Archive.Payload.Entries entries = 16; + */ + public chaintool.car.abi.Car.Archive.Payload.Entries.Builder addEntriesBuilder( + int index) { + return getEntriesFieldBuilder().addBuilder( + index, chaintool.car.abi.Car.Archive.Payload.Entries.getDefaultInstance()); + } + /** + * repeated .chaintool.car.abi.Archive.Payload.Entries entries = 16; + */ + public java.util.List + getEntriesBuilderList() { + return getEntriesFieldBuilder().getBuilderList(); + } + private com.google.protobuf.RepeatedFieldBuilder< + chaintool.car.abi.Car.Archive.Payload.Entries, chaintool.car.abi.Car.Archive.Payload.Entries.Builder, chaintool.car.abi.Car.Archive.Payload.EntriesOrBuilder> + getEntriesFieldBuilder() { + if (entriesBuilder_ == null) { + entriesBuilder_ = new com.google.protobuf.RepeatedFieldBuilder< + chaintool.car.abi.Car.Archive.Payload.Entries, chaintool.car.abi.Car.Archive.Payload.Entries.Builder, chaintool.car.abi.Car.Archive.Payload.EntriesOrBuilder>( + entries_, + ((bitField0_ & 0x00000002) == 0x00000002), + getParentForChildren(), + isClean()); + entries_ = null; + } + return entriesBuilder_; + } + + // @@protoc_insertion_point(builder_scope:chaintool.car.abi.Archive.Payload) + } + + // @@protoc_insertion_point(class_scope:chaintool.car.abi.Archive.Payload) + private static final chaintool.car.abi.Car.Archive.Payload DEFAULT_INSTANCE; + static { + DEFAULT_INSTANCE = new chaintool.car.abi.Car.Archive.Payload(); + } + + public static chaintool.car.abi.Car.Archive.Payload getDefaultInstance() { + return DEFAULT_INSTANCE; + } + + @java.lang.Deprecated public static final com.google.protobuf.Parser + PARSER = new com.google.protobuf.AbstractParser() { + public Payload parsePartialFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + try { + return new Payload(input, extensionRegistry); + } catch (RuntimeException e) { + if (e.getCause() instanceof + com.google.protobuf.InvalidProtocolBufferException) { + throw (com.google.protobuf.InvalidProtocolBufferException) + e.getCause(); + } + throw e; + } + } + }; + + public static com.google.protobuf.Parser parser() { + return PARSER; + } + + @java.lang.Override + public com.google.protobuf.Parser getParserForType() { + return PARSER; + } + + public chaintool.car.abi.Car.Archive.Payload getDefaultInstanceForType() { + return DEFAULT_INSTANCE; + } + + } + + private int bitField0_; + public static final int SIGNATURE_FIELD_NUMBER = 1; + private chaintool.car.abi.Car.Archive.Signature signature_; + /** + * optional .chaintool.car.abi.Archive.Signature signature = 1; + */ + public boolean hasSignature() { + return ((bitField0_ & 0x00000001) == 0x00000001); + } + /** + * optional .chaintool.car.abi.Archive.Signature signature = 1; + */ + public chaintool.car.abi.Car.Archive.Signature getSignature() { + return signature_ == null ? chaintool.car.abi.Car.Archive.Signature.getDefaultInstance() : signature_; + } + /** + * optional .chaintool.car.abi.Archive.Signature signature = 1; + */ + public chaintool.car.abi.Car.Archive.SignatureOrBuilder getSignatureOrBuilder() { + return signature_ == null ? chaintool.car.abi.Car.Archive.Signature.getDefaultInstance() : signature_; + } + + public static final int PAYLOAD_FIELD_NUMBER = 2; + private com.google.protobuf.ByteString payload_; + /** + * optional bytes payload = 2; + */ + public boolean hasPayload() { + return ((bitField0_ & 0x00000002) == 0x00000002); + } + /** + * optional bytes payload = 2; + */ + public com.google.protobuf.ByteString getPayload() { + return payload_; + } + + private byte memoizedIsInitialized = -1; + public final boolean isInitialized() { + byte isInitialized = memoizedIsInitialized; + if (isInitialized == 1) return true; + if (isInitialized == 0) return false; + + memoizedIsInitialized = 1; + return true; + } + + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + if (((bitField0_ & 0x00000001) == 0x00000001)) { + output.writeMessage(1, getSignature()); + } + if (((bitField0_ & 0x00000002) == 0x00000002)) { + output.writeBytes(2, payload_); + } + unknownFields.writeTo(output); + } + + public int getSerializedSize() { + int size = memoizedSize; + if (size != -1) return size; + + size = 0; + if (((bitField0_ & 0x00000001) == 0x00000001)) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(1, getSignature()); + } + if (((bitField0_ & 0x00000002) == 0x00000002)) { + size += com.google.protobuf.CodedOutputStream + .computeBytesSize(2, payload_); + } + size += unknownFields.getSerializedSize(); + memoizedSize = size; + return size; + } + + private static final long serialVersionUID = 0L; + public static chaintool.car.abi.Car.Archive parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static chaintool.car.abi.Car.Archive parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static chaintool.car.abi.Car.Archive parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static chaintool.car.abi.Car.Archive parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static chaintool.car.abi.Car.Archive parseFrom(java.io.InputStream input) + throws java.io.IOException { + return PARSER.parseFrom(input); + } + public static chaintool.car.abi.Car.Archive parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return PARSER.parseFrom(input, extensionRegistry); + } + public static chaintool.car.abi.Car.Archive parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + return PARSER.parseDelimitedFrom(input); + } + public static chaintool.car.abi.Car.Archive parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return PARSER.parseDelimitedFrom(input, extensionRegistry); + } + public static chaintool.car.abi.Car.Archive parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return PARSER.parseFrom(input); + } + public static chaintool.car.abi.Car.Archive parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return PARSER.parseFrom(input, extensionRegistry); + } + + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder() { + return DEFAULT_INSTANCE.toBuilder(); + } + public static Builder newBuilder(chaintool.car.abi.Car.Archive prototype) { + return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); + } + public Builder toBuilder() { + return this == DEFAULT_INSTANCE + ? new Builder() : new Builder().mergeFrom(this); + } + + @java.lang.Override + protected Builder newBuilderForType( + com.google.protobuf.GeneratedMessage.BuilderParent parent) { + Builder builder = new Builder(parent); + return builder; + } + /** + * Protobuf type {@code chaintool.car.abi.Archive} + */ + public static final class Builder extends + com.google.protobuf.GeneratedMessage.Builder implements + // @@protoc_insertion_point(builder_implements:chaintool.car.abi.Archive) + chaintool.car.abi.Car.ArchiveOrBuilder { + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return chaintool.car.abi.Car.internal_static_chaintool_car_abi_Archive_descriptor; + } + + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return chaintool.car.abi.Car.internal_static_chaintool_car_abi_Archive_fieldAccessorTable + .ensureFieldAccessorsInitialized( + chaintool.car.abi.Car.Archive.class, chaintool.car.abi.Car.Archive.Builder.class); + } + + // Construct using chaintool.car.abi.Car.Archive.newBuilder() + private Builder() { + maybeForceBuilderInitialization(); + } + + private Builder( + com.google.protobuf.GeneratedMessage.BuilderParent parent) { + super(parent); + maybeForceBuilderInitialization(); + } + private void maybeForceBuilderInitialization() { + if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) { + getSignatureFieldBuilder(); + } + } + public Builder clear() { + super.clear(); + if (signatureBuilder_ == null) { + signature_ = null; + } else { + signatureBuilder_.clear(); + } + bitField0_ = (bitField0_ & ~0x00000001); + payload_ = com.google.protobuf.ByteString.EMPTY; + bitField0_ = (bitField0_ & ~0x00000002); + return this; + } + + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return chaintool.car.abi.Car.internal_static_chaintool_car_abi_Archive_descriptor; + } + + public chaintool.car.abi.Car.Archive getDefaultInstanceForType() { + return chaintool.car.abi.Car.Archive.getDefaultInstance(); + } + + public chaintool.car.abi.Car.Archive build() { + chaintool.car.abi.Car.Archive result = buildPartial(); + if (!result.isInitialized()) { + throw newUninitializedMessageException(result); + } + return result; + } + + public chaintool.car.abi.Car.Archive buildPartial() { + chaintool.car.abi.Car.Archive result = new chaintool.car.abi.Car.Archive(this); + int from_bitField0_ = bitField0_; + int to_bitField0_ = 0; + if (((from_bitField0_ & 0x00000001) == 0x00000001)) { + to_bitField0_ |= 0x00000001; + } + if (signatureBuilder_ == null) { + result.signature_ = signature_; + } else { + result.signature_ = signatureBuilder_.build(); + } + if (((from_bitField0_ & 0x00000002) == 0x00000002)) { + to_bitField0_ |= 0x00000002; + } + result.payload_ = payload_; + result.bitField0_ = to_bitField0_; + onBuilt(); + return result; + } + + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof chaintool.car.abi.Car.Archive) { + return mergeFrom((chaintool.car.abi.Car.Archive)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(chaintool.car.abi.Car.Archive other) { + if (other == chaintool.car.abi.Car.Archive.getDefaultInstance()) return this; + if (other.hasSignature()) { + mergeSignature(other.getSignature()); + } + if (other.hasPayload()) { + setPayload(other.getPayload()); + } + this.mergeUnknownFields(other.unknownFields); + onChanged(); + return this; + } + + public final boolean isInitialized() { + return true; + } + + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + chaintool.car.abi.Car.Archive parsedMessage = null; + try { + parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry); + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + parsedMessage = (chaintool.car.abi.Car.Archive) e.getUnfinishedMessage(); + throw e; + } finally { + if (parsedMessage != null) { + mergeFrom(parsedMessage); + } + } + return this; + } + private int bitField0_; + + private chaintool.car.abi.Car.Archive.Signature signature_ = null; + private com.google.protobuf.SingleFieldBuilder< + chaintool.car.abi.Car.Archive.Signature, chaintool.car.abi.Car.Archive.Signature.Builder, chaintool.car.abi.Car.Archive.SignatureOrBuilder> signatureBuilder_; + /** + * optional .chaintool.car.abi.Archive.Signature signature = 1; + */ + public boolean hasSignature() { + return ((bitField0_ & 0x00000001) == 0x00000001); + } + /** + * optional .chaintool.car.abi.Archive.Signature signature = 1; + */ + public chaintool.car.abi.Car.Archive.Signature getSignature() { + if (signatureBuilder_ == null) { + return signature_ == null ? chaintool.car.abi.Car.Archive.Signature.getDefaultInstance() : signature_; + } else { + return signatureBuilder_.getMessage(); + } + } + /** + * optional .chaintool.car.abi.Archive.Signature signature = 1; + */ + public Builder setSignature(chaintool.car.abi.Car.Archive.Signature value) { + if (signatureBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + signature_ = value; + onChanged(); + } else { + signatureBuilder_.setMessage(value); + } + bitField0_ |= 0x00000001; + return this; + } + /** + * optional .chaintool.car.abi.Archive.Signature signature = 1; + */ + public Builder setSignature( + chaintool.car.abi.Car.Archive.Signature.Builder builderForValue) { + if (signatureBuilder_ == null) { + signature_ = builderForValue.build(); + onChanged(); + } else { + signatureBuilder_.setMessage(builderForValue.build()); + } + bitField0_ |= 0x00000001; + return this; + } + /** + * optional .chaintool.car.abi.Archive.Signature signature = 1; + */ + public Builder mergeSignature(chaintool.car.abi.Car.Archive.Signature value) { + if (signatureBuilder_ == null) { + if (((bitField0_ & 0x00000001) == 0x00000001) && + signature_ != null && + signature_ != chaintool.car.abi.Car.Archive.Signature.getDefaultInstance()) { + signature_ = + chaintool.car.abi.Car.Archive.Signature.newBuilder(signature_).mergeFrom(value).buildPartial(); + } else { + signature_ = value; + } + onChanged(); + } else { + signatureBuilder_.mergeFrom(value); + } + bitField0_ |= 0x00000001; + return this; + } + /** + * optional .chaintool.car.abi.Archive.Signature signature = 1; + */ + public Builder clearSignature() { + if (signatureBuilder_ == null) { + signature_ = null; + onChanged(); + } else { + signatureBuilder_.clear(); + } + bitField0_ = (bitField0_ & ~0x00000001); + return this; + } + /** + * optional .chaintool.car.abi.Archive.Signature signature = 1; + */ + public chaintool.car.abi.Car.Archive.Signature.Builder getSignatureBuilder() { + bitField0_ |= 0x00000001; + onChanged(); + return getSignatureFieldBuilder().getBuilder(); + } + /** + * optional .chaintool.car.abi.Archive.Signature signature = 1; + */ + public chaintool.car.abi.Car.Archive.SignatureOrBuilder getSignatureOrBuilder() { + if (signatureBuilder_ != null) { + return signatureBuilder_.getMessageOrBuilder(); + } else { + return signature_ == null ? + chaintool.car.abi.Car.Archive.Signature.getDefaultInstance() : signature_; + } + } + /** + * optional .chaintool.car.abi.Archive.Signature signature = 1; + */ + private com.google.protobuf.SingleFieldBuilder< + chaintool.car.abi.Car.Archive.Signature, chaintool.car.abi.Car.Archive.Signature.Builder, chaintool.car.abi.Car.Archive.SignatureOrBuilder> + getSignatureFieldBuilder() { + if (signatureBuilder_ == null) { + signatureBuilder_ = new com.google.protobuf.SingleFieldBuilder< + chaintool.car.abi.Car.Archive.Signature, chaintool.car.abi.Car.Archive.Signature.Builder, chaintool.car.abi.Car.Archive.SignatureOrBuilder>( + getSignature(), + getParentForChildren(), + isClean()); + signature_ = null; + } + return signatureBuilder_; + } + + private com.google.protobuf.ByteString payload_ = com.google.protobuf.ByteString.EMPTY; + /** + * optional bytes payload = 2; + */ + public boolean hasPayload() { + return ((bitField0_ & 0x00000002) == 0x00000002); + } + /** + * optional bytes payload = 2; + */ + public com.google.protobuf.ByteString getPayload() { + return payload_; + } + /** + * optional bytes payload = 2; + */ + public Builder setPayload(com.google.protobuf.ByteString value) { + if (value == null) { + throw new NullPointerException(); + } + bitField0_ |= 0x00000002; + payload_ = value; + onChanged(); + return this; + } + /** + * optional bytes payload = 2; + */ + public Builder clearPayload() { + bitField0_ = (bitField0_ & ~0x00000002); + payload_ = getDefaultInstance().getPayload(); + onChanged(); + return this; + } + + // @@protoc_insertion_point(builder_scope:chaintool.car.abi.Archive) + } + + // @@protoc_insertion_point(class_scope:chaintool.car.abi.Archive) + private static final chaintool.car.abi.Car.Archive DEFAULT_INSTANCE; + static { + DEFAULT_INSTANCE = new chaintool.car.abi.Car.Archive(); + } + + public static chaintool.car.abi.Car.Archive getDefaultInstance() { + return DEFAULT_INSTANCE; + } + + @java.lang.Deprecated public static final com.google.protobuf.Parser + PARSER = new com.google.protobuf.AbstractParser() { + public Archive parsePartialFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + try { + return new Archive(input, extensionRegistry); + } catch (RuntimeException e) { + if (e.getCause() instanceof + com.google.protobuf.InvalidProtocolBufferException) { + throw (com.google.protobuf.InvalidProtocolBufferException) + e.getCause(); + } + throw e; + } + } + }; + + public static com.google.protobuf.Parser parser() { + return PARSER; + } + + @java.lang.Override + public com.google.protobuf.Parser getParserForType() { + return PARSER; + } + + public chaintool.car.abi.Car.Archive getDefaultInstanceForType() { + return DEFAULT_INSTANCE; + } + + } + + private static com.google.protobuf.Descriptors.Descriptor + internal_static_chaintool_car_abi_CompatibilityHeader_descriptor; + private static + com.google.protobuf.GeneratedMessage.FieldAccessorTable + internal_static_chaintool_car_abi_CompatibilityHeader_fieldAccessorTable; + private static com.google.protobuf.Descriptors.Descriptor + internal_static_chaintool_car_abi_Archive_descriptor; + private static + com.google.protobuf.GeneratedMessage.FieldAccessorTable + internal_static_chaintool_car_abi_Archive_fieldAccessorTable; + private static com.google.protobuf.Descriptors.Descriptor + internal_static_chaintool_car_abi_Archive_Signature_descriptor; + private static + com.google.protobuf.GeneratedMessage.FieldAccessorTable + internal_static_chaintool_car_abi_Archive_Signature_fieldAccessorTable; + private static com.google.protobuf.Descriptors.Descriptor + internal_static_chaintool_car_abi_Archive_Payload_descriptor; + private static + com.google.protobuf.GeneratedMessage.FieldAccessorTable + internal_static_chaintool_car_abi_Archive_Payload_fieldAccessorTable; + private static com.google.protobuf.Descriptors.Descriptor + internal_static_chaintool_car_abi_Archive_Payload_Compression_descriptor; + private static + com.google.protobuf.GeneratedMessage.FieldAccessorTable + internal_static_chaintool_car_abi_Archive_Payload_Compression_fieldAccessorTable; + private static com.google.protobuf.Descriptors.Descriptor + internal_static_chaintool_car_abi_Archive_Payload_Entries_descriptor; + private static + com.google.protobuf.GeneratedMessage.FieldAccessorTable + internal_static_chaintool_car_abi_Archive_Payload_Entries_fieldAccessorTable; + + public static com.google.protobuf.Descriptors.FileDescriptor + getDescriptor() { + return descriptor; + } + private static com.google.protobuf.Descriptors.FileDescriptor + descriptor; + static { + java.lang.String[] descriptorData = { + "\n\031resources/proto/car.proto\022\021chaintool.c" + + "ar.abi\"G\n\023CompatibilityHeader\022\r\n\005magic\030\001" + + " \002(\t\022\017\n\007version\030\002 \002(\005\022\020\n\010features\030\003 \003(\t\"" + + "\320\004\n\007Archive\0227\n\tsignature\030\001 \001(\0132$.chainto" + + "ol.car.abi.Archive.Signature\022\017\n\007payload\030" + + "\002 \001(\014\032\202\001\n\tSignature\0227\n\004type\030\001 \001(\0162).chai" + + "ntool.car.abi.Archive.Signature.Type\022\023\n\013" + + "description\030\002 \001(\t\022\014\n\004data\030\003 \001(\014\"\031\n\004Type\022" + + "\010\n\004NONE\020\001\022\007\n\003RSA\020\002\032\365\002\n\007Payload\022C\n\013compre" + + "ssion\030\001 \001(\0132..chaintool.car.abi.Archive.", + "Payload.Compression\022;\n\007entries\030\020 \003(\0132*.c" + + "haintool.car.abi.Archive.Payload.Entries" + + "\032\244\001\n\013Compression\022G\n\004type\030\001 \001(\01623.chainto" + + "ol.car.abi.Archive.Payload.Compression.T" + + "ype:\004NONE\022\023\n\013description\030\002 \001(\t\"7\n\004Type\022\010" + + "\n\004NONE\020\001\022\010\n\004GZIP\020\002\022\010\n\004LZMA\020\003\022\t\n\005BZIP2\020\004\022" + + "\006\n\002XZ\020\005\032A\n\007Entries\022\014\n\004path\030\001 \001(\t\022\014\n\004size" + + "\030\002 \001(\004\022\014\n\004sha1\030\003 \001(\t\022\014\n\004data\030\020 \001(\014" + }; + com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner = + new com.google.protobuf.Descriptors.FileDescriptor. InternalDescriptorAssigner() { + public com.google.protobuf.ExtensionRegistry assignDescriptors( + com.google.protobuf.Descriptors.FileDescriptor root) { + descriptor = root; + return null; + } + }; + com.google.protobuf.Descriptors.FileDescriptor + .internalBuildGeneratedFileFrom(descriptorData, + new com.google.protobuf.Descriptors.FileDescriptor[] { + }, assigner); + internal_static_chaintool_car_abi_CompatibilityHeader_descriptor = + getDescriptor().getMessageTypes().get(0); + internal_static_chaintool_car_abi_CompatibilityHeader_fieldAccessorTable = new + com.google.protobuf.GeneratedMessage.FieldAccessorTable( + internal_static_chaintool_car_abi_CompatibilityHeader_descriptor, + new java.lang.String[] { "Magic", "Version", "Features", }); + internal_static_chaintool_car_abi_Archive_descriptor = + getDescriptor().getMessageTypes().get(1); + internal_static_chaintool_car_abi_Archive_fieldAccessorTable = new + com.google.protobuf.GeneratedMessage.FieldAccessorTable( + internal_static_chaintool_car_abi_Archive_descriptor, + new java.lang.String[] { "Signature", "Payload", }); + internal_static_chaintool_car_abi_Archive_Signature_descriptor = + internal_static_chaintool_car_abi_Archive_descriptor.getNestedTypes().get(0); + internal_static_chaintool_car_abi_Archive_Signature_fieldAccessorTable = new + com.google.protobuf.GeneratedMessage.FieldAccessorTable( + internal_static_chaintool_car_abi_Archive_Signature_descriptor, + new java.lang.String[] { "Type", "Description", "Data", }); + internal_static_chaintool_car_abi_Archive_Payload_descriptor = + internal_static_chaintool_car_abi_Archive_descriptor.getNestedTypes().get(1); + internal_static_chaintool_car_abi_Archive_Payload_fieldAccessorTable = new + com.google.protobuf.GeneratedMessage.FieldAccessorTable( + internal_static_chaintool_car_abi_Archive_Payload_descriptor, + new java.lang.String[] { "Compression", "Entries", }); + internal_static_chaintool_car_abi_Archive_Payload_Compression_descriptor = + internal_static_chaintool_car_abi_Archive_Payload_descriptor.getNestedTypes().get(0); + internal_static_chaintool_car_abi_Archive_Payload_Compression_fieldAccessorTable = new + com.google.protobuf.GeneratedMessage.FieldAccessorTable( + internal_static_chaintool_car_abi_Archive_Payload_Compression_descriptor, + new java.lang.String[] { "Type", "Description", }); + internal_static_chaintool_car_abi_Archive_Payload_Entries_descriptor = + internal_static_chaintool_car_abi_Archive_Payload_descriptor.getNestedTypes().get(1); + internal_static_chaintool_car_abi_Archive_Payload_Entries_fieldAccessorTable = new + com.google.protobuf.GeneratedMessage.FieldAccessorTable( + internal_static_chaintool_car_abi_Archive_Payload_Entries_descriptor, + new java.lang.String[] { "Path", "Size", "Sha1", "Data", }); + } + + // @@protoc_insertion_point(outer_class_scope) +} diff --git a/src/chaintool/car/ls.clj b/src/chaintool/car/ls.clj new file mode 100644 index 0000000..468f851 --- /dev/null +++ b/src/chaintool/car/ls.clj @@ -0,0 +1,34 @@ +;; Copyright London Stock Exchange Group 2016 All Rights Reserved. +;; +;; Licensed under the Apache License, Version 2.0 (the "License"); +;; you may not use this file except in compliance with the License. +;; You may obtain a copy of the License at +;; +;; http://www.apache.org/licenses/LICENSE-2.0 +;; +;; Unless required by applicable law or agreed to in writing, software +;; distributed under the License is distributed on an "AS IS" BASIS, +;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +;; See the License for the specific language governing permissions and +;; limitations under the License. + +(ns chaintool.car.ls + (:require [chaintool.car.read :as car] + [clojure.java.io :as io] + [doric.core :as doric] + [pandect.algo.sha3-512 :refer :all])) + +(defn platform-version [config] + (str (->> config :Platform :Name) " version " (->> config :Platform :Version))) + +(defn ls [file] + (let [{:keys [payload config]} (with-open [is (io/input-stream file)] (car/read is)) + entries (:entries payload)] + + (println (doric/table [{:name :size} {:name :sha1 :title "SHA1"} {:name :path}] entries)) + (println "Platform: " (platform-version config)) + (println "Digital Signature: none") + (println "Raw Data Size: " (->> entries (map :size) (reduce +)) "bytes") + (println "Archive Size: " (.length file) "bytes") + (println "Compression Alg: " (get-in payload [:compression :description])) + (println "Chaincode SHA3: " (sha3-512 file)))) diff --git a/src/chaintool/car/read.clj b/src/chaintool/car/read.clj new file mode 100644 index 0000000..68e0d6b --- /dev/null +++ b/src/chaintool/car/read.clj @@ -0,0 +1,125 @@ +;; Copyright London Stock Exchange Group 2016 All Rights Reserved. +;; +;; Licensed under the Apache License, Version 2.0 (the "License"); +;; you may not use this file except in compliance with the License. +;; You may obtain a copy of the License at +;; +;; http://www.apache.org/licenses/LICENSE-2.0 +;; +;; Unless required by applicable law or agreed to in writing, software +;; distributed under the License is distributed on an "AS IS" BASIS, +;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +;; See the License for the specific language governing permissions and +;; limitations under the License. + +(ns chaintool.car.read + (:require [flatland.protobuf.core :as fl] + [chaintool.util :as util] + [chaintool.car.types :refer :all] + [chaintool.codecs :as codecs] + [chaintool.config.parser :as config.parser] + [chaintool.config.util :as config.util] + [pandect.algo.sha1 :refer :all]) + (:refer-clojure :exclude [read])) + +;;-------------------------------------------------------------------------------------- +;; read-protobuf - reads a single protobuf message from a delimited stream +;; +;; our protobuf file consists of two primary message types, delimited by a size. +;; (fl/protobuf-seq) is designed to return an infinite lazy sequence of one type +;; so we need to feed this through (first) to extract only one. +;;-------------------------------------------------------------------------------------- +(defn read-protobuf [t is] (->> is (fl/protobuf-seq t) first)) + +;;-------------------------------------------------------------------------------------- +;; read-XX - read one instance of a specific type of protobuf message [Header|Archive] +;;-------------------------------------------------------------------------------------- +(defn read-header [is] (read-protobuf Header is)) +(defn read-archive [is] (read-protobuf Archive is)) + +;;-------------------------------------------------------------------------------------- +;; make-input-stream - factory function for creating an input-stream for a specific entry +;; +;; We install the necessary decompressor such that the output of this stream represents +;; raw, uncompressed original data +;;-------------------------------------------------------------------------------------- +(defn make-input-stream [type entry] + (let [is (->> entry :data .newInput)] + (codecs/decompressor type is))) + +;;-------------------------------------------------------------------------------------- +;; import-header - imports and validates a Header object from the input stream +;; +;; evaluates to the parsed header if successful, or throws an exception otherwise +;;-------------------------------------------------------------------------------------- +(defn import-header [is] + (if-let [header (read-header is)] + (let [compat (select-keys header [:magic :version])] + (if (= compat CompatVersion) + (:features header) + (util/abort -1 (str "Incompatible header detected (expected: " CompatVersion " got: " compat ")")))) + (util/abort -1 (str "Failed to read archive header")))) + +;;-------------------------------------------------------------------------------------- +;; import-archive - imports an Archive object from the input stream +;;-------------------------------------------------------------------------------------- +(defn import-archive [is] + (read-archive is)) ;; FIXME - check digitial signature + +;;-------------------------------------------------------------------------------------- +;; import-entry - validates an entry object +;; +;; returns the proper input-stream-factory when sucessful, or throws an exception otherwise +;;-------------------------------------------------------------------------------------- +(defn import-entry [compression entry] + (let [type (:description compression) + factory #(make-input-stream type entry)] + + ;; verify the SHA1 + (with-open [is (factory)] + (let [sha (sha1 is)] + (when (not= sha (:sha1 entry)) + (util/abort -1 (str (:path entry) ": hash verification failure (expected: " (:sha1 entry) ", got: " sha ")"))))) + + ;; and inject our stream factory + {:entry entry :input-stream-factory factory})) + +;;-------------------------------------------------------------------------------------- +;; import-payload - imports a Payload object from Archive::Payload field +;; +;; We separate Archive from Payload to delineate signature boundaries. Everything within +;; Payload is expected to be optionally digitally signed (and thus verified upon import) +;;-------------------------------------------------------------------------------------- +(defn import-payload [archive] (->> archive :payload .newInput (fl/protobuf-load-stream Payload))) + +;;-------------------------------------------------------------------------------------- +;; synth-index - synthesize an index of entries, keyed by :path +;; +;; Takes a payload object and constructs a map of entries, keyed by their path. Each +;; entry is fully verified and processed (such as attaching an input-stream filter) +;;-------------------------------------------------------------------------------------- +(defn synth-index [payload] + (let [compression (:compression payload)] + (->> (:entries payload) (map #(vector (:path %) (import-entry compression %))) (into {})))) + +;;-------------------------------------------------------------------------------------- +;; entry-stream - instantiate an input-stream from the factory +;; +;; This allows a caller to obtain a simple input-stream interface to our entries where +;; all the details such as compression are already factored in. Therefore, this stream +;; is suitable to any number of tasks such as interpreting results, verifying contents, +;; or writing data to files +;;-------------------------------------------------------------------------------------- +(defn entry-stream [entry] + (let [factory (:input-stream-factory entry)] + (factory))) + +(defn read [is] + (let [features (import-header is) + archive (import-archive is) + payload (import-payload archive) + index (synth-index payload)] + + (with-open [config-stream (->> config.util/configname index entry-stream)] + (let [config (->> config-stream slurp config.parser/from-string)] + {:features features :payload payload :index index :config config})))) diff --git a/src/chaintool/car/types.clj b/src/chaintool/car/types.clj new file mode 100644 index 0000000..bb742e3 --- /dev/null +++ b/src/chaintool/car/types.clj @@ -0,0 +1,31 @@ +;; Copyright London Stock Exchange Group 2016 All Rights Reserved. +;; +;; Licensed under the Apache License, Version 2.0 (the "License"); +;; you may not use this file except in compliance with the License. +;; You may obtain a copy of the License at +;; +;; http://www.apache.org/licenses/LICENSE-2.0 +;; +;; Unless required by applicable law or agreed to in writing, software +;; distributed under the License is distributed on an "AS IS" BASIS, +;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +;; See the License for the specific language governing permissions and +;; limitations under the License. +(ns chaintool.car.types + (:import [chaintool.car.abi + Car$CompatibilityHeader + Car$Archive + Car$Archive$Signature + Car$Archive$Payload + Car$Archive$Payload$Compression + Car$Archive$Payload$Entries]) + (:require [flatland.protobuf.core :as fl])) + +(def Header (fl/protodef Car$CompatibilityHeader)) +(def Archive (fl/protodef Car$Archive)) +(def Signature (fl/protodef Car$Archive$Signature)) +(def Payload (fl/protodef Car$Archive$Payload)) +(def Compression (fl/protodef Car$Archive$Payload$Compression)) +(def Entries (fl/protodef Car$Archive$Payload$Entries)) + +(def CompatVersion {:magic "org.hyperledger.chaincode-archive" :version 1}) diff --git a/src/chaintool/car/unpack.clj b/src/chaintool/car/unpack.clj new file mode 100644 index 0000000..cbb1a3e --- /dev/null +++ b/src/chaintool/car/unpack.clj @@ -0,0 +1,40 @@ +;; Copyright London Stock Exchange Group 2016 All Rights Reserved. +;; +;; Licensed under the Apache License, Version 2.0 (the "License"); +;; you may not use this file except in compliance with the License. +;; You may obtain a copy of the License at +;; +;; http://www.apache.org/licenses/LICENSE-2.0 +;; +;; Unless required by applicable law or agreed to in writing, software +;; distributed under the License is distributed on an "AS IS" BASIS, +;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +;; See the License for the specific language governing permissions and +;; limitations under the License. + +(ns chaintool.car.unpack + (:require [clojure.java.io :as io] + [chaintool.car.read :as car.read])) + +;;-------------------------------------------------------------------------------------- +;; unpack - given a (pre-read) index of entries and an outputdir, unpack each element +;;-------------------------------------------------------------------------------------- +(defn unpack [index outputdir verbose] + (dorun + (for [[path item] index] + (let [entry (:entry item) + outputfile (io/file outputdir path)] + + ;; ensure our output path exists + (io/make-parents outputfile) + + ;; walk each entry and stream it out to the filesystem + (with-open [is (car.read/entry-stream item) + os (io/output-stream outputfile)] + + ;; we optionally may report out status to stdout + (when (= verbose :true) + (println (:sha1 entry) (:path entry) (str "(" (:size entry) " bytes)"))) + + ;; stream it out, pulling the input stream through any appropriate decompressor transparently + (io/copy is os)))))) diff --git a/src/chaintool/car/write.clj b/src/chaintool/car/write.clj new file mode 100644 index 0000000..1e94ce5 --- /dev/null +++ b/src/chaintool/car/write.clj @@ -0,0 +1,115 @@ +;; Copyright London Stock Exchange Group 2016 All Rights Reserved. +;; +;; Licensed under the Apache License, Version 2.0 (the "License"); +;; you may not use this file except in compliance with the License. +;; You may obtain a copy of the License at +;; +;; http://www.apache.org/licenses/LICENSE-2.0 +;; +;; Unless required by applicable law or agreed to in writing, software +;; distributed under the License is distributed on an "AS IS" BASIS, +;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +;; See the License for the specific language governing permissions and +;; limitations under the License. + +(ns chaintool.car.write + (:require [chaintool.car.types :refer :all] + [chaintool.codecs :as codecs] + [chaintool.util :as util] + [clojure.java.io :as io] + [clojure.string :as string] + [flatland.protobuf.core :as fl] + [pandect.algo.sha1 :refer :all]) + (:import (org.apache.commons.io.input TeeInputStream) + (org.apache.commons.io.output ByteArrayOutputStream)) + (:refer-clojure :exclude [import])) + +(defn findfiles [path] + (->> path file-seq (filter #(.isFile %)))) + +;;-------------------------------------------------------------------------------------- +;; convertfile - takes a basepath (string) and file (handle) and returns a tuple containing +;; {handle path} +;; +;; handle: the raw io/file handle as passed in via 'file' +;; path: the relative path of the file w.r.t. the root of the archive +;;-------------------------------------------------------------------------------------- +(defn convertfile [basepath file] + (let [basepathlen (->> basepath io/file .getAbsolutePath count inc) + fqpath (.getAbsolutePath file) + path (subs fqpath basepathlen)] + {:handle file :path path})) + +;;-------------------------------------------------------------------------------------- +;; import - takes a file handle and returns a tuple containing [sha1 size data] +;; +;; sha1: a string containing the computed sha1 of the raw uncompressed file contents +;; size: the raw uncompressed size of the file as it existed on the filesystem +;; data: a byte-array containing the compressed binary data imported from the filesystem +;;-------------------------------------------------------------------------------------- +(defn import [file compressiontype] + (let [os (ByteArrayOutputStream.) + [sha size] (with-open [is (io/input-stream file) ;; FIXME - validate maximum file size supported + compressor (codecs/compressor compressiontype os) + tee (TeeInputStream. is compressor)] + [(sha1 tee) (.length file)])] ;; FIXME - prefer to get the length from the stream + [sha size (.toByteArray os)])) + +;;-------------------------------------------------------------------------------------- +;; buildfiles - takes a basepath string, and a vector of spec strings, and builds +;; a sorted list of {:handle :path} structures. +;; +;; Spec entires can be either an explicit file or a directory, both of which are +;; implicitly relative to basepath. E.g. ["/path/to/foo" ["bar" "baz.conf"]] +;; would import ("/path/to/foo/bar" "/path/to/foo/baz.conf"). If any spec is a +;; directory it will be recursively expanded. +;; +;; The resulting structure will consist of an io/file under :handle, and a :path +;; with the basepath removed, sorted by :path (for determinisim) +;;-------------------------------------------------------------------------------------- +(defn buildfiles [basepath spec] + (let [handles (flatten (map #(findfiles (io/file basepath %)) spec)) + descriptors (map #(convertfile basepath %) handles)] + (sort-by :path descriptors))) + +;;-------------------------------------------------------------------------------------- +;; buildentry - builds a protobuf "Entry" object based on the tuple as emitted by (convertfile) +;;-------------------------------------------------------------------------------------- +(defn buildentry [{:keys [path handle]} compressiontype] + (let [[sha size payload] (import handle compressiontype)] + (fl/protobuf Entries :path path :size size :sha1 sha :data payload))) + +;;-------------------------------------------------------------------------------------- +;; buildentries - builds a list of protobuf "Entry" objects based on an input list +;; of {handle path} tuples. The output list will respect the input list order, and +;; it is important that the input list be pre-sorted in a deterministic manner if +;; the serialized output is expected to be deterministic as well. +;;-------------------------------------------------------------------------------------- +(defn buildentries [files compressiontype] + (map #(buildentry % compressiontype) files)) + +;;-------------------------------------------------------------------------------------- +;; buildcompression - builds a protobuf "Compression" object based on the requested type +;; after validating that the type is a supported option. +;;-------------------------------------------------------------------------------------- +(defn buildcompression [type] + (if (codecs/codec-types type) + (fl/protobuf Compression :type (string/upper-case type) :description type))) + +(defn write [rootpath filespec compressiontype outputfile] + (if-let [compression (buildcompression compressiontype)] + (let [files (buildfiles rootpath filespec) + header (fl/protobuf Header :magic (:magic CompatVersion) :version (:version CompatVersion)) + entries (buildentries files compressiontype) + payload (fl/protobuf Payload :compression compression :entries entries) + archive (fl/protobuf Archive :payload (fl/protobuf-dump payload))] + + ;; ensure the path exists + (io/make-parents outputfile) + + ;; emit our output + (with-open [os (io/output-stream outputfile :truncate true)] + (fl/protobuf-write os header archive))) + + ;; else + (util/abort -1 (str "Unknown compression type: \"" compressiontype "\"")))) diff --git a/src/chaintool/codecs.clj b/src/chaintool/codecs.clj new file mode 100644 index 0000000..c5f9031 --- /dev/null +++ b/src/chaintool/codecs.clj @@ -0,0 +1,55 @@ +;; Copyright London Stock Exchange Group 2016 All Rights Reserved. +;; +;; Licensed under the Apache License, Version 2.0 (the "License"); +;; you may not use this file except in compliance with the License. +;; You may obtain a copy of the License at +;; +;; http://www.apache.org/licenses/LICENSE-2.0 +;; +;; Unless required by applicable law or agreed to in writing, software +;; distributed under the License is distributed on an "AS IS" BASIS, +;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +;; See the License for the specific language governing permissions and +;; limitations under the License. + +(ns chaintool.codecs + (:import (lzma.streams LzmaOutputStream$Builder) + (org.apache.commons.compress.compressors.bzip2 BZip2CompressorInputStream + BZip2CompressorOutputStream) + (org.apache.commons.compress.compressors.gzip GzipCompressorInputStream + GzipCompressorOutputStream + GzipParameters) + (org.apache.commons.compress.compressors.lzma LZMACompressorInputStream) + (org.apache.commons.compress.compressors.xz XZCompressorInputStream + XZCompressorOutputStream) + (org.apache.commons.io.input ProxyInputStream) + (org.apache.commons.io.output ProxyOutputStream))) + +;;-------------------------------------------------------------------------------------- +;; compression support +;;-------------------------------------------------------------------------------------- +(def codec-descriptors + [{:name "none" + :output #(ProxyOutputStream. %) + :input #(ProxyInputStream. %)} + + {:name "gzip" + :output #(let [params (GzipParameters.)] (.setCompressionLevel params 9) (GzipCompressorOutputStream. % params)) + :input #(GzipCompressorInputStream. %)} + + {:name "lzma" + :output #(-> (LzmaOutputStream$Builder. %) .build) + :input #(LZMACompressorInputStream. %)} + + {:name "bzip2" + :output #(BZip2CompressorOutputStream. %) + :input #(BZip2CompressorInputStream. %)} + + {:name "xz" + :output #(XZCompressorOutputStream. % 6) + :input #(XZCompressorInputStream. %)}]) + +(def codec-types (->> codec-descriptors (map #(vector (:name %) %)) (into {}))) + +(defn compressor [type os] ((->> type codec-types :output) os)) +(defn decompressor [type is] ((->> type codec-types :input) is)) diff --git a/src/chaintool/config/parser.clj b/src/chaintool/config/parser.clj new file mode 100644 index 0000000..6348564 --- /dev/null +++ b/src/chaintool/config/parser.clj @@ -0,0 +1,28 @@ +;; Copyright London Stock Exchange Group 2016 All Rights Reserved. +;; +;; Licensed under the Apache License, Version 2.0 (the "License"); +;; you may not use this file except in compliance with the License. +;; You may obtain a copy of the License at +;; +;; http://www.apache.org/licenses/LICENSE-2.0 +;; +;; Unless required by applicable law or agreed to in writing, software +;; distributed under the License is distributed on an "AS IS" BASIS, +;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +;; See the License for the specific language governing permissions and +;; limitations under the License. + +(ns chaintool.config.parser + (:require [chaintool.util :as util] + [clj-yaml.core :as yaml])) + +(def supported-schema 1) + +(defn from-string [data] + (let [config (yaml/parse-string data) + schema (:Schema config)] + (if (not= schema supported-schema) + (util/abort -1 (str "Unsuported configuration schema (read:" schema " expected:" supported-schema ")")) + config))) + +(defn from-file [file] (->> file slurp from-string)) diff --git a/src/chaintool/config/util.clj b/src/chaintool/config/util.clj new file mode 100644 index 0000000..1a87805 --- /dev/null +++ b/src/chaintool/config/util.clj @@ -0,0 +1,42 @@ +;; Copyright London Stock Exchange Group 2016 All Rights Reserved. +;; +;; Licensed under the Apache License, Version 2.0 (the "License"); +;; you may not use this file except in compliance with the License. +;; You may obtain a copy of the License at +;; +;; http://www.apache.org/licenses/LICENSE-2.0 +;; +;; Unless required by applicable law or agreed to in writing, software +;; distributed under the License is distributed on an "AS IS" BASIS, +;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +;; See the License for the specific language governing permissions and +;; limitations under the License. + +(ns chaintool.config.util + (:require [chaintool.util :as util] + [clojure.java.io :as io] + [clojure.zip :as zip] + [chaintool.config.parser :as config.parser]) + (:refer-clojure :exclude [load find])) + +(def configname "chaincode.yaml") + +(defn load [path] + (let [file (io/file path configname)] + (cond + + (not (.isFile file)) + (util/abort -1 (str (.getCanonicalPath file) " not found")) + + :else + (config.parser/from-file file)))) + +(defn load-from-options [options] + (let [path (:path options) + config (load path)] + [path config])) + +(defn compositename [config] + (let [name (:Name config) + version (:Version config)] + (str name "-" version))) diff --git a/src/chaintool/core.clj b/src/chaintool/core.clj new file mode 100644 index 0000000..0d0e3ea --- /dev/null +++ b/src/chaintool/core.clj @@ -0,0 +1,179 @@ +;; Copyright London Stock Exchange Group 2016 All Rights Reserved. +;; +;; Licensed under the Apache License, Version 2.0 (the "License"); +;; you may not use this file except in compliance with the License. +;; You may obtain a copy of the License at +;; +;; http://www.apache.org/licenses/LICENSE-2.0 +;; +;; Unless required by applicable law or agreed to in writing, software +;; distributed under the License is distributed on an "AS IS" BASIS, +;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +;; See the License for the specific language governing permissions and +;; limitations under the License. + +(ns chaintool.core + (:require [chaintool.subcommands.build :as buildcmd] + [chaintool.subcommands.buildcar :as buildcarcmd] + [chaintool.subcommands.clean :as cleancmd] + [chaintool.subcommands.inspect :as inspectcmd] + [chaintool.subcommands.ls :as lscmd] + [chaintool.subcommands.package :as packagecmd] + [chaintool.subcommands.proto :as protocmd] + [chaintool.subcommands.unpack :as unpackcmd] + [chaintool.util :as util] + [clojure.string :as string] + [clojure.tools.cli :refer [parse-opts]] + [slingshot.slingshot :as slingshot]) + (:gen-class)) + +(defn option-merge [& args] (vec (apply concat args))) + +;; options common to all modes, top-level as well as subcommands +(def common-options + [["-h" "--help"]]) + +(def toplevel-options + (option-merge [["-v" "--version" "Print the version and exit"]] + common-options)) + +;; these options are common to subcommands that are expected to operate on a chaincode tree +(def common-path-options + (option-merge [["-p" "--path PATH" "path to chaincode project" :default "./"]] + common-options)) + +(def subcommand-descriptors + [{:name "build" :desc "Build the chaincode project" + :handler buildcmd/run + :options (option-merge [["-o" "--output NAME" "path to the output destination"]] + common-path-options)} + + {:name "buildcar" :desc "Build the chaincode project from a CAR file" + :handler buildcarcmd/run + :arguments "path/to/file.car" + :validate (fn [options arguments] (= (count arguments) 1)) + :options (option-merge [["-o" "--output NAME" "path to the output destination"]] + common-options)} + + {:name "clean" :desc "Clean the chaincode project" + :handler cleancmd/run + :options common-path-options} + + {:name "package" :desc "Package the chaincode into a CAR file for deployment" + :handler packagecmd/run + :options (option-merge [["-o" "--output NAME" "path to the output destination"] + ["-c" "--compress NAME" "compression algorithm to use" :default "gzip"]] + common-path-options)} + + {:name "unpack" :desc "Unpackage a CAR file" + :handler unpackcmd/run + :arguments "path/to/file.car" + :validate (fn [options arguments] (= (count arguments) 1)) + :options (option-merge [["-d" "--directory NAME" "path to the output destination"]] + common-options)} + + {:name "ls" :desc "List the contents of a CAR file" + :handler lscmd/run + :arguments "path/to/file.car" + :validate (fn [options arguments] (= (count arguments) 1)) + :options common-options} + + {:name "proto" :desc "Compiles a CCI file to a .proto" + :handler protocmd/run + :arguments "path/to/file.cci" + :validate (fn [options arguments] (= (count arguments) 1)) + :options (option-merge [["-o" "--output NAME" "path to the output destination"]] + common-options)} + + {:name "inspect" :desc "Retrieves metadata from a running instance" + :handler inspectcmd/run + :validate (fn [options arguments] (:name options)) + :options (option-merge [[nil "--host HOST" "The API hostname of the running fabric" + :default "localhost"] + [nil "--port PORT" "The API port of the running fabric" + :default 5000 + :parse-fn #(Integer/parseInt %) + :validate [#(< 0 % 65536) "Must be a number between 0 and 65536"]] + ["-n" "--name NAME" "The name of the chaincode instance"] + ["-i" "--interfaces PATH" "retrieve interfaces from endpoint and saves them to PATH"]] + common-options)}]) + +;; N.B. the resulting map values are vectors each with a single map as an element +;; +(def subcommands (group-by :name subcommand-descriptors)) + +(defn exit [status msg & rest] + (do + (apply println msg rest) + status)) + +(defn version [] (str "chaintool version: v" util/app-version)) + +(defn prep-usage [msg] (->> msg flatten (string/join \newline))) + +(defn usage [options-summary] + (prep-usage [(version) + "" + "Usage: chaintool [general-options] action [action-options]" + "" + "General Options:" + options-summary + "" + "Actions:" + (map (fn [[_ [{:keys [name desc]}]]] (str " " name " -> " desc)) subcommands) + "" + "(run \"chaintool -h\" for action specific help)"])) + +(defn subcommand-usage [subcommand options-summary] + (prep-usage [(version) + "" + (str "Description: chaintool " (:name subcommand) " - " (:desc subcommand)) + "" + (str "Usage: chaintool " (:name subcommand) " [options] " (when-let [arguments (:arguments subcommand)] arguments)) + "" + "Command Options:" + options-summary + ""])) + +(defn -app [& args] + (let [{:keys [options arguments errors summary]} (parse-opts args toplevel-options :in-order true)] + (cond + + (:help options) + (exit 0 (usage summary)) + + (not= errors nil) + (exit -1 "Error: " (string/join errors)) + + (:version options) + (exit 0 (version)) + + (zero? (count arguments)) + (exit -1 (usage summary)) + + :else + (if-let [[subcommand] (subcommands (first arguments))] + (let [{:keys [options arguments errors summary]} (parse-opts (rest arguments) (:options subcommand))] + (cond + + (:help options) + (exit 0 (subcommand-usage subcommand summary)) + + (not= errors nil) + (exit -1 "Error: " (string/join errors)) + + (and (:validate subcommand) (not ((:validate subcommand) options arguments))) + (exit -1 (subcommand-usage subcommand summary)) + + :else + (slingshot/try+ + ((:handler subcommand) options arguments) + (exit 0 "") + (catch [:type :chaintoolabort] {:keys [msg retval]} + (exit retval (str "Error: " msg)))))) + + ;; unrecognized subcommand + (exit 1 (usage summary)))))) + +(defn -main [& args] + (System/exit (apply -app args))) diff --git a/src/chaintool/inspect/core.clj b/src/chaintool/inspect/core.clj new file mode 100644 index 0000000..5acd92b --- /dev/null +++ b/src/chaintool/inspect/core.clj @@ -0,0 +1,116 @@ +;; Copyright London Stock Exchange Group 2016 All Rights Reserved. +;; +;; Licensed under the Apache License, Version 2.0 (the "License"); +;; you may not use this file except in compliance with the License. +;; You may obtain a copy of the License at +;; +;; http://www.apache.org/licenses/LICENSE-2.0 +;; +;; Unless required by applicable law or agreed to in writing, software +;; distributed under the License is distributed on an "AS IS" BASIS, +;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +;; See the License for the specific language governing permissions and +;; limitations under the License. + +(ns chaintool.inspect.core + (:import [org.hyperledger.chaintool.meta + OrgHyperledgerChaintoolMeta$GetInterfacesParams + OrgHyperledgerChaintoolMeta$Interfaces + OrgHyperledgerChaintoolMeta$InterfaceDescriptor + OrgHyperledgerChaintoolMeta$GetFactsParams + OrgHyperledgerChaintoolMeta$Facts]) + (:require [clojure.java.io :as io] + [clj-http.client :as http] + [flatland.protobuf.core :as fl] + [clojure.data.codec.base64 :as base64] + [cheshire.core :as json] + [chaintool.codecs :as codecs] + [chaintool.util :as util] + [doric.core :as doric])) + +(def GetInterfacesParams (fl/protodef OrgHyperledgerChaintoolMeta$GetInterfacesParams)) +(def Interfaces (fl/protodef OrgHyperledgerChaintoolMeta$Interfaces)) +(def InterfaceDescriptor (fl/protodef OrgHyperledgerChaintoolMeta$InterfaceDescriptor)) +(def GetFactsParams (fl/protodef OrgHyperledgerChaintoolMeta$GetFactsParams)) +(def Facts (fl/protodef OrgHyperledgerChaintoolMeta$Facts)) + +(defn- encode [item] (-> item fl/protobuf-dump base64/encode (String. "UTF-8"))) +(defn- decode [type item] (->> item .getBytes base64/decode (fl/protobuf-load type))) + +(defn- url [{:keys [host port]}] + (str "http://" host ":" port "/chaincode")) + +;;-------------------------------------------------------------------------------------- +;; post - performs a synchronous http/jsonrpc to the server, evaluating to the response +;;-------------------------------------------------------------------------------------- +(defn- post [{:keys [method name func args] :as options}] + (let [body {:jsonrpc "2.0" + :method method + :params {:type 3 + :chaincodeID {:name name} + :ctorMsg {:function func + :args [(encode args)]}} + :id "1"}] + + (http/post (url options) + {:content-type :json + :accept :json + :form-params body}))) + +;;-------------------------------------------------------------------------------------- +;; invokes a "query" operation on top of (post) and evaluates to a successful response +;; or throws an exception +;;-------------------------------------------------------------------------------------- +(defn- query [args] + (let [{:keys [body]} (post (assoc args :method "query")) + response (-> body (json/parse-string true) (select-keys [:result :error]))] + + (if (= (-> response :result :status) "OK") + (->> response :result :message) + ;; else + (util/abort -1 (str response))))) + +;;-------------------------------------------------------------------------------------- +;; get-* operations invoke specific query operations +;;-------------------------------------------------------------------------------------- +(defn- get-interfaces + "gets all interface names declared, optionally with a request to include cci content" + [{:keys [host port] :as options}] + (let [response (query (assoc options + :func "org.hyperledger.chaintool.meta/query/1" + :args (fl/protobuf GetInterfacesParams :IncludeContent (some? (:interfaces options)))))] + + (decode Interfaces response))) + +(defn- get-facts + "gets all fact name/value pairs from the running instance" + [{:keys [host port] :as options}] + (let [response (query (assoc options + :func "org.hyperledger.chaintool.meta/query/3" + :args (fl/protobuf GetFactsParams)))] + + (decode Facts response))) + +;;-------------------------------------------------------------------------------------- +(defn run + "main entrypoint for inspection function" + [options] + + (println "Connecting to" (url options)) + + (let [{:keys [facts]} (get-facts options) + interfaces (get-interfaces options)] + + (println (doric/table [{:name :name :title "Fact"} {:name :value}] facts)) + + (println "Exported Interfaces:") + (dorun (for [{:keys [name data]} (:descriptors interfaces)] + (do + (println "\t-" name) + (when-let [path (:interfaces options)] + (let [is (->> data .newInput (codecs/decompressor "gzip")) + file (io/file path (str name ".cci"))] + + (io/make-parents file) + (with-open [os (io/output-stream file)] + (io/copy is os))))))))) diff --git a/src/chaintool/platforms/api.clj b/src/chaintool/platforms/api.clj new file mode 100644 index 0000000..47c9016 --- /dev/null +++ b/src/chaintool/platforms/api.clj @@ -0,0 +1,23 @@ +;; Copyright London Stock Exchange Group 2016 All Rights Reserved. +;; +;; Licensed under the Apache License, Version 2.0 (the "License"); +;; you may not use this file except in compliance with the License. +;; You may obtain a copy of the License at +;; +;; http://www.apache.org/licenses/LICENSE-2.0 +;; +;; Unless required by applicable law or agreed to in writing, software +;; distributed under the License is distributed on an "AS IS" BASIS, +;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +;; See the License for the specific language governing permissions and +;; limitations under the License. + +(ns chaintool.platforms.api) + +(defprotocol Platform + ;; Compiles the platform + (build [this params]) + ;; Cleans any previous builds of the platform + (clean [this params]) + ;; Packages the chaincode project according to the platform + (package [this params])) diff --git a/src/chaintool/platforms/core.clj b/src/chaintool/platforms/core.clj new file mode 100644 index 0000000..2564faf --- /dev/null +++ b/src/chaintool/platforms/core.clj @@ -0,0 +1,31 @@ +;; Copyright London Stock Exchange Group 2016 All Rights Reserved. +;; +;; Licensed under the Apache License, Version 2.0 (the "License"); +;; you may not use this file except in compliance with the License. +;; You may obtain a copy of the License at +;; +;; http://www.apache.org/licenses/LICENSE-2.0 +;; +;; Unless required by applicable law or agreed to in writing, software +;; distributed under the License is distributed on an "AS IS" BASIS, +;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +;; See the License for the specific language governing permissions and +;; limitations under the License. + +(ns chaintool.platforms.core + (:require [chaintool.platforms.golang.system :as syscc] + [chaintool.platforms.golang.userspace :as golang] + [chaintool.util :as util]) + (:refer-clojure :exclude [find])) + +(def factories + {"org.hyperledger.chaincode.golang" golang/factory + "org.hyperledger.chaincode.system" syscc/factory}) + +(defn find [config] + (let [platform (:Platform config) + name (:Name platform) + version (:Version platform)] + (if-let [factory (factories name)] + (factory version) + (util/abort -1 (str "Unknown platform type: \"" name "\""))))) diff --git a/src/chaintool/platforms/golang/core.clj b/src/chaintool/platforms/golang/core.clj new file mode 100644 index 0000000..d762e53 --- /dev/null +++ b/src/chaintool/platforms/golang/core.clj @@ -0,0 +1,259 @@ +;; Copyright London Stock Exchange Group 2016 All Rights Reserved. +;; +;; Licensed under the Apache License, Version 2.0 (the "License"); +;; you may not use this file except in compliance with the License. +;; You may obtain a copy of the License at +;; +;; http://www.apache.org/licenses/LICENSE-2.0 +;; +;; Unless required by applicable law or agreed to in writing, software +;; distributed under the License is distributed on an "AS IS" BASIS, +;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +;; See the License for the specific language governing permissions and +;; limitations under the License. + +(ns chaintool.platforms.golang.core + (:require [chaintool.build.interface :as intf] + [chaintool.codecs :as codecs] + [chaintool.protobuf.generate :as pb] + [chaintool.util :as util] + [clojure.algo.generic.functor :as algo] + [clojure.java.io :as io] + [clojure.string :as string] + [me.raynes.conch :as conch] + [me.raynes.conch.low-level :as sh]) + (:import (java.util ArrayList) + (org.apache.commons.io.output ByteArrayOutputStream) + (org.stringtemplate.v4 STGroupFile))) + +(conch/programs protoc) +(conch/programs gofmt) +(conch/programs go) + +;; types to map to java objects that string template expects. +;; + +(deftype Function [^String rettype ^String name ^String param ^Integer index]) +(deftype Interface [^String name ^String package ^String packageCamel ^String packagepath ^ArrayList transactions ^ArrayList queries]) +(deftype InterfaceDefinition [^String name ^String bytes]) +(deftype Fact [^String name ^String value]) + +;;------------------------------------------------------------------ +;; helper functions +;;------------------------------------------------------------------ +(defn pkg-to-relpath [path] + (string/replace path #"^_/" "")) + +(defn- package-name [name] (-> name (string/split #"\.") last)) +(defn- package-camel [name] (-> name package-name string/capitalize)) +(defn- package-path [base name] (str (pkg-to-relpath base) "/cci/" (string/replace name "." "/"))) + +;;------------------------------------------------------------------ +;; return a string with composite GOPATH elements, separated by ":" +;; +;; (note that the first entry is where the system will write dependencies +;; retrived by "go get") +;;------------------------------------------------------------------ +(defn buildgopath [path] + (->> [[path "build/deps"] [path "build"] [path] [(System/getenv "GOPATH")]] + (filter #(not= % [nil])) + (map #(.getCanonicalPath (apply io/file %))) + (clojure.string/join ":"))) + +;;------------------------------------------------------------------ +;; X-cmd interfaces: Invoke external commands +;;------------------------------------------------------------------ +(defn- protoc-cmd [_path _proto] + (let [path (->> _path io/file .getCanonicalPath) + go_out (str "--go_out=" path) + proto_path (str "--proto_path=" path) + proto (.getCanonicalPath _proto)] + (println "[PB] protoc" go_out proto_path proto) + (try + (let [result (protoc go_out proto_path proto {:verbose true})] + (println (:stderr result))) + (catch clojure.lang.ExceptionInfo e + (util/abort -1 (-> e ex-data :stderr)))))) + +(defn go-cmd [path env & args] + (println "[GO] go" (apply print-str args)) + (let [gopath (buildgopath path) + _args (vec (concat ["go"] args [:env (merge {"GOPATH" gopath} env)]))] + + (println "\tUsing GOPATH" gopath) + (let [result (apply sh/proc _args) + _ (sh/done result) + stderr (sh/stream-to-string result :err)] + + (if (zero? (sh/exit-code result)) + (println stderr) + (util/abort -1 stderr))))) + +;;----------------------------------------------------------------- +;; buildX - build our ST friendly objects +;;----------------------------------------------------------------- + +(defn- build-function [{:keys [rettype functionName param index]}] + (vector functionName (->Function (when (not= rettype "void") rettype) functionName param index))) + +(defn- build-functions [functions] + (into {} (for [[k v] functions] + (build-function v)))) + +(defn- build-interface [base name interface] + (let [transactions (build-functions (:transactions interface)) + queries (build-functions (:queries interface))] + (vector name (->Interface name (package-name name) (package-camel name) (package-path base name) transactions queries)))) + +(defn- build-interfaces [base interfaces] + (into {} (map (fn [[name interface]] (build-interface base name interface)) interfaces))) + +(defn- build-interface-definition [ipath name] + (let [path (io/file ipath (str name ".cci")) + os (ByteArrayOutputStream.)] + + ;; first compress the file into memory + (with-open [is (io/input-stream path) + compressor (codecs/compressor "gzip" os)] + (io/copy is compressor)) + + ;; compute our new string value for []byte + (let [data (string/join (for [i (seq (.toByteArray os))] (format "\\x%02x" i)))] + ;; finally, construct a new definition object + (vector name (->InterfaceDefinition name data))))) + +(defn- build-interface-definitions [ipath interfaces] + (into {} (map (fn [interface] (build-interface-definition ipath interface)) interfaces))) + +(defn- build-facts [config] + (let [facts [["Application Name" (:Name config)] + ["Application Version" (:Version config)] + ["Platform" (str (-> config :Platform :Name) " version " (-> config :Platform :Version))] + ["Go Version" (-> (go "version") string/trim-newline (string/replace "go version " ""))] + ["Chaintool Version" util/app-version]]] + (into {} (map (fn [[name value]] (vector name (->Fact name value))) facts)))) + +;;----------------------------------------------------------------- +;; generic template rendering +;;----------------------------------------------------------------- +(defn- render-golang [templatename params] + (let [stg (STGroupFile. "generators/golang.stg") + template (.getInstanceOf stg templatename)] + + (dorun (for [[param value] params] (.add template param value))) + (.render template))) + +;;----------------------------------------------------------------- +;; render stub output - compiles the interfaces into the primary +;; golang stub, suitable for writing to a file +;;----------------------------------------------------------------- +(defn- render-primary-stub [base package config interfaces] + (let [functions (algo/fmap intf/getallfunctions interfaces) + provides (build-interfaces base (select-keys functions (intf/getprovides config)))] + + (render-golang "primary" [["base" base] + ["system" package] + ["provides" provides]]))) + +;;----------------------------------------------------------------- +;; render metadata - compiles the interfaces into metadata +;; structures suitable for surfacing via the +;; org.hyperledger.chaintool.meta interface +;;----------------------------------------------------------------- +(defn- render-metadata [config ipath] + (let [facts (build-facts config) + provides (->> config intf/getprovides (build-interface-definitions ipath))] + (render-golang "metadata" [["facts" facts] + ["provides" provides]]))) + +;;----------------------------------------------------------------- +;; write golang source to the filesystem, using gofmt to clean +;; up the generated code +;;----------------------------------------------------------------- +(defn- emit-golang [outputfile content] + (util/truncate-file outputfile content) + (gofmt "-w" (.getCanonicalPath outputfile))) + +;;----------------------------------------------------------------- +;; emit-stub +;;----------------------------------------------------------------- +(defn- emit-stub [base name functions template srcdir filename] + (let [[_ interface] (build-interface base name functions) + content (render-golang template [["base" base] ["intf" interface]]) + output (io/file srcdir (package-path base name) filename)] + + (emit-golang output content))) + +;;----------------------------------------------------------------- +;; emit-server-stub +;;----------------------------------------------------------------- +(defn- emit-server-stub [base name functions srcdir] + (emit-stub base name functions "server" srcdir "server-stub.go")) + +;;----------------------------------------------------------------- +;; emit-proto +;;----------------------------------------------------------------- +(defn- emit-proto [base srcdir [name ast :as interface]] + (let [outputdir (io/file srcdir (package-path base name)) + output (io/file outputdir "interface.proto")] + + ;; emit the .proto file + (pb/to-file output (package-name name) interface) + + ;; execute the protoc compiler to generate golang + (protoc-cmd outputdir output))) + +;;----------------------------------------------------------------- +;; compile-metadata +;;----------------------------------------------------------------- +(def metadata-name "org.hyperledger.chaintool.meta") +(defn- compile-metadata [] + (let [data (->> (str "metadata/" metadata-name ".cci") io/resource slurp)] + (intf/compileintf {:path metadata-name :data data}))) + +;;----------------------------------------------------------------- +;; compile interfaces +;;----------------------------------------------------------------- +(defn- compile-interfaces [ipath config] + (let [interfaces (intf/compile ipath config) + metadata (compile-metadata)] + (assoc interfaces metadata-name metadata))) + +;;----------------------------------------------------------------- +;; generate - generates all of our protobuf/go code based on the +;; config +;;----------------------------------------------------------------- +(defn generate [{:keys [ipath opath config base package] :as params}] + (let [interfaces (compile-interfaces ipath config)] + + ;; generate protobuf output + (dorun (for [interface interfaces] + (emit-proto base opath interface))) + + ;; generate our primary stub + (let [path (io/file opath (pkg-to-relpath base) "ccs")] + (let [content (render-primary-stub base package config interfaces) + filename (io/file path "entrypoint.go")] + (emit-golang filename content)) + (let [content (render-metadata config ipath) + filename (io/file path "metadata.go")] + (emit-golang filename content)) + (let [content (render-golang "api" []) + filename (io/file path "api" "api.go")] + (emit-golang filename content))) + + ;; generate our server stubs + (let [provides (->> config intf/getprovides (filter #(not= % "appinit")) (cons metadata-name))] + + ;; first process all _except_ the appinit interface + (dorun (for [name provides] + (let [functions (intf/getallfunctions (interfaces name))] + (emit-server-stub base name functions opath)))) + + ;; and now special case the appinit interface + (emit-server-stub base "appinit" {:transactions {1 {:rettype "void", :functionName "Init", :param "Init", :index 1, :subType nil, :typeName nil}}} opath)) + + ;; generate our client stubs + (dorun (for [name (intf/getconsumes config)] + (let [functions (intf/getallfunctions (interfaces name))] + (emit-stub base name functions "client" opath "client-stub.go")))))) diff --git a/src/chaintool/platforms/golang/system.clj b/src/chaintool/platforms/golang/system.clj new file mode 100644 index 0000000..deff5f8 --- /dev/null +++ b/src/chaintool/platforms/golang/system.clj @@ -0,0 +1,81 @@ +;; Copyright London Stock Exchange Group 2016 All Rights Reserved. +;; +;; Licensed under the Apache License, Version 2.0 (the "License"); +;; you may not use this file except in compliance with the License. +;; You may obtain a copy of the License at +;; +;; http://www.apache.org/licenses/LICENSE-2.0 +;; +;; Unless required by applicable law or agreed to in writing, software +;; distributed under the License is distributed on an "AS IS" BASIS, +;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +;; See the License for the specific language governing permissions and +;; limitations under the License. + +(ns chaintool.platforms.golang.system + (:require [chaintool.platforms.api :as platforms.api] + [chaintool.platforms.golang.core :refer :all] + [chaintool.util :as util] + [clojure.java.io :as io] + [clojure.string :as string] + [clojure.tools.file-utils :as fileutils]) + (:refer-clojure :exclude [compile])) + +(defn get-package-name [path] + ;; FIXME: This will only work when chaintool is in CWD, need to "cd $path" first + (string/trim-newline (go "list"))) + +(defn subtract-paths [fqpath relpath] + (->> (string/replace (str fqpath) relpath "") io/file .getCanonicalPath str)) + +(defn get-fqp [path] + (->> path io/file .getCanonicalPath)) + +(defn compute-gopath [path pkgname] + (->> pkgname pkg-to-relpath (subtract-paths (get-fqp path)))) + +;;----------------------------------------------------------------- +;; Supports "org.hyperledger.chaincode.system" platform, a golang +;; based environment for system chaincode applications. +;;----------------------------------------------------------------- +(deftype GolangSystemPlatform [] + platforms.api/Platform + + ;;----------------------------------------------------------------- + ;; build - generates all golang platform artifacts within the + ;; default location in the build area + ;;----------------------------------------------------------------- + (build [_ {:keys [path config output]}] + (let [builddir "build" + opath (io/file path builddir) + pkgname (get-package-name path) + gopath (compute-gopath path pkgname)] + + ;; ensure we clean up any previous runs + (fileutils/recursive-delete opath) + + ;; run our code generator + (generate {:base (str pkgname "/" builddir) + :package pkgname + :ipath (io/file path "interfaces") + :opath (io/file gopath) + :config config}) + + (println "Compilation complete"))) + + ;;----------------------------------------------------------------- + ;; clean - cleans up any artifacts from a previous build, if any + ;;----------------------------------------------------------------- + (clean [_ {:keys [path]}] + (fileutils/recursive-delete (io/file path "build"))) + + ;;----------------------------------------------------------------- + ;; package - not supported for system chaincode + ;;----------------------------------------------------------------- + (package [_ _] + (util/abort -1 "unsupported platform operation: package"))) + +(defn factory [version] + (if (= version 1) + (GolangSystemPlatform.) + (util/abort -1 (str "Version " version " not supported")))) diff --git a/src/chaintool/platforms/golang/userspace.clj b/src/chaintool/platforms/golang/userspace.clj new file mode 100644 index 0000000..6d0bdcb --- /dev/null +++ b/src/chaintool/platforms/golang/userspace.clj @@ -0,0 +1,82 @@ +;; Copyright London Stock Exchange Group 2016 All Rights Reserved. +;; +;; Licensed under the Apache License, Version 2.0 (the "License"); +;; you may not use this file except in compliance with the License. +;; You may obtain a copy of the License at +;; +;; http://www.apache.org/licenses/LICENSE-2.0 +;; +;; Unless required by applicable law or agreed to in writing, software +;; distributed under the License is distributed on an "AS IS" BASIS, +;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +;; See the License for the specific language governing permissions and +;; limitations under the License. + +(ns chaintool.platforms.golang.userspace + (:require [chaintool.car.ls :refer :all] + [chaintool.car.write :as car] + [chaintool.config.util :as config] + [chaintool.platforms.api :as platforms.api] + [chaintool.platforms.golang.core :refer :all] + [chaintool.util :as util] + [clojure.java.io :as io] + [clojure.tools.file-utils :as fileutils]) + (:refer-clojure :exclude [compile])) + +;;----------------------------------------------------------------- +;; Supports "org.hyperledger.chaincode.golang" platform, a golang +;; based environment for standard chaincode applications. +;;----------------------------------------------------------------- +(deftype GolangUserspacePlatform [] + platforms.api/Platform + + ;;----------------------------------------------------------------- + ;; build - generates all golang platform artifacts within the + ;; default location in the build area + ;;----------------------------------------------------------------- + (build [_ {:keys [path config output]}] + (let [builddir (io/file path "build")] + + ;; run our code generator + (generate {:base "hyperledger" + :ipath (io/file path "src/interfaces") + :opath (io/file builddir "src") + :config config}) + + ;; install go dependencies + (go-cmd path {} "get" "-d" "-v" "chaincode") + + ;; build the actual code + (let [gobin (io/file builddir "bin")] + (io/make-parents (io/file gobin ".dummy")) + (io/make-parents output) + (go-cmd path {"GOBIN" (.getCanonicalPath gobin)} "build" "-o" (.getCanonicalPath output) "chaincode")) + + (println "Compilation complete"))) + + ;;----------------------------------------------------------------- + ;; clean - cleans up any artifacts from a previous build, if any + ;;----------------------------------------------------------------- + (clean [_ {:keys [path]}] + (fileutils/recursive-delete (io/file path "build"))) + + ;;----------------------------------------------------------------- + ;; package - writes the chaincode package to the filesystem + ;;----------------------------------------------------------------- + (package [_ {:keys [path config outputfile compressiontype]}] + (let [filespec ["src" config/configname]] + + ;; emit header information after we know the file write was successful + (println "Writing CAR to:" (.getCanonicalPath outputfile)) + (println "Using path" path (str filespec)) + + ;; generate the actual file + (car/write path filespec compressiontype outputfile) + + ;; re-use the ls function to display the contents + (ls outputfile)))) + +(defn factory [version] + (if (= version 1) + (GolangUserspacePlatform.) + (util/abort -1 (str "Version " version " not supported")))) diff --git a/src/chaintool/protobuf/generate.clj b/src/chaintool/protobuf/generate.clj new file mode 100644 index 0000000..54efbb2 --- /dev/null +++ b/src/chaintool/protobuf/generate.clj @@ -0,0 +1,152 @@ +;; Copyright London Stock Exchange Group 2016 All Rights Reserved. +;; +;; Licensed under the Apache License, Version 2.0 (the "License"); +;; you may not use this file except in compliance with the License. +;; You may obtain a copy of the License at +;; +;; http://www.apache.org/licenses/LICENSE-2.0 +;; +;; Unless required by applicable law or agreed to in writing, software +;; distributed under the License is distributed on an "AS IS" BASIS, +;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +;; See the License for the specific language governing permissions and +;; limitations under the License. + +(ns chaintool.protobuf.generate + (:require [chaintool.build.interface :as intf] + [chaintool.util :as util] + [clojure.zip :as zip]) + (:import (java.util ArrayList) + (org.stringtemplate.v4 STGroupFile)) + (:refer-clojure :exclude [compile])) + +;; types to map to java objects that string template expects. +;; + +(deftype Field [^String modifier ^String type ^String name ^String index]) +(deftype Definition [^String type ^String name ^ArrayList entries]) +(deftype Entry [^Definition message ^Definition enum ^Field field]) +(deftype Function [^String key ^String rettype ^String name ^String param]) + +(defn- typeconvert [[_ name]] name) + +(defn- find-toplevel-definitions [ast] + (loop [loc (->> ast zip/down zip/right) defs []] + (cond + + (nil? loc) + defs + + :else + (let [type (->> loc zip/down zip/node)] + (recur (zip/right loc) + (if (or (= type :message) (= type :enum)) + (conj defs loc) + defs)))))) + +(def function-class + {:transactions "txn" + :queries "query"}) + +(defn- getallfunctions [ast] + (flatten (for [[type functions] (intf/getallfunctions ast)] + (for [[_ func] functions] + (assoc func :type (function-class type)))))) + +;;----------------------------------------------------------------- +;; buildX - build our ST friendly objects from the AST +;;----------------------------------------------------------------- +(defn- build-msgfield [ast] + (let [field (zip/down ast) + {:keys [modifier type fieldName index]} (intf/getattrs field)] + (->Entry nil nil (->Field modifier (typeconvert type) fieldName index)))) + +(defn- build-enumfield [ast] + (let [field (zip/down ast) + name (->> field zip/right zip/node) + index (->> field zip/right zip/right zip/node)] + (->Field nil nil name index))) + +(declare build-message) +(declare build-enum) + +(defn- build-subentry [ast] + (let [type (->> ast zip/down zip/node)] + (case type + :message (build-message ast) + :enum (build-enum ast) + :field (build-msgfield ast)))) + +(defn- build-message [ast] + (let [elem (zip/down ast) + name (->> elem zip/right zip/node) + first (->> elem zip/right zip/right) + entries (loop [loc first entries {} index 0] + (cond + + (nil? loc) + entries + + :else + (recur (zip/right loc) (assoc entries index (build-subentry loc)) (inc index))))] + (->Entry (->Definition "message" name entries) nil nil))) + +(defn- build-enum [ast] + (let [elem (zip/down ast) + name (->> elem zip/right zip/node) + first (->> elem zip/right zip/right) + entries (loop [loc first entries {} index 0] + (cond + + (nil? loc) + entries + + :else + (recur (zip/right loc) (assoc entries index (build-enumfield loc)) (inc index))))] + (->Entry nil (->Definition "enum" name entries) nil))) + +(defn- build-toplevel-entry [ast] + (let [type (->> ast zip/down zip/node)] + (case type + :message (build-message ast) + :enum (build-enum ast)))) + +(defn- build-toplevel-entries [ast] + (->> ast + find-toplevel-definitions + (mapv build-toplevel-entry) + (interleave (range)) + (partition 2) + (mapv vec) + (into {}))) + +(defn- buildfunction [name {:keys [rettype functionName param index type] :as ast}] + (let [key (str name "/" type "/" index)] + (->Function key rettype functionName param))) + +(defn- buildfunctions [name ast] + (let [funcs (map #(buildfunction name %) (getallfunctions ast))] + (into {} (map #(vector (.key %) %) funcs)))) + +;;----------------------------------------------------------------- +;; to-string - compiles the interface into a protobuf +;; specification in a string, suitable for writing to a file or +;; passing to protoc +;;----------------------------------------------------------------- +(defn to-string [package [name ast]] + (let [definitions (build-toplevel-entries ast) + functions (buildfunctions name ast) + stg (STGroupFile. "generators/proto.stg") + template (.getInstanceOf stg "protobuf")] + + (.add template "package" (if (nil? package) name package)) + (.add template "definitions" definitions) + (.add template "functions" functions) + (.render template))) + +;;----------------------------------------------------------------- +;; to-file - generates a protobuf specification and writes +;; it to a file +;;----------------------------------------------------------------- +(defn to-file [filename package interface] + (util/truncate-file filename (to-string package interface))) diff --git a/src/chaintool/subcommands/build.clj b/src/chaintool/subcommands/build.clj new file mode 100644 index 0000000..202a53e --- /dev/null +++ b/src/chaintool/subcommands/build.clj @@ -0,0 +1,28 @@ +;; Copyright London Stock Exchange Group 2016 All Rights Reserved. +;; +;; Licensed under the Apache License, Version 2.0 (the "License"); +;; you may not use this file except in compliance with the License. +;; You may obtain a copy of the License at +;; +;; http://www.apache.org/licenses/LICENSE-2.0 +;; +;; Unless required by applicable law or agreed to in writing, software +;; distributed under the License is distributed on an "AS IS" BASIS, +;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +;; See the License for the specific language governing permissions and +;; limitations under the License. +(ns chaintool.subcommands.build + (:require [clojure.java.io :as io] + [chaintool.config.util :as config.util] + [chaintool.build.core :as build.core])) + +(defn getoutput [options path config] + (if-let [output (:output options)] + (io/file output) + (io/file path "build/bin" (config.util/compositename config)))) + +(defn run [options args] + (let [[path config] (config.util/load-from-options options) + output (getoutput options path config)] + (println "Build using configuration for " path) + (build.core/compile {:path path :config config :output output}))) diff --git a/src/chaintool/subcommands/buildcar.clj b/src/chaintool/subcommands/buildcar.clj new file mode 100644 index 0000000..f5e2f11 --- /dev/null +++ b/src/chaintool/subcommands/buildcar.clj @@ -0,0 +1,39 @@ +;; Copyright London Stock Exchange Group 2016 All Rights Reserved. +;; +;; Licensed under the Apache License, Version 2.0 (the "License"); +;; you may not use this file except in compliance with the License. +;; You may obtain a copy of the License at +;; +;; http://www.apache.org/licenses/LICENSE-2.0 +;; +;; Unless required by applicable law or agreed to in writing, software +;; distributed under the License is distributed on an "AS IS" BASIS, +;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +;; See the License for the specific language governing permissions and +;; limitations under the License. +(ns chaintool.subcommands.buildcar + (:require [clojure.java.io :as io] + [me.raynes.fs :as fs] + [clojure.tools.file-utils :as fileutils] + [chaintool.util :as util] + [chaintool.config.util :as config.util] + [chaintool.car.read :as car.read] + [chaintool.car.unpack :as car.unpack] + [chaintool.build.core :as build.core])) + +(defn getoutput [options] + (if-let [output (:output options)] + (io/file output) + (util/abort -1 "Missing -o output (see -h for details)"))) + +(defn run [options args] + (let [output (getoutput options) + file (io/file (first args)) + {:keys [index config]} (with-open [is (io/input-stream file)] (car.read/read is)) + workingdir (fs/temp-dir "buildcar-")] + + (car.unpack/unpack index workingdir :false) + (let [config (config.util/load workingdir)] + (println "Building CAR" (.getCanonicalPath file)) + (build.core/compile {:path workingdir :config config :output output}) + (fileutils/recursive-delete (io/file workingdir))))) diff --git a/src/chaintool/subcommands/clean.clj b/src/chaintool/subcommands/clean.clj new file mode 100644 index 0000000..25ded53 --- /dev/null +++ b/src/chaintool/subcommands/clean.clj @@ -0,0 +1,23 @@ +;; Copyright London Stock Exchange Group 2016 All Rights Reserved. +;; +;; Licensed under the Apache License, Version 2.0 (the "License"); +;; you may not use this file except in compliance with the License. +;; You may obtain a copy of the License at +;; +;; http://www.apache.org/licenses/LICENSE-2.0 +;; +;; Unless required by applicable law or agreed to in writing, software +;; distributed under the License is distributed on an "AS IS" BASIS, +;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +;; See the License for the specific language governing permissions and +;; limitations under the License. +(ns chaintool.subcommands.clean + (:require [chaintool.config.util :as config.util] + [chaintool.platforms.core :as platforms.core] + [chaintool.platforms.api :as platforms.api])) + +(defn run [options args] + (let [[path config] (config.util/load-from-options options)] + (when-let [platform (platforms.core/find config)] + (println "Cleaning project found at " path) + (platforms.api/clean platform {:path path})))) diff --git a/src/chaintool/subcommands/inspect.clj b/src/chaintool/subcommands/inspect.clj new file mode 100644 index 0000000..e4a89ce --- /dev/null +++ b/src/chaintool/subcommands/inspect.clj @@ -0,0 +1,26 @@ +;; Copyright London Stock Exchange Group 2016 All Rights Reserved. +;; +;; Licensed under the Apache License, Version 2.0 (the "License"); +;; you may not use this file except in compliance with the License. +;; You may obtain a copy of the License at +;; +;; http://www.apache.org/licenses/LICENSE-2.0 +;; +;; Unless required by applicable law or agreed to in writing, software +;; distributed under the License is distributed on an "AS IS" BASIS, +;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +;; See the License for the specific language governing permissions and +;; limitations under the License. + +(ns chaintool.subcommands.inspect + (:require [chaintool.inspect.core :as inspect] + [clojure.java.io :as io])) + +(defn getoutputdir [options] + (if-let [path (:interfaces options)] + (io/file path) + (io/file "."))) + +(defn run [options args] + (let [output (getoutputdir options)] + (inspect/run (assoc options :output output)))) diff --git a/src/chaintool/subcommands/ls.clj b/src/chaintool/subcommands/ls.clj new file mode 100644 index 0000000..73ab616 --- /dev/null +++ b/src/chaintool/subcommands/ls.clj @@ -0,0 +1,21 @@ +;; Copyright London Stock Exchange Group 2016 All Rights Reserved. +;; +;; Licensed under the Apache License, Version 2.0 (the "License"); +;; you may not use this file except in compliance with the License. +;; You may obtain a copy of the License at +;; +;; http://www.apache.org/licenses/LICENSE-2.0 +;; +;; Unless required by applicable law or agreed to in writing, software +;; distributed under the License is distributed on an "AS IS" BASIS, +;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +;; See the License for the specific language governing permissions and +;; limitations under the License. + +(ns chaintool.subcommands.ls + (:require [chaintool.car.ls :as car] + [clojure.java.io :as io])) + +(defn run [options args] + (let [file (io/file (first args))] + (car/ls file))) diff --git a/src/chaintool/subcommands/package.clj b/src/chaintool/subcommands/package.clj new file mode 100644 index 0000000..582a50f --- /dev/null +++ b/src/chaintool/subcommands/package.clj @@ -0,0 +1,35 @@ +;; Copyright London Stock Exchange Group 2016 All Rights Reserved. +;; +;; Licensed under the Apache License, Version 2.0 (the "License"); +;; you may not use this file except in compliance with the License. +;; You may obtain a copy of the License at +;; +;; http://www.apache.org/licenses/LICENSE-2.0 +;; +;; Unless required by applicable law or agreed to in writing, software +;; distributed under the License is distributed on an "AS IS" BASIS, +;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +;; See the License for the specific language governing permissions and +;; limitations under the License. +(ns chaintool.subcommands.package + (:require [chaintool.config.util :as config] + [chaintool.platforms.core :as platforms.core] + [chaintool.platforms.api :as platforms.api] + [clojure.java.io :as io] + [clojure.tools.cli :refer [parse-opts]])) + +(defn getoutputfile [options path config] + (if-let [output (:output options)] + (io/file output) + (io/file path "build" (str (config/compositename config) ".car")))) + +(defn run [options args] + (let [[path config] (config/load-from-options options) + compressiontype (:compress options) + outputfile (getoutputfile options path config) + platform (platforms.core/find config)] + + (platforms.api/package platform {:path path + :config config + :compressiontype compressiontype + :outputfile outputfile}))) diff --git a/src/chaintool/subcommands/proto.clj b/src/chaintool/subcommands/proto.clj new file mode 100644 index 0000000..3c67d29 --- /dev/null +++ b/src/chaintool/subcommands/proto.clj @@ -0,0 +1,32 @@ +;; Copyright London Stock Exchange Group 2016 All Rights Reserved. +;; +;; Licensed under the Apache License, Version 2.0 (the "License"); +;; you may not use this file except in compliance with the License. +;; You may obtain a copy of the License at +;; +;; http://www.apache.org/licenses/LICENSE-2.0 +;; +;; Unless required by applicable law or agreed to in writing, software +;; distributed under the License is distributed on an "AS IS" BASIS, +;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +;; See the License for the specific language governing permissions and +;; limitations under the License. + +(ns chaintool.subcommands.proto + (:require [chaintool.build.interface :as intf] + [chaintool.protobuf.generate :as pb] + [chaintool.util :as util] + [clojure.java.io :as io] + [me.raynes.fs :as fs])) + +(defn getoutputfile [options input name] + (if-let [output (:output options)] + (io/file output) + (io/file (str name ".proto")))) + +(defn run [options args] + (let [input (io/file (first args)) + name (fs/base-name input true) + output (getoutputfile options input name) + intf (intf/compileintf {:path (.getCanonicalPath input) :data (util/safe-slurp input)})] + (pb/to-file output name [name intf]))) diff --git a/src/chaintool/subcommands/unpack.clj b/src/chaintool/subcommands/unpack.clj new file mode 100644 index 0000000..a9919ee --- /dev/null +++ b/src/chaintool/subcommands/unpack.clj @@ -0,0 +1,37 @@ +;; Copyright London Stock Exchange Group 2016 All Rights Reserved. +;; +;; Licensed under the Apache License, Version 2.0 (the "License"); +;; you may not use this file except in compliance with the License. +;; You may obtain a copy of the License at +;; +;; http://www.apache.org/licenses/LICENSE-2.0 +;; +;; Unless required by applicable law or agreed to in writing, software +;; distributed under the License is distributed on an "AS IS" BASIS, +;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +;; See the License for the specific language governing permissions and +;; limitations under the License. + +(ns chaintool.subcommands.unpack + (:require [chaintool.config.util :as config] + [chaintool.util :as util] + [chaintool.car.read :as car.read] + [chaintool.car.unpack :as car.unpack] + [clojure.java.io :as io])) + +(defn getoutputdir [options config] + (if-let [dir (:directory options)] + (io/file dir) + (io/file "./" (str (config/compositename config))))) + +(defn run [options args] + (let [file (io/file (first args)) + {:keys [index config]} (with-open [is (io/input-stream file)] (car.read/read is)) + outputdir (getoutputdir options config)] + + (when (.exists outputdir) + (util/abort -1 (str "output directory " (.getCanonicalPath outputdir) " exists"))) + + (println "Unpacking CAR to:" (.getCanonicalPath outputdir)) + (println) + (car.unpack/unpack index outputdir :true))) diff --git a/src/chaintool/util.clj b/src/chaintool/util.clj new file mode 100644 index 0000000..5beae41 --- /dev/null +++ b/src/chaintool/util.clj @@ -0,0 +1,37 @@ +;; Copyright London Stock Exchange Group 2016 All Rights Reserved. +;; +;; Licensed under the Apache License, Version 2.0 (the "License"); +;; you may not use this file except in compliance with the License. +;; You may obtain a copy of the License at +;; +;; http://www.apache.org/licenses/LICENSE-2.0 +;; +;; Unless required by applicable law or agreed to in writing, software +;; distributed under the License is distributed on an "AS IS" BASIS, +;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +;; See the License for the specific language governing permissions and +;; limitations under the License. + +(ns chaintool.util + (:require [clojure.java.io :as io] + [slingshot.slingshot :as slingshot])) + +(def app-version (System/getProperty "chaintool.version")) + +(defn truncate-file [filename content] + + ;; ensure the path exists + (io/make-parents filename) + + ;; and blast it out to the filesystem + (spit filename content :truncate true)) + +;; throws an exception that should unwind us all the way to the core/main +;; function and exit cleanly with an error message rather than a stacktrace, etc +(defn abort [retval msg] + (slingshot/throw+ {:type :chaintoolabort :retval retval :msg msg})) + +(defn safe-slurp [file] + (if (.exists file) + (slurp file) + (abort -1 (str (.getCanonicalPath file) " not found")))) diff --git a/src/org/hyperledger/chaintool/meta/OrgHyperledgerChaintoolMeta.java b/src/org/hyperledger/chaintool/meta/OrgHyperledgerChaintoolMeta.java new file mode 100644 index 0000000..36b8bd8 --- /dev/null +++ b/src/org/hyperledger/chaintool/meta/OrgHyperledgerChaintoolMeta.java @@ -0,0 +1,3712 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: target/org.hyperledger.chaintool.meta.proto + +package org.hyperledger.chaintool.meta; + +public final class OrgHyperledgerChaintoolMeta { + private OrgHyperledgerChaintoolMeta() {} + public static void registerAllExtensions( + com.google.protobuf.ExtensionRegistry registry) { + } + public interface InterfaceDescriptorOrBuilder extends + // @@protoc_insertion_point(interface_extends:org.hyperledger.chaintool.meta.InterfaceDescriptor) + com.google.protobuf.MessageOrBuilder { + + /** + * optional string name = 1; + */ + java.lang.String getName(); + /** + * optional string name = 1; + */ + com.google.protobuf.ByteString + getNameBytes(); + + /** + * optional bytes data = 2; + */ + com.google.protobuf.ByteString getData(); + } + /** + * Protobuf type {@code org.hyperledger.chaintool.meta.InterfaceDescriptor} + */ + public static final class InterfaceDescriptor extends + com.google.protobuf.GeneratedMessage implements + // @@protoc_insertion_point(message_implements:org.hyperledger.chaintool.meta.InterfaceDescriptor) + InterfaceDescriptorOrBuilder { + // Use InterfaceDescriptor.newBuilder() to construct. + private InterfaceDescriptor(com.google.protobuf.GeneratedMessage.Builder builder) { + super(builder); + } + private InterfaceDescriptor() { + name_ = ""; + data_ = com.google.protobuf.ByteString.EMPTY; + } + + @java.lang.Override + public final com.google.protobuf.UnknownFieldSet + getUnknownFields() { + return com.google.protobuf.UnknownFieldSet.getDefaultInstance(); + } + private InterfaceDescriptor( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) { + this(); + int mutable_bitField0_ = 0; + try { + boolean done = false; + while (!done) { + int tag = input.readTag(); + switch (tag) { + case 0: + done = true; + break; + default: { + if (!input.skipField(tag)) { + done = true; + } + break; + } + case 10: { + java.lang.String s = input.readStringRequireUtf8(); + + name_ = s; + break; + } + case 18: { + + data_ = input.readBytes(); + break; + } + } + } + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw new RuntimeException(e.setUnfinishedMessage(this)); + } catch (java.io.IOException e) { + throw new RuntimeException( + new com.google.protobuf.InvalidProtocolBufferException( + e.getMessage()).setUnfinishedMessage(this)); + } finally { + makeExtensionsImmutable(); + } + } + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.internal_static_org_hyperledger_chaintool_meta_InterfaceDescriptor_descriptor; + } + + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.internal_static_org_hyperledger_chaintool_meta_InterfaceDescriptor_fieldAccessorTable + .ensureFieldAccessorsInitialized( + org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.InterfaceDescriptor.class, org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.InterfaceDescriptor.Builder.class); + } + + public static final int NAME_FIELD_NUMBER = 1; + private volatile java.lang.Object name_; + /** + * optional string name = 1; + */ + public java.lang.String getName() { + java.lang.Object ref = name_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + name_ = s; + return s; + } + } + /** + * optional string name = 1; + */ + public com.google.protobuf.ByteString + getNameBytes() { + java.lang.Object ref = name_; + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + name_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + public static final int DATA_FIELD_NUMBER = 2; + private com.google.protobuf.ByteString data_; + /** + * optional bytes data = 2; + */ + public com.google.protobuf.ByteString getData() { + return data_; + } + + private byte memoizedIsInitialized = -1; + public final boolean isInitialized() { + byte isInitialized = memoizedIsInitialized; + if (isInitialized == 1) return true; + if (isInitialized == 0) return false; + + memoizedIsInitialized = 1; + return true; + } + + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + if (!getNameBytes().isEmpty()) { + com.google.protobuf.GeneratedMessage.writeString(output, 1, name_); + } + if (!data_.isEmpty()) { + output.writeBytes(2, data_); + } + } + + public int getSerializedSize() { + int size = memoizedSize; + if (size != -1) return size; + + size = 0; + if (!getNameBytes().isEmpty()) { + size += com.google.protobuf.GeneratedMessage.computeStringSize(1, name_); + } + if (!data_.isEmpty()) { + size += com.google.protobuf.CodedOutputStream + .computeBytesSize(2, data_); + } + memoizedSize = size; + return size; + } + + private static final long serialVersionUID = 0L; + public static org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.InterfaceDescriptor parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.InterfaceDescriptor parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.InterfaceDescriptor parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.InterfaceDescriptor parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.InterfaceDescriptor parseFrom(java.io.InputStream input) + throws java.io.IOException { + return PARSER.parseFrom(input); + } + public static org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.InterfaceDescriptor parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return PARSER.parseFrom(input, extensionRegistry); + } + public static org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.InterfaceDescriptor parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + return PARSER.parseDelimitedFrom(input); + } + public static org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.InterfaceDescriptor parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return PARSER.parseDelimitedFrom(input, extensionRegistry); + } + public static org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.InterfaceDescriptor parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return PARSER.parseFrom(input); + } + public static org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.InterfaceDescriptor parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return PARSER.parseFrom(input, extensionRegistry); + } + + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder() { + return DEFAULT_INSTANCE.toBuilder(); + } + public static Builder newBuilder(org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.InterfaceDescriptor prototype) { + return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); + } + public Builder toBuilder() { + return this == DEFAULT_INSTANCE + ? new Builder() : new Builder().mergeFrom(this); + } + + @java.lang.Override + protected Builder newBuilderForType( + com.google.protobuf.GeneratedMessage.BuilderParent parent) { + Builder builder = new Builder(parent); + return builder; + } + /** + * Protobuf type {@code org.hyperledger.chaintool.meta.InterfaceDescriptor} + */ + public static final class Builder extends + com.google.protobuf.GeneratedMessage.Builder implements + // @@protoc_insertion_point(builder_implements:org.hyperledger.chaintool.meta.InterfaceDescriptor) + org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.InterfaceDescriptorOrBuilder { + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.internal_static_org_hyperledger_chaintool_meta_InterfaceDescriptor_descriptor; + } + + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.internal_static_org_hyperledger_chaintool_meta_InterfaceDescriptor_fieldAccessorTable + .ensureFieldAccessorsInitialized( + org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.InterfaceDescriptor.class, org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.InterfaceDescriptor.Builder.class); + } + + // Construct using org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.InterfaceDescriptor.newBuilder() + private Builder() { + maybeForceBuilderInitialization(); + } + + private Builder( + com.google.protobuf.GeneratedMessage.BuilderParent parent) { + super(parent); + maybeForceBuilderInitialization(); + } + private void maybeForceBuilderInitialization() { + if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) { + } + } + public Builder clear() { + super.clear(); + name_ = ""; + + data_ = com.google.protobuf.ByteString.EMPTY; + + return this; + } + + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.internal_static_org_hyperledger_chaintool_meta_InterfaceDescriptor_descriptor; + } + + public org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.InterfaceDescriptor getDefaultInstanceForType() { + return org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.InterfaceDescriptor.getDefaultInstance(); + } + + public org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.InterfaceDescriptor build() { + org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.InterfaceDescriptor result = buildPartial(); + if (!result.isInitialized()) { + throw newUninitializedMessageException(result); + } + return result; + } + + public org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.InterfaceDescriptor buildPartial() { + org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.InterfaceDescriptor result = new org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.InterfaceDescriptor(this); + result.name_ = name_; + result.data_ = data_; + onBuilt(); + return result; + } + + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.InterfaceDescriptor) { + return mergeFrom((org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.InterfaceDescriptor)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.InterfaceDescriptor other) { + if (other == org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.InterfaceDescriptor.getDefaultInstance()) return this; + if (!other.getName().isEmpty()) { + name_ = other.name_; + onChanged(); + } + if (other.getData() != com.google.protobuf.ByteString.EMPTY) { + setData(other.getData()); + } + onChanged(); + return this; + } + + public final boolean isInitialized() { + return true; + } + + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.InterfaceDescriptor parsedMessage = null; + try { + parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry); + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + parsedMessage = (org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.InterfaceDescriptor) e.getUnfinishedMessage(); + throw e; + } finally { + if (parsedMessage != null) { + mergeFrom(parsedMessage); + } + } + return this; + } + + private java.lang.Object name_ = ""; + /** + * optional string name = 1; + */ + public java.lang.String getName() { + java.lang.Object ref = name_; + if (!(ref instanceof java.lang.String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + name_ = s; + return s; + } else { + return (java.lang.String) ref; + } + } + /** + * optional string name = 1; + */ + public com.google.protobuf.ByteString + getNameBytes() { + java.lang.Object ref = name_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + name_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + * optional string name = 1; + */ + public Builder setName( + java.lang.String value) { + if (value == null) { + throw new NullPointerException(); + } + + name_ = value; + onChanged(); + return this; + } + /** + * optional string name = 1; + */ + public Builder clearName() { + + name_ = getDefaultInstance().getName(); + onChanged(); + return this; + } + /** + * optional string name = 1; + */ + public Builder setNameBytes( + com.google.protobuf.ByteString value) { + if (value == null) { + throw new NullPointerException(); + } + checkByteStringIsUtf8(value); + + name_ = value; + onChanged(); + return this; + } + + private com.google.protobuf.ByteString data_ = com.google.protobuf.ByteString.EMPTY; + /** + * optional bytes data = 2; + */ + public com.google.protobuf.ByteString getData() { + return data_; + } + /** + * optional bytes data = 2; + */ + public Builder setData(com.google.protobuf.ByteString value) { + if (value == null) { + throw new NullPointerException(); + } + + data_ = value; + onChanged(); + return this; + } + /** + * optional bytes data = 2; + */ + public Builder clearData() { + + data_ = getDefaultInstance().getData(); + onChanged(); + return this; + } + public final Builder setUnknownFields( + final com.google.protobuf.UnknownFieldSet unknownFields) { + return this; + } + + public final Builder mergeUnknownFields( + final com.google.protobuf.UnknownFieldSet unknownFields) { + return this; + } + + + // @@protoc_insertion_point(builder_scope:org.hyperledger.chaintool.meta.InterfaceDescriptor) + } + + // @@protoc_insertion_point(class_scope:org.hyperledger.chaintool.meta.InterfaceDescriptor) + private static final org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.InterfaceDescriptor DEFAULT_INSTANCE; + static { + DEFAULT_INSTANCE = new org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.InterfaceDescriptor(); + } + + public static org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.InterfaceDescriptor getDefaultInstance() { + return DEFAULT_INSTANCE; + } + + private static final com.google.protobuf.Parser + PARSER = new com.google.protobuf.AbstractParser() { + public InterfaceDescriptor parsePartialFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + try { + return new InterfaceDescriptor(input, extensionRegistry); + } catch (RuntimeException e) { + if (e.getCause() instanceof + com.google.protobuf.InvalidProtocolBufferException) { + throw (com.google.protobuf.InvalidProtocolBufferException) + e.getCause(); + } + throw e; + } + } + }; + + public static com.google.protobuf.Parser parser() { + return PARSER; + } + + @java.lang.Override + public com.google.protobuf.Parser getParserForType() { + return PARSER; + } + + public org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.InterfaceDescriptor getDefaultInstanceForType() { + return DEFAULT_INSTANCE; + } + + } + + public interface InterfacesOrBuilder extends + // @@protoc_insertion_point(interface_extends:org.hyperledger.chaintool.meta.Interfaces) + com.google.protobuf.MessageOrBuilder { + + /** + * repeated .org.hyperledger.chaintool.meta.InterfaceDescriptor descriptors = 1; + */ + java.util.List + getDescriptorsList(); + /** + * repeated .org.hyperledger.chaintool.meta.InterfaceDescriptor descriptors = 1; + */ + org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.InterfaceDescriptor getDescriptors(int index); + /** + * repeated .org.hyperledger.chaintool.meta.InterfaceDescriptor descriptors = 1; + */ + int getDescriptorsCount(); + /** + * repeated .org.hyperledger.chaintool.meta.InterfaceDescriptor descriptors = 1; + */ + java.util.List + getDescriptorsOrBuilderList(); + /** + * repeated .org.hyperledger.chaintool.meta.InterfaceDescriptor descriptors = 1; + */ + org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.InterfaceDescriptorOrBuilder getDescriptorsOrBuilder( + int index); + } + /** + * Protobuf type {@code org.hyperledger.chaintool.meta.Interfaces} + */ + public static final class Interfaces extends + com.google.protobuf.GeneratedMessage implements + // @@protoc_insertion_point(message_implements:org.hyperledger.chaintool.meta.Interfaces) + InterfacesOrBuilder { + // Use Interfaces.newBuilder() to construct. + private Interfaces(com.google.protobuf.GeneratedMessage.Builder builder) { + super(builder); + } + private Interfaces() { + descriptors_ = java.util.Collections.emptyList(); + } + + @java.lang.Override + public final com.google.protobuf.UnknownFieldSet + getUnknownFields() { + return com.google.protobuf.UnknownFieldSet.getDefaultInstance(); + } + private Interfaces( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) { + this(); + int mutable_bitField0_ = 0; + try { + boolean done = false; + while (!done) { + int tag = input.readTag(); + switch (tag) { + case 0: + done = true; + break; + default: { + if (!input.skipField(tag)) { + done = true; + } + break; + } + case 10: { + if (!((mutable_bitField0_ & 0x00000001) == 0x00000001)) { + descriptors_ = new java.util.ArrayList(); + mutable_bitField0_ |= 0x00000001; + } + descriptors_.add(input.readMessage(org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.InterfaceDescriptor.parser(), extensionRegistry)); + break; + } + } + } + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw new RuntimeException(e.setUnfinishedMessage(this)); + } catch (java.io.IOException e) { + throw new RuntimeException( + new com.google.protobuf.InvalidProtocolBufferException( + e.getMessage()).setUnfinishedMessage(this)); + } finally { + if (((mutable_bitField0_ & 0x00000001) == 0x00000001)) { + descriptors_ = java.util.Collections.unmodifiableList(descriptors_); + } + makeExtensionsImmutable(); + } + } + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.internal_static_org_hyperledger_chaintool_meta_Interfaces_descriptor; + } + + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.internal_static_org_hyperledger_chaintool_meta_Interfaces_fieldAccessorTable + .ensureFieldAccessorsInitialized( + org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.Interfaces.class, org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.Interfaces.Builder.class); + } + + public static final int DESCRIPTORS_FIELD_NUMBER = 1; + private java.util.List descriptors_; + /** + * repeated .org.hyperledger.chaintool.meta.InterfaceDescriptor descriptors = 1; + */ + public java.util.List getDescriptorsList() { + return descriptors_; + } + /** + * repeated .org.hyperledger.chaintool.meta.InterfaceDescriptor descriptors = 1; + */ + public java.util.List + getDescriptorsOrBuilderList() { + return descriptors_; + } + /** + * repeated .org.hyperledger.chaintool.meta.InterfaceDescriptor descriptors = 1; + */ + public int getDescriptorsCount() { + return descriptors_.size(); + } + /** + * repeated .org.hyperledger.chaintool.meta.InterfaceDescriptor descriptors = 1; + */ + public org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.InterfaceDescriptor getDescriptors(int index) { + return descriptors_.get(index); + } + /** + * repeated .org.hyperledger.chaintool.meta.InterfaceDescriptor descriptors = 1; + */ + public org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.InterfaceDescriptorOrBuilder getDescriptorsOrBuilder( + int index) { + return descriptors_.get(index); + } + + private byte memoizedIsInitialized = -1; + public final boolean isInitialized() { + byte isInitialized = memoizedIsInitialized; + if (isInitialized == 1) return true; + if (isInitialized == 0) return false; + + memoizedIsInitialized = 1; + return true; + } + + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + for (int i = 0; i < descriptors_.size(); i++) { + output.writeMessage(1, descriptors_.get(i)); + } + } + + public int getSerializedSize() { + int size = memoizedSize; + if (size != -1) return size; + + size = 0; + for (int i = 0; i < descriptors_.size(); i++) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(1, descriptors_.get(i)); + } + memoizedSize = size; + return size; + } + + private static final long serialVersionUID = 0L; + public static org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.Interfaces parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.Interfaces parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.Interfaces parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.Interfaces parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.Interfaces parseFrom(java.io.InputStream input) + throws java.io.IOException { + return PARSER.parseFrom(input); + } + public static org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.Interfaces parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return PARSER.parseFrom(input, extensionRegistry); + } + public static org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.Interfaces parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + return PARSER.parseDelimitedFrom(input); + } + public static org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.Interfaces parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return PARSER.parseDelimitedFrom(input, extensionRegistry); + } + public static org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.Interfaces parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return PARSER.parseFrom(input); + } + public static org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.Interfaces parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return PARSER.parseFrom(input, extensionRegistry); + } + + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder() { + return DEFAULT_INSTANCE.toBuilder(); + } + public static Builder newBuilder(org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.Interfaces prototype) { + return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); + } + public Builder toBuilder() { + return this == DEFAULT_INSTANCE + ? new Builder() : new Builder().mergeFrom(this); + } + + @java.lang.Override + protected Builder newBuilderForType( + com.google.protobuf.GeneratedMessage.BuilderParent parent) { + Builder builder = new Builder(parent); + return builder; + } + /** + * Protobuf type {@code org.hyperledger.chaintool.meta.Interfaces} + */ + public static final class Builder extends + com.google.protobuf.GeneratedMessage.Builder implements + // @@protoc_insertion_point(builder_implements:org.hyperledger.chaintool.meta.Interfaces) + org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.InterfacesOrBuilder { + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.internal_static_org_hyperledger_chaintool_meta_Interfaces_descriptor; + } + + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.internal_static_org_hyperledger_chaintool_meta_Interfaces_fieldAccessorTable + .ensureFieldAccessorsInitialized( + org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.Interfaces.class, org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.Interfaces.Builder.class); + } + + // Construct using org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.Interfaces.newBuilder() + private Builder() { + maybeForceBuilderInitialization(); + } + + private Builder( + com.google.protobuf.GeneratedMessage.BuilderParent parent) { + super(parent); + maybeForceBuilderInitialization(); + } + private void maybeForceBuilderInitialization() { + if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) { + getDescriptorsFieldBuilder(); + } + } + public Builder clear() { + super.clear(); + if (descriptorsBuilder_ == null) { + descriptors_ = java.util.Collections.emptyList(); + bitField0_ = (bitField0_ & ~0x00000001); + } else { + descriptorsBuilder_.clear(); + } + return this; + } + + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.internal_static_org_hyperledger_chaintool_meta_Interfaces_descriptor; + } + + public org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.Interfaces getDefaultInstanceForType() { + return org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.Interfaces.getDefaultInstance(); + } + + public org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.Interfaces build() { + org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.Interfaces result = buildPartial(); + if (!result.isInitialized()) { + throw newUninitializedMessageException(result); + } + return result; + } + + public org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.Interfaces buildPartial() { + org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.Interfaces result = new org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.Interfaces(this); + int from_bitField0_ = bitField0_; + if (descriptorsBuilder_ == null) { + if (((bitField0_ & 0x00000001) == 0x00000001)) { + descriptors_ = java.util.Collections.unmodifiableList(descriptors_); + bitField0_ = (bitField0_ & ~0x00000001); + } + result.descriptors_ = descriptors_; + } else { + result.descriptors_ = descriptorsBuilder_.build(); + } + onBuilt(); + return result; + } + + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.Interfaces) { + return mergeFrom((org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.Interfaces)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.Interfaces other) { + if (other == org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.Interfaces.getDefaultInstance()) return this; + if (descriptorsBuilder_ == null) { + if (!other.descriptors_.isEmpty()) { + if (descriptors_.isEmpty()) { + descriptors_ = other.descriptors_; + bitField0_ = (bitField0_ & ~0x00000001); + } else { + ensureDescriptorsIsMutable(); + descriptors_.addAll(other.descriptors_); + } + onChanged(); + } + } else { + if (!other.descriptors_.isEmpty()) { + if (descriptorsBuilder_.isEmpty()) { + descriptorsBuilder_.dispose(); + descriptorsBuilder_ = null; + descriptors_ = other.descriptors_; + bitField0_ = (bitField0_ & ~0x00000001); + descriptorsBuilder_ = + com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders ? + getDescriptorsFieldBuilder() : null; + } else { + descriptorsBuilder_.addAllMessages(other.descriptors_); + } + } + } + onChanged(); + return this; + } + + public final boolean isInitialized() { + return true; + } + + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.Interfaces parsedMessage = null; + try { + parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry); + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + parsedMessage = (org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.Interfaces) e.getUnfinishedMessage(); + throw e; + } finally { + if (parsedMessage != null) { + mergeFrom(parsedMessage); + } + } + return this; + } + private int bitField0_; + + private java.util.List descriptors_ = + java.util.Collections.emptyList(); + private void ensureDescriptorsIsMutable() { + if (!((bitField0_ & 0x00000001) == 0x00000001)) { + descriptors_ = new java.util.ArrayList(descriptors_); + bitField0_ |= 0x00000001; + } + } + + private com.google.protobuf.RepeatedFieldBuilder< + org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.InterfaceDescriptor, org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.InterfaceDescriptor.Builder, org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.InterfaceDescriptorOrBuilder> descriptorsBuilder_; + + /** + * repeated .org.hyperledger.chaintool.meta.InterfaceDescriptor descriptors = 1; + */ + public java.util.List getDescriptorsList() { + if (descriptorsBuilder_ == null) { + return java.util.Collections.unmodifiableList(descriptors_); + } else { + return descriptorsBuilder_.getMessageList(); + } + } + /** + * repeated .org.hyperledger.chaintool.meta.InterfaceDescriptor descriptors = 1; + */ + public int getDescriptorsCount() { + if (descriptorsBuilder_ == null) { + return descriptors_.size(); + } else { + return descriptorsBuilder_.getCount(); + } + } + /** + * repeated .org.hyperledger.chaintool.meta.InterfaceDescriptor descriptors = 1; + */ + public org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.InterfaceDescriptor getDescriptors(int index) { + if (descriptorsBuilder_ == null) { + return descriptors_.get(index); + } else { + return descriptorsBuilder_.getMessage(index); + } + } + /** + * repeated .org.hyperledger.chaintool.meta.InterfaceDescriptor descriptors = 1; + */ + public Builder setDescriptors( + int index, org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.InterfaceDescriptor value) { + if (descriptorsBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + ensureDescriptorsIsMutable(); + descriptors_.set(index, value); + onChanged(); + } else { + descriptorsBuilder_.setMessage(index, value); + } + return this; + } + /** + * repeated .org.hyperledger.chaintool.meta.InterfaceDescriptor descriptors = 1; + */ + public Builder setDescriptors( + int index, org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.InterfaceDescriptor.Builder builderForValue) { + if (descriptorsBuilder_ == null) { + ensureDescriptorsIsMutable(); + descriptors_.set(index, builderForValue.build()); + onChanged(); + } else { + descriptorsBuilder_.setMessage(index, builderForValue.build()); + } + return this; + } + /** + * repeated .org.hyperledger.chaintool.meta.InterfaceDescriptor descriptors = 1; + */ + public Builder addDescriptors(org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.InterfaceDescriptor value) { + if (descriptorsBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + ensureDescriptorsIsMutable(); + descriptors_.add(value); + onChanged(); + } else { + descriptorsBuilder_.addMessage(value); + } + return this; + } + /** + * repeated .org.hyperledger.chaintool.meta.InterfaceDescriptor descriptors = 1; + */ + public Builder addDescriptors( + int index, org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.InterfaceDescriptor value) { + if (descriptorsBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + ensureDescriptorsIsMutable(); + descriptors_.add(index, value); + onChanged(); + } else { + descriptorsBuilder_.addMessage(index, value); + } + return this; + } + /** + * repeated .org.hyperledger.chaintool.meta.InterfaceDescriptor descriptors = 1; + */ + public Builder addDescriptors( + org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.InterfaceDescriptor.Builder builderForValue) { + if (descriptorsBuilder_ == null) { + ensureDescriptorsIsMutable(); + descriptors_.add(builderForValue.build()); + onChanged(); + } else { + descriptorsBuilder_.addMessage(builderForValue.build()); + } + return this; + } + /** + * repeated .org.hyperledger.chaintool.meta.InterfaceDescriptor descriptors = 1; + */ + public Builder addDescriptors( + int index, org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.InterfaceDescriptor.Builder builderForValue) { + if (descriptorsBuilder_ == null) { + ensureDescriptorsIsMutable(); + descriptors_.add(index, builderForValue.build()); + onChanged(); + } else { + descriptorsBuilder_.addMessage(index, builderForValue.build()); + } + return this; + } + /** + * repeated .org.hyperledger.chaintool.meta.InterfaceDescriptor descriptors = 1; + */ + public Builder addAllDescriptors( + java.lang.Iterable values) { + if (descriptorsBuilder_ == null) { + ensureDescriptorsIsMutable(); + com.google.protobuf.AbstractMessageLite.Builder.addAll( + values, descriptors_); + onChanged(); + } else { + descriptorsBuilder_.addAllMessages(values); + } + return this; + } + /** + * repeated .org.hyperledger.chaintool.meta.InterfaceDescriptor descriptors = 1; + */ + public Builder clearDescriptors() { + if (descriptorsBuilder_ == null) { + descriptors_ = java.util.Collections.emptyList(); + bitField0_ = (bitField0_ & ~0x00000001); + onChanged(); + } else { + descriptorsBuilder_.clear(); + } + return this; + } + /** + * repeated .org.hyperledger.chaintool.meta.InterfaceDescriptor descriptors = 1; + */ + public Builder removeDescriptors(int index) { + if (descriptorsBuilder_ == null) { + ensureDescriptorsIsMutable(); + descriptors_.remove(index); + onChanged(); + } else { + descriptorsBuilder_.remove(index); + } + return this; + } + /** + * repeated .org.hyperledger.chaintool.meta.InterfaceDescriptor descriptors = 1; + */ + public org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.InterfaceDescriptor.Builder getDescriptorsBuilder( + int index) { + return getDescriptorsFieldBuilder().getBuilder(index); + } + /** + * repeated .org.hyperledger.chaintool.meta.InterfaceDescriptor descriptors = 1; + */ + public org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.InterfaceDescriptorOrBuilder getDescriptorsOrBuilder( + int index) { + if (descriptorsBuilder_ == null) { + return descriptors_.get(index); } else { + return descriptorsBuilder_.getMessageOrBuilder(index); + } + } + /** + * repeated .org.hyperledger.chaintool.meta.InterfaceDescriptor descriptors = 1; + */ + public java.util.List + getDescriptorsOrBuilderList() { + if (descriptorsBuilder_ != null) { + return descriptorsBuilder_.getMessageOrBuilderList(); + } else { + return java.util.Collections.unmodifiableList(descriptors_); + } + } + /** + * repeated .org.hyperledger.chaintool.meta.InterfaceDescriptor descriptors = 1; + */ + public org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.InterfaceDescriptor.Builder addDescriptorsBuilder() { + return getDescriptorsFieldBuilder().addBuilder( + org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.InterfaceDescriptor.getDefaultInstance()); + } + /** + * repeated .org.hyperledger.chaintool.meta.InterfaceDescriptor descriptors = 1; + */ + public org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.InterfaceDescriptor.Builder addDescriptorsBuilder( + int index) { + return getDescriptorsFieldBuilder().addBuilder( + index, org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.InterfaceDescriptor.getDefaultInstance()); + } + /** + * repeated .org.hyperledger.chaintool.meta.InterfaceDescriptor descriptors = 1; + */ + public java.util.List + getDescriptorsBuilderList() { + return getDescriptorsFieldBuilder().getBuilderList(); + } + private com.google.protobuf.RepeatedFieldBuilder< + org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.InterfaceDescriptor, org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.InterfaceDescriptor.Builder, org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.InterfaceDescriptorOrBuilder> + getDescriptorsFieldBuilder() { + if (descriptorsBuilder_ == null) { + descriptorsBuilder_ = new com.google.protobuf.RepeatedFieldBuilder< + org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.InterfaceDescriptor, org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.InterfaceDescriptor.Builder, org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.InterfaceDescriptorOrBuilder>( + descriptors_, + ((bitField0_ & 0x00000001) == 0x00000001), + getParentForChildren(), + isClean()); + descriptors_ = null; + } + return descriptorsBuilder_; + } + public final Builder setUnknownFields( + final com.google.protobuf.UnknownFieldSet unknownFields) { + return this; + } + + public final Builder mergeUnknownFields( + final com.google.protobuf.UnknownFieldSet unknownFields) { + return this; + } + + + // @@protoc_insertion_point(builder_scope:org.hyperledger.chaintool.meta.Interfaces) + } + + // @@protoc_insertion_point(class_scope:org.hyperledger.chaintool.meta.Interfaces) + private static final org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.Interfaces DEFAULT_INSTANCE; + static { + DEFAULT_INSTANCE = new org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.Interfaces(); + } + + public static org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.Interfaces getDefaultInstance() { + return DEFAULT_INSTANCE; + } + + private static final com.google.protobuf.Parser + PARSER = new com.google.protobuf.AbstractParser() { + public Interfaces parsePartialFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + try { + return new Interfaces(input, extensionRegistry); + } catch (RuntimeException e) { + if (e.getCause() instanceof + com.google.protobuf.InvalidProtocolBufferException) { + throw (com.google.protobuf.InvalidProtocolBufferException) + e.getCause(); + } + throw e; + } + } + }; + + public static com.google.protobuf.Parser parser() { + return PARSER; + } + + @java.lang.Override + public com.google.protobuf.Parser getParserForType() { + return PARSER; + } + + public org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.Interfaces getDefaultInstanceForType() { + return DEFAULT_INSTANCE; + } + + } + + public interface GetInterfacesParamsOrBuilder extends + // @@protoc_insertion_point(interface_extends:org.hyperledger.chaintool.meta.GetInterfacesParams) + com.google.protobuf.MessageOrBuilder { + + /** + * optional bool IncludeContent = 1; + */ + boolean getIncludeContent(); + } + /** + * Protobuf type {@code org.hyperledger.chaintool.meta.GetInterfacesParams} + */ + public static final class GetInterfacesParams extends + com.google.protobuf.GeneratedMessage implements + // @@protoc_insertion_point(message_implements:org.hyperledger.chaintool.meta.GetInterfacesParams) + GetInterfacesParamsOrBuilder { + // Use GetInterfacesParams.newBuilder() to construct. + private GetInterfacesParams(com.google.protobuf.GeneratedMessage.Builder builder) { + super(builder); + } + private GetInterfacesParams() { + includeContent_ = false; + } + + @java.lang.Override + public final com.google.protobuf.UnknownFieldSet + getUnknownFields() { + return com.google.protobuf.UnknownFieldSet.getDefaultInstance(); + } + private GetInterfacesParams( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) { + this(); + int mutable_bitField0_ = 0; + try { + boolean done = false; + while (!done) { + int tag = input.readTag(); + switch (tag) { + case 0: + done = true; + break; + default: { + if (!input.skipField(tag)) { + done = true; + } + break; + } + case 8: { + + includeContent_ = input.readBool(); + break; + } + } + } + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw new RuntimeException(e.setUnfinishedMessage(this)); + } catch (java.io.IOException e) { + throw new RuntimeException( + new com.google.protobuf.InvalidProtocolBufferException( + e.getMessage()).setUnfinishedMessage(this)); + } finally { + makeExtensionsImmutable(); + } + } + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.internal_static_org_hyperledger_chaintool_meta_GetInterfacesParams_descriptor; + } + + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.internal_static_org_hyperledger_chaintool_meta_GetInterfacesParams_fieldAccessorTable + .ensureFieldAccessorsInitialized( + org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.GetInterfacesParams.class, org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.GetInterfacesParams.Builder.class); + } + + public static final int INCLUDECONTENT_FIELD_NUMBER = 1; + private boolean includeContent_; + /** + * optional bool IncludeContent = 1; + */ + public boolean getIncludeContent() { + return includeContent_; + } + + private byte memoizedIsInitialized = -1; + public final boolean isInitialized() { + byte isInitialized = memoizedIsInitialized; + if (isInitialized == 1) return true; + if (isInitialized == 0) return false; + + memoizedIsInitialized = 1; + return true; + } + + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + if (includeContent_ != false) { + output.writeBool(1, includeContent_); + } + } + + public int getSerializedSize() { + int size = memoizedSize; + if (size != -1) return size; + + size = 0; + if (includeContent_ != false) { + size += com.google.protobuf.CodedOutputStream + .computeBoolSize(1, includeContent_); + } + memoizedSize = size; + return size; + } + + private static final long serialVersionUID = 0L; + public static org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.GetInterfacesParams parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.GetInterfacesParams parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.GetInterfacesParams parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.GetInterfacesParams parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.GetInterfacesParams parseFrom(java.io.InputStream input) + throws java.io.IOException { + return PARSER.parseFrom(input); + } + public static org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.GetInterfacesParams parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return PARSER.parseFrom(input, extensionRegistry); + } + public static org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.GetInterfacesParams parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + return PARSER.parseDelimitedFrom(input); + } + public static org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.GetInterfacesParams parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return PARSER.parseDelimitedFrom(input, extensionRegistry); + } + public static org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.GetInterfacesParams parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return PARSER.parseFrom(input); + } + public static org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.GetInterfacesParams parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return PARSER.parseFrom(input, extensionRegistry); + } + + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder() { + return DEFAULT_INSTANCE.toBuilder(); + } + public static Builder newBuilder(org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.GetInterfacesParams prototype) { + return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); + } + public Builder toBuilder() { + return this == DEFAULT_INSTANCE + ? new Builder() : new Builder().mergeFrom(this); + } + + @java.lang.Override + protected Builder newBuilderForType( + com.google.protobuf.GeneratedMessage.BuilderParent parent) { + Builder builder = new Builder(parent); + return builder; + } + /** + * Protobuf type {@code org.hyperledger.chaintool.meta.GetInterfacesParams} + */ + public static final class Builder extends + com.google.protobuf.GeneratedMessage.Builder implements + // @@protoc_insertion_point(builder_implements:org.hyperledger.chaintool.meta.GetInterfacesParams) + org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.GetInterfacesParamsOrBuilder { + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.internal_static_org_hyperledger_chaintool_meta_GetInterfacesParams_descriptor; + } + + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.internal_static_org_hyperledger_chaintool_meta_GetInterfacesParams_fieldAccessorTable + .ensureFieldAccessorsInitialized( + org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.GetInterfacesParams.class, org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.GetInterfacesParams.Builder.class); + } + + // Construct using org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.GetInterfacesParams.newBuilder() + private Builder() { + maybeForceBuilderInitialization(); + } + + private Builder( + com.google.protobuf.GeneratedMessage.BuilderParent parent) { + super(parent); + maybeForceBuilderInitialization(); + } + private void maybeForceBuilderInitialization() { + if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) { + } + } + public Builder clear() { + super.clear(); + includeContent_ = false; + + return this; + } + + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.internal_static_org_hyperledger_chaintool_meta_GetInterfacesParams_descriptor; + } + + public org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.GetInterfacesParams getDefaultInstanceForType() { + return org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.GetInterfacesParams.getDefaultInstance(); + } + + public org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.GetInterfacesParams build() { + org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.GetInterfacesParams result = buildPartial(); + if (!result.isInitialized()) { + throw newUninitializedMessageException(result); + } + return result; + } + + public org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.GetInterfacesParams buildPartial() { + org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.GetInterfacesParams result = new org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.GetInterfacesParams(this); + result.includeContent_ = includeContent_; + onBuilt(); + return result; + } + + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.GetInterfacesParams) { + return mergeFrom((org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.GetInterfacesParams)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.GetInterfacesParams other) { + if (other == org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.GetInterfacesParams.getDefaultInstance()) return this; + if (other.getIncludeContent() != false) { + setIncludeContent(other.getIncludeContent()); + } + onChanged(); + return this; + } + + public final boolean isInitialized() { + return true; + } + + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.GetInterfacesParams parsedMessage = null; + try { + parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry); + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + parsedMessage = (org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.GetInterfacesParams) e.getUnfinishedMessage(); + throw e; + } finally { + if (parsedMessage != null) { + mergeFrom(parsedMessage); + } + } + return this; + } + + private boolean includeContent_ ; + /** + * optional bool IncludeContent = 1; + */ + public boolean getIncludeContent() { + return includeContent_; + } + /** + * optional bool IncludeContent = 1; + */ + public Builder setIncludeContent(boolean value) { + + includeContent_ = value; + onChanged(); + return this; + } + /** + * optional bool IncludeContent = 1; + */ + public Builder clearIncludeContent() { + + includeContent_ = false; + onChanged(); + return this; + } + public final Builder setUnknownFields( + final com.google.protobuf.UnknownFieldSet unknownFields) { + return this; + } + + public final Builder mergeUnknownFields( + final com.google.protobuf.UnknownFieldSet unknownFields) { + return this; + } + + + // @@protoc_insertion_point(builder_scope:org.hyperledger.chaintool.meta.GetInterfacesParams) + } + + // @@protoc_insertion_point(class_scope:org.hyperledger.chaintool.meta.GetInterfacesParams) + private static final org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.GetInterfacesParams DEFAULT_INSTANCE; + static { + DEFAULT_INSTANCE = new org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.GetInterfacesParams(); + } + + public static org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.GetInterfacesParams getDefaultInstance() { + return DEFAULT_INSTANCE; + } + + private static final com.google.protobuf.Parser + PARSER = new com.google.protobuf.AbstractParser() { + public GetInterfacesParams parsePartialFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + try { + return new GetInterfacesParams(input, extensionRegistry); + } catch (RuntimeException e) { + if (e.getCause() instanceof + com.google.protobuf.InvalidProtocolBufferException) { + throw (com.google.protobuf.InvalidProtocolBufferException) + e.getCause(); + } + throw e; + } + } + }; + + public static com.google.protobuf.Parser parser() { + return PARSER; + } + + @java.lang.Override + public com.google.protobuf.Parser getParserForType() { + return PARSER; + } + + public org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.GetInterfacesParams getDefaultInstanceForType() { + return DEFAULT_INSTANCE; + } + + } + + public interface GetInterfaceParamsOrBuilder extends + // @@protoc_insertion_point(interface_extends:org.hyperledger.chaintool.meta.GetInterfaceParams) + com.google.protobuf.MessageOrBuilder { + + /** + * optional string name = 1; + */ + java.lang.String getName(); + /** + * optional string name = 1; + */ + com.google.protobuf.ByteString + getNameBytes(); + } + /** + * Protobuf type {@code org.hyperledger.chaintool.meta.GetInterfaceParams} + */ + public static final class GetInterfaceParams extends + com.google.protobuf.GeneratedMessage implements + // @@protoc_insertion_point(message_implements:org.hyperledger.chaintool.meta.GetInterfaceParams) + GetInterfaceParamsOrBuilder { + // Use GetInterfaceParams.newBuilder() to construct. + private GetInterfaceParams(com.google.protobuf.GeneratedMessage.Builder builder) { + super(builder); + } + private GetInterfaceParams() { + name_ = ""; + } + + @java.lang.Override + public final com.google.protobuf.UnknownFieldSet + getUnknownFields() { + return com.google.protobuf.UnknownFieldSet.getDefaultInstance(); + } + private GetInterfaceParams( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) { + this(); + int mutable_bitField0_ = 0; + try { + boolean done = false; + while (!done) { + int tag = input.readTag(); + switch (tag) { + case 0: + done = true; + break; + default: { + if (!input.skipField(tag)) { + done = true; + } + break; + } + case 10: { + java.lang.String s = input.readStringRequireUtf8(); + + name_ = s; + break; + } + } + } + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw new RuntimeException(e.setUnfinishedMessage(this)); + } catch (java.io.IOException e) { + throw new RuntimeException( + new com.google.protobuf.InvalidProtocolBufferException( + e.getMessage()).setUnfinishedMessage(this)); + } finally { + makeExtensionsImmutable(); + } + } + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.internal_static_org_hyperledger_chaintool_meta_GetInterfaceParams_descriptor; + } + + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.internal_static_org_hyperledger_chaintool_meta_GetInterfaceParams_fieldAccessorTable + .ensureFieldAccessorsInitialized( + org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.GetInterfaceParams.class, org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.GetInterfaceParams.Builder.class); + } + + public static final int NAME_FIELD_NUMBER = 1; + private volatile java.lang.Object name_; + /** + * optional string name = 1; + */ + public java.lang.String getName() { + java.lang.Object ref = name_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + name_ = s; + return s; + } + } + /** + * optional string name = 1; + */ + public com.google.protobuf.ByteString + getNameBytes() { + java.lang.Object ref = name_; + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + name_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + private byte memoizedIsInitialized = -1; + public final boolean isInitialized() { + byte isInitialized = memoizedIsInitialized; + if (isInitialized == 1) return true; + if (isInitialized == 0) return false; + + memoizedIsInitialized = 1; + return true; + } + + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + if (!getNameBytes().isEmpty()) { + com.google.protobuf.GeneratedMessage.writeString(output, 1, name_); + } + } + + public int getSerializedSize() { + int size = memoizedSize; + if (size != -1) return size; + + size = 0; + if (!getNameBytes().isEmpty()) { + size += com.google.protobuf.GeneratedMessage.computeStringSize(1, name_); + } + memoizedSize = size; + return size; + } + + private static final long serialVersionUID = 0L; + public static org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.GetInterfaceParams parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.GetInterfaceParams parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.GetInterfaceParams parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.GetInterfaceParams parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.GetInterfaceParams parseFrom(java.io.InputStream input) + throws java.io.IOException { + return PARSER.parseFrom(input); + } + public static org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.GetInterfaceParams parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return PARSER.parseFrom(input, extensionRegistry); + } + public static org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.GetInterfaceParams parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + return PARSER.parseDelimitedFrom(input); + } + public static org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.GetInterfaceParams parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return PARSER.parseDelimitedFrom(input, extensionRegistry); + } + public static org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.GetInterfaceParams parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return PARSER.parseFrom(input); + } + public static org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.GetInterfaceParams parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return PARSER.parseFrom(input, extensionRegistry); + } + + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder() { + return DEFAULT_INSTANCE.toBuilder(); + } + public static Builder newBuilder(org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.GetInterfaceParams prototype) { + return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); + } + public Builder toBuilder() { + return this == DEFAULT_INSTANCE + ? new Builder() : new Builder().mergeFrom(this); + } + + @java.lang.Override + protected Builder newBuilderForType( + com.google.protobuf.GeneratedMessage.BuilderParent parent) { + Builder builder = new Builder(parent); + return builder; + } + /** + * Protobuf type {@code org.hyperledger.chaintool.meta.GetInterfaceParams} + */ + public static final class Builder extends + com.google.protobuf.GeneratedMessage.Builder implements + // @@protoc_insertion_point(builder_implements:org.hyperledger.chaintool.meta.GetInterfaceParams) + org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.GetInterfaceParamsOrBuilder { + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.internal_static_org_hyperledger_chaintool_meta_GetInterfaceParams_descriptor; + } + + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.internal_static_org_hyperledger_chaintool_meta_GetInterfaceParams_fieldAccessorTable + .ensureFieldAccessorsInitialized( + org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.GetInterfaceParams.class, org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.GetInterfaceParams.Builder.class); + } + + // Construct using org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.GetInterfaceParams.newBuilder() + private Builder() { + maybeForceBuilderInitialization(); + } + + private Builder( + com.google.protobuf.GeneratedMessage.BuilderParent parent) { + super(parent); + maybeForceBuilderInitialization(); + } + private void maybeForceBuilderInitialization() { + if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) { + } + } + public Builder clear() { + super.clear(); + name_ = ""; + + return this; + } + + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.internal_static_org_hyperledger_chaintool_meta_GetInterfaceParams_descriptor; + } + + public org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.GetInterfaceParams getDefaultInstanceForType() { + return org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.GetInterfaceParams.getDefaultInstance(); + } + + public org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.GetInterfaceParams build() { + org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.GetInterfaceParams result = buildPartial(); + if (!result.isInitialized()) { + throw newUninitializedMessageException(result); + } + return result; + } + + public org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.GetInterfaceParams buildPartial() { + org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.GetInterfaceParams result = new org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.GetInterfaceParams(this); + result.name_ = name_; + onBuilt(); + return result; + } + + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.GetInterfaceParams) { + return mergeFrom((org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.GetInterfaceParams)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.GetInterfaceParams other) { + if (other == org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.GetInterfaceParams.getDefaultInstance()) return this; + if (!other.getName().isEmpty()) { + name_ = other.name_; + onChanged(); + } + onChanged(); + return this; + } + + public final boolean isInitialized() { + return true; + } + + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.GetInterfaceParams parsedMessage = null; + try { + parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry); + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + parsedMessage = (org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.GetInterfaceParams) e.getUnfinishedMessage(); + throw e; + } finally { + if (parsedMessage != null) { + mergeFrom(parsedMessage); + } + } + return this; + } + + private java.lang.Object name_ = ""; + /** + * optional string name = 1; + */ + public java.lang.String getName() { + java.lang.Object ref = name_; + if (!(ref instanceof java.lang.String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + name_ = s; + return s; + } else { + return (java.lang.String) ref; + } + } + /** + * optional string name = 1; + */ + public com.google.protobuf.ByteString + getNameBytes() { + java.lang.Object ref = name_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + name_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + * optional string name = 1; + */ + public Builder setName( + java.lang.String value) { + if (value == null) { + throw new NullPointerException(); + } + + name_ = value; + onChanged(); + return this; + } + /** + * optional string name = 1; + */ + public Builder clearName() { + + name_ = getDefaultInstance().getName(); + onChanged(); + return this; + } + /** + * optional string name = 1; + */ + public Builder setNameBytes( + com.google.protobuf.ByteString value) { + if (value == null) { + throw new NullPointerException(); + } + checkByteStringIsUtf8(value); + + name_ = value; + onChanged(); + return this; + } + public final Builder setUnknownFields( + final com.google.protobuf.UnknownFieldSet unknownFields) { + return this; + } + + public final Builder mergeUnknownFields( + final com.google.protobuf.UnknownFieldSet unknownFields) { + return this; + } + + + // @@protoc_insertion_point(builder_scope:org.hyperledger.chaintool.meta.GetInterfaceParams) + } + + // @@protoc_insertion_point(class_scope:org.hyperledger.chaintool.meta.GetInterfaceParams) + private static final org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.GetInterfaceParams DEFAULT_INSTANCE; + static { + DEFAULT_INSTANCE = new org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.GetInterfaceParams(); + } + + public static org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.GetInterfaceParams getDefaultInstance() { + return DEFAULT_INSTANCE; + } + + private static final com.google.protobuf.Parser + PARSER = new com.google.protobuf.AbstractParser() { + public GetInterfaceParams parsePartialFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + try { + return new GetInterfaceParams(input, extensionRegistry); + } catch (RuntimeException e) { + if (e.getCause() instanceof + com.google.protobuf.InvalidProtocolBufferException) { + throw (com.google.protobuf.InvalidProtocolBufferException) + e.getCause(); + } + throw e; + } + } + }; + + public static com.google.protobuf.Parser parser() { + return PARSER; + } + + @java.lang.Override + public com.google.protobuf.Parser getParserForType() { + return PARSER; + } + + public org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.GetInterfaceParams getDefaultInstanceForType() { + return DEFAULT_INSTANCE; + } + + } + + public interface GetFactsParamsOrBuilder extends + // @@protoc_insertion_point(interface_extends:org.hyperledger.chaintool.meta.GetFactsParams) + com.google.protobuf.MessageOrBuilder { + } + /** + * Protobuf type {@code org.hyperledger.chaintool.meta.GetFactsParams} + */ + public static final class GetFactsParams extends + com.google.protobuf.GeneratedMessage implements + // @@protoc_insertion_point(message_implements:org.hyperledger.chaintool.meta.GetFactsParams) + GetFactsParamsOrBuilder { + // Use GetFactsParams.newBuilder() to construct. + private GetFactsParams(com.google.protobuf.GeneratedMessage.Builder builder) { + super(builder); + } + private GetFactsParams() { + } + + @java.lang.Override + public final com.google.protobuf.UnknownFieldSet + getUnknownFields() { + return com.google.protobuf.UnknownFieldSet.getDefaultInstance(); + } + private GetFactsParams( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) { + this(); + try { + boolean done = false; + while (!done) { + int tag = input.readTag(); + switch (tag) { + case 0: + done = true; + break; + default: { + if (!input.skipField(tag)) { + done = true; + } + break; + } + } + } + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw new RuntimeException(e.setUnfinishedMessage(this)); + } catch (java.io.IOException e) { + throw new RuntimeException( + new com.google.protobuf.InvalidProtocolBufferException( + e.getMessage()).setUnfinishedMessage(this)); + } finally { + makeExtensionsImmutable(); + } + } + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.internal_static_org_hyperledger_chaintool_meta_GetFactsParams_descriptor; + } + + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.internal_static_org_hyperledger_chaintool_meta_GetFactsParams_fieldAccessorTable + .ensureFieldAccessorsInitialized( + org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.GetFactsParams.class, org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.GetFactsParams.Builder.class); + } + + private byte memoizedIsInitialized = -1; + public final boolean isInitialized() { + byte isInitialized = memoizedIsInitialized; + if (isInitialized == 1) return true; + if (isInitialized == 0) return false; + + memoizedIsInitialized = 1; + return true; + } + + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + } + + public int getSerializedSize() { + int size = memoizedSize; + if (size != -1) return size; + + size = 0; + memoizedSize = size; + return size; + } + + private static final long serialVersionUID = 0L; + public static org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.GetFactsParams parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.GetFactsParams parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.GetFactsParams parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.GetFactsParams parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.GetFactsParams parseFrom(java.io.InputStream input) + throws java.io.IOException { + return PARSER.parseFrom(input); + } + public static org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.GetFactsParams parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return PARSER.parseFrom(input, extensionRegistry); + } + public static org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.GetFactsParams parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + return PARSER.parseDelimitedFrom(input); + } + public static org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.GetFactsParams parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return PARSER.parseDelimitedFrom(input, extensionRegistry); + } + public static org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.GetFactsParams parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return PARSER.parseFrom(input); + } + public static org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.GetFactsParams parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return PARSER.parseFrom(input, extensionRegistry); + } + + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder() { + return DEFAULT_INSTANCE.toBuilder(); + } + public static Builder newBuilder(org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.GetFactsParams prototype) { + return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); + } + public Builder toBuilder() { + return this == DEFAULT_INSTANCE + ? new Builder() : new Builder().mergeFrom(this); + } + + @java.lang.Override + protected Builder newBuilderForType( + com.google.protobuf.GeneratedMessage.BuilderParent parent) { + Builder builder = new Builder(parent); + return builder; + } + /** + * Protobuf type {@code org.hyperledger.chaintool.meta.GetFactsParams} + */ + public static final class Builder extends + com.google.protobuf.GeneratedMessage.Builder implements + // @@protoc_insertion_point(builder_implements:org.hyperledger.chaintool.meta.GetFactsParams) + org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.GetFactsParamsOrBuilder { + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.internal_static_org_hyperledger_chaintool_meta_GetFactsParams_descriptor; + } + + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.internal_static_org_hyperledger_chaintool_meta_GetFactsParams_fieldAccessorTable + .ensureFieldAccessorsInitialized( + org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.GetFactsParams.class, org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.GetFactsParams.Builder.class); + } + + // Construct using org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.GetFactsParams.newBuilder() + private Builder() { + maybeForceBuilderInitialization(); + } + + private Builder( + com.google.protobuf.GeneratedMessage.BuilderParent parent) { + super(parent); + maybeForceBuilderInitialization(); + } + private void maybeForceBuilderInitialization() { + if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) { + } + } + public Builder clear() { + super.clear(); + return this; + } + + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.internal_static_org_hyperledger_chaintool_meta_GetFactsParams_descriptor; + } + + public org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.GetFactsParams getDefaultInstanceForType() { + return org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.GetFactsParams.getDefaultInstance(); + } + + public org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.GetFactsParams build() { + org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.GetFactsParams result = buildPartial(); + if (!result.isInitialized()) { + throw newUninitializedMessageException(result); + } + return result; + } + + public org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.GetFactsParams buildPartial() { + org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.GetFactsParams result = new org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.GetFactsParams(this); + onBuilt(); + return result; + } + + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.GetFactsParams) { + return mergeFrom((org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.GetFactsParams)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.GetFactsParams other) { + if (other == org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.GetFactsParams.getDefaultInstance()) return this; + onChanged(); + return this; + } + + public final boolean isInitialized() { + return true; + } + + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.GetFactsParams parsedMessage = null; + try { + parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry); + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + parsedMessage = (org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.GetFactsParams) e.getUnfinishedMessage(); + throw e; + } finally { + if (parsedMessage != null) { + mergeFrom(parsedMessage); + } + } + return this; + } + public final Builder setUnknownFields( + final com.google.protobuf.UnknownFieldSet unknownFields) { + return this; + } + + public final Builder mergeUnknownFields( + final com.google.protobuf.UnknownFieldSet unknownFields) { + return this; + } + + + // @@protoc_insertion_point(builder_scope:org.hyperledger.chaintool.meta.GetFactsParams) + } + + // @@protoc_insertion_point(class_scope:org.hyperledger.chaintool.meta.GetFactsParams) + private static final org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.GetFactsParams DEFAULT_INSTANCE; + static { + DEFAULT_INSTANCE = new org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.GetFactsParams(); + } + + public static org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.GetFactsParams getDefaultInstance() { + return DEFAULT_INSTANCE; + } + + private static final com.google.protobuf.Parser + PARSER = new com.google.protobuf.AbstractParser() { + public GetFactsParams parsePartialFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + try { + return new GetFactsParams(input, extensionRegistry); + } catch (RuntimeException e) { + if (e.getCause() instanceof + com.google.protobuf.InvalidProtocolBufferException) { + throw (com.google.protobuf.InvalidProtocolBufferException) + e.getCause(); + } + throw e; + } + } + }; + + public static com.google.protobuf.Parser parser() { + return PARSER; + } + + @java.lang.Override + public com.google.protobuf.Parser getParserForType() { + return PARSER; + } + + public org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.GetFactsParams getDefaultInstanceForType() { + return DEFAULT_INSTANCE; + } + + } + + public interface FactsOrBuilder extends + // @@protoc_insertion_point(interface_extends:org.hyperledger.chaintool.meta.Facts) + com.google.protobuf.MessageOrBuilder { + + /** + * repeated .org.hyperledger.chaintool.meta.Facts.Fact facts = 1; + */ + java.util.List + getFactsList(); + /** + * repeated .org.hyperledger.chaintool.meta.Facts.Fact facts = 1; + */ + org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.Facts.Fact getFacts(int index); + /** + * repeated .org.hyperledger.chaintool.meta.Facts.Fact facts = 1; + */ + int getFactsCount(); + /** + * repeated .org.hyperledger.chaintool.meta.Facts.Fact facts = 1; + */ + java.util.List + getFactsOrBuilderList(); + /** + * repeated .org.hyperledger.chaintool.meta.Facts.Fact facts = 1; + */ + org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.Facts.FactOrBuilder getFactsOrBuilder( + int index); + } + /** + * Protobuf type {@code org.hyperledger.chaintool.meta.Facts} + */ + public static final class Facts extends + com.google.protobuf.GeneratedMessage implements + // @@protoc_insertion_point(message_implements:org.hyperledger.chaintool.meta.Facts) + FactsOrBuilder { + // Use Facts.newBuilder() to construct. + private Facts(com.google.protobuf.GeneratedMessage.Builder builder) { + super(builder); + } + private Facts() { + facts_ = java.util.Collections.emptyList(); + } + + @java.lang.Override + public final com.google.protobuf.UnknownFieldSet + getUnknownFields() { + return com.google.protobuf.UnknownFieldSet.getDefaultInstance(); + } + private Facts( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) { + this(); + int mutable_bitField0_ = 0; + try { + boolean done = false; + while (!done) { + int tag = input.readTag(); + switch (tag) { + case 0: + done = true; + break; + default: { + if (!input.skipField(tag)) { + done = true; + } + break; + } + case 10: { + if (!((mutable_bitField0_ & 0x00000001) == 0x00000001)) { + facts_ = new java.util.ArrayList(); + mutable_bitField0_ |= 0x00000001; + } + facts_.add(input.readMessage(org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.Facts.Fact.parser(), extensionRegistry)); + break; + } + } + } + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw new RuntimeException(e.setUnfinishedMessage(this)); + } catch (java.io.IOException e) { + throw new RuntimeException( + new com.google.protobuf.InvalidProtocolBufferException( + e.getMessage()).setUnfinishedMessage(this)); + } finally { + if (((mutable_bitField0_ & 0x00000001) == 0x00000001)) { + facts_ = java.util.Collections.unmodifiableList(facts_); + } + makeExtensionsImmutable(); + } + } + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.internal_static_org_hyperledger_chaintool_meta_Facts_descriptor; + } + + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.internal_static_org_hyperledger_chaintool_meta_Facts_fieldAccessorTable + .ensureFieldAccessorsInitialized( + org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.Facts.class, org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.Facts.Builder.class); + } + + public interface FactOrBuilder extends + // @@protoc_insertion_point(interface_extends:org.hyperledger.chaintool.meta.Facts.Fact) + com.google.protobuf.MessageOrBuilder { + + /** + * optional string name = 1; + */ + java.lang.String getName(); + /** + * optional string name = 1; + */ + com.google.protobuf.ByteString + getNameBytes(); + + /** + * optional string value = 2; + */ + java.lang.String getValue(); + /** + * optional string value = 2; + */ + com.google.protobuf.ByteString + getValueBytes(); + } + /** + * Protobuf type {@code org.hyperledger.chaintool.meta.Facts.Fact} + */ + public static final class Fact extends + com.google.protobuf.GeneratedMessage implements + // @@protoc_insertion_point(message_implements:org.hyperledger.chaintool.meta.Facts.Fact) + FactOrBuilder { + // Use Fact.newBuilder() to construct. + private Fact(com.google.protobuf.GeneratedMessage.Builder builder) { + super(builder); + } + private Fact() { + name_ = ""; + value_ = ""; + } + + @java.lang.Override + public final com.google.protobuf.UnknownFieldSet + getUnknownFields() { + return com.google.protobuf.UnknownFieldSet.getDefaultInstance(); + } + private Fact( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) { + this(); + int mutable_bitField0_ = 0; + try { + boolean done = false; + while (!done) { + int tag = input.readTag(); + switch (tag) { + case 0: + done = true; + break; + default: { + if (!input.skipField(tag)) { + done = true; + } + break; + } + case 10: { + java.lang.String s = input.readStringRequireUtf8(); + + name_ = s; + break; + } + case 18: { + java.lang.String s = input.readStringRequireUtf8(); + + value_ = s; + break; + } + } + } + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw new RuntimeException(e.setUnfinishedMessage(this)); + } catch (java.io.IOException e) { + throw new RuntimeException( + new com.google.protobuf.InvalidProtocolBufferException( + e.getMessage()).setUnfinishedMessage(this)); + } finally { + makeExtensionsImmutable(); + } + } + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.internal_static_org_hyperledger_chaintool_meta_Facts_Fact_descriptor; + } + + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.internal_static_org_hyperledger_chaintool_meta_Facts_Fact_fieldAccessorTable + .ensureFieldAccessorsInitialized( + org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.Facts.Fact.class, org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.Facts.Fact.Builder.class); + } + + public static final int NAME_FIELD_NUMBER = 1; + private volatile java.lang.Object name_; + /** + * optional string name = 1; + */ + public java.lang.String getName() { + java.lang.Object ref = name_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + name_ = s; + return s; + } + } + /** + * optional string name = 1; + */ + public com.google.protobuf.ByteString + getNameBytes() { + java.lang.Object ref = name_; + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + name_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + public static final int VALUE_FIELD_NUMBER = 2; + private volatile java.lang.Object value_; + /** + * optional string value = 2; + */ + public java.lang.String getValue() { + java.lang.Object ref = value_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + value_ = s; + return s; + } + } + /** + * optional string value = 2; + */ + public com.google.protobuf.ByteString + getValueBytes() { + java.lang.Object ref = value_; + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + value_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + private byte memoizedIsInitialized = -1; + public final boolean isInitialized() { + byte isInitialized = memoizedIsInitialized; + if (isInitialized == 1) return true; + if (isInitialized == 0) return false; + + memoizedIsInitialized = 1; + return true; + } + + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + if (!getNameBytes().isEmpty()) { + com.google.protobuf.GeneratedMessage.writeString(output, 1, name_); + } + if (!getValueBytes().isEmpty()) { + com.google.protobuf.GeneratedMessage.writeString(output, 2, value_); + } + } + + public int getSerializedSize() { + int size = memoizedSize; + if (size != -1) return size; + + size = 0; + if (!getNameBytes().isEmpty()) { + size += com.google.protobuf.GeneratedMessage.computeStringSize(1, name_); + } + if (!getValueBytes().isEmpty()) { + size += com.google.protobuf.GeneratedMessage.computeStringSize(2, value_); + } + memoizedSize = size; + return size; + } + + private static final long serialVersionUID = 0L; + public static org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.Facts.Fact parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.Facts.Fact parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.Facts.Fact parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.Facts.Fact parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.Facts.Fact parseFrom(java.io.InputStream input) + throws java.io.IOException { + return PARSER.parseFrom(input); + } + public static org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.Facts.Fact parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return PARSER.parseFrom(input, extensionRegistry); + } + public static org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.Facts.Fact parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + return PARSER.parseDelimitedFrom(input); + } + public static org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.Facts.Fact parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return PARSER.parseDelimitedFrom(input, extensionRegistry); + } + public static org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.Facts.Fact parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return PARSER.parseFrom(input); + } + public static org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.Facts.Fact parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return PARSER.parseFrom(input, extensionRegistry); + } + + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder() { + return DEFAULT_INSTANCE.toBuilder(); + } + public static Builder newBuilder(org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.Facts.Fact prototype) { + return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); + } + public Builder toBuilder() { + return this == DEFAULT_INSTANCE + ? new Builder() : new Builder().mergeFrom(this); + } + + @java.lang.Override + protected Builder newBuilderForType( + com.google.protobuf.GeneratedMessage.BuilderParent parent) { + Builder builder = new Builder(parent); + return builder; + } + /** + * Protobuf type {@code org.hyperledger.chaintool.meta.Facts.Fact} + */ + public static final class Builder extends + com.google.protobuf.GeneratedMessage.Builder implements + // @@protoc_insertion_point(builder_implements:org.hyperledger.chaintool.meta.Facts.Fact) + org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.Facts.FactOrBuilder { + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.internal_static_org_hyperledger_chaintool_meta_Facts_Fact_descriptor; + } + + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.internal_static_org_hyperledger_chaintool_meta_Facts_Fact_fieldAccessorTable + .ensureFieldAccessorsInitialized( + org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.Facts.Fact.class, org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.Facts.Fact.Builder.class); + } + + // Construct using org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.Facts.Fact.newBuilder() + private Builder() { + maybeForceBuilderInitialization(); + } + + private Builder( + com.google.protobuf.GeneratedMessage.BuilderParent parent) { + super(parent); + maybeForceBuilderInitialization(); + } + private void maybeForceBuilderInitialization() { + if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) { + } + } + public Builder clear() { + super.clear(); + name_ = ""; + + value_ = ""; + + return this; + } + + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.internal_static_org_hyperledger_chaintool_meta_Facts_Fact_descriptor; + } + + public org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.Facts.Fact getDefaultInstanceForType() { + return org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.Facts.Fact.getDefaultInstance(); + } + + public org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.Facts.Fact build() { + org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.Facts.Fact result = buildPartial(); + if (!result.isInitialized()) { + throw newUninitializedMessageException(result); + } + return result; + } + + public org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.Facts.Fact buildPartial() { + org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.Facts.Fact result = new org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.Facts.Fact(this); + result.name_ = name_; + result.value_ = value_; + onBuilt(); + return result; + } + + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.Facts.Fact) { + return mergeFrom((org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.Facts.Fact)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.Facts.Fact other) { + if (other == org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.Facts.Fact.getDefaultInstance()) return this; + if (!other.getName().isEmpty()) { + name_ = other.name_; + onChanged(); + } + if (!other.getValue().isEmpty()) { + value_ = other.value_; + onChanged(); + } + onChanged(); + return this; + } + + public final boolean isInitialized() { + return true; + } + + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.Facts.Fact parsedMessage = null; + try { + parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry); + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + parsedMessage = (org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.Facts.Fact) e.getUnfinishedMessage(); + throw e; + } finally { + if (parsedMessage != null) { + mergeFrom(parsedMessage); + } + } + return this; + } + + private java.lang.Object name_ = ""; + /** + * optional string name = 1; + */ + public java.lang.String getName() { + java.lang.Object ref = name_; + if (!(ref instanceof java.lang.String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + name_ = s; + return s; + } else { + return (java.lang.String) ref; + } + } + /** + * optional string name = 1; + */ + public com.google.protobuf.ByteString + getNameBytes() { + java.lang.Object ref = name_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + name_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + * optional string name = 1; + */ + public Builder setName( + java.lang.String value) { + if (value == null) { + throw new NullPointerException(); + } + + name_ = value; + onChanged(); + return this; + } + /** + * optional string name = 1; + */ + public Builder clearName() { + + name_ = getDefaultInstance().getName(); + onChanged(); + return this; + } + /** + * optional string name = 1; + */ + public Builder setNameBytes( + com.google.protobuf.ByteString value) { + if (value == null) { + throw new NullPointerException(); + } + checkByteStringIsUtf8(value); + + name_ = value; + onChanged(); + return this; + } + + private java.lang.Object value_ = ""; + /** + * optional string value = 2; + */ + public java.lang.String getValue() { + java.lang.Object ref = value_; + if (!(ref instanceof java.lang.String)) { + com.google.protobuf.ByteString bs = + (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + value_ = s; + return s; + } else { + return (java.lang.String) ref; + } + } + /** + * optional string value = 2; + */ + public com.google.protobuf.ByteString + getValueBytes() { + java.lang.Object ref = value_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + value_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + /** + * optional string value = 2; + */ + public Builder setValue( + java.lang.String value) { + if (value == null) { + throw new NullPointerException(); + } + + value_ = value; + onChanged(); + return this; + } + /** + * optional string value = 2; + */ + public Builder clearValue() { + + value_ = getDefaultInstance().getValue(); + onChanged(); + return this; + } + /** + * optional string value = 2; + */ + public Builder setValueBytes( + com.google.protobuf.ByteString value) { + if (value == null) { + throw new NullPointerException(); + } + checkByteStringIsUtf8(value); + + value_ = value; + onChanged(); + return this; + } + public final Builder setUnknownFields( + final com.google.protobuf.UnknownFieldSet unknownFields) { + return this; + } + + public final Builder mergeUnknownFields( + final com.google.protobuf.UnknownFieldSet unknownFields) { + return this; + } + + + // @@protoc_insertion_point(builder_scope:org.hyperledger.chaintool.meta.Facts.Fact) + } + + // @@protoc_insertion_point(class_scope:org.hyperledger.chaintool.meta.Facts.Fact) + private static final org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.Facts.Fact DEFAULT_INSTANCE; + static { + DEFAULT_INSTANCE = new org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.Facts.Fact(); + } + + public static org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.Facts.Fact getDefaultInstance() { + return DEFAULT_INSTANCE; + } + + private static final com.google.protobuf.Parser + PARSER = new com.google.protobuf.AbstractParser() { + public Fact parsePartialFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + try { + return new Fact(input, extensionRegistry); + } catch (RuntimeException e) { + if (e.getCause() instanceof + com.google.protobuf.InvalidProtocolBufferException) { + throw (com.google.protobuf.InvalidProtocolBufferException) + e.getCause(); + } + throw e; + } + } + }; + + public static com.google.protobuf.Parser parser() { + return PARSER; + } + + @java.lang.Override + public com.google.protobuf.Parser getParserForType() { + return PARSER; + } + + public org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.Facts.Fact getDefaultInstanceForType() { + return DEFAULT_INSTANCE; + } + + } + + public static final int FACTS_FIELD_NUMBER = 1; + private java.util.List facts_; + /** + * repeated .org.hyperledger.chaintool.meta.Facts.Fact facts = 1; + */ + public java.util.List getFactsList() { + return facts_; + } + /** + * repeated .org.hyperledger.chaintool.meta.Facts.Fact facts = 1; + */ + public java.util.List + getFactsOrBuilderList() { + return facts_; + } + /** + * repeated .org.hyperledger.chaintool.meta.Facts.Fact facts = 1; + */ + public int getFactsCount() { + return facts_.size(); + } + /** + * repeated .org.hyperledger.chaintool.meta.Facts.Fact facts = 1; + */ + public org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.Facts.Fact getFacts(int index) { + return facts_.get(index); + } + /** + * repeated .org.hyperledger.chaintool.meta.Facts.Fact facts = 1; + */ + public org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.Facts.FactOrBuilder getFactsOrBuilder( + int index) { + return facts_.get(index); + } + + private byte memoizedIsInitialized = -1; + public final boolean isInitialized() { + byte isInitialized = memoizedIsInitialized; + if (isInitialized == 1) return true; + if (isInitialized == 0) return false; + + memoizedIsInitialized = 1; + return true; + } + + public void writeTo(com.google.protobuf.CodedOutputStream output) + throws java.io.IOException { + for (int i = 0; i < facts_.size(); i++) { + output.writeMessage(1, facts_.get(i)); + } + } + + public int getSerializedSize() { + int size = memoizedSize; + if (size != -1) return size; + + size = 0; + for (int i = 0; i < facts_.size(); i++) { + size += com.google.protobuf.CodedOutputStream + .computeMessageSize(1, facts_.get(i)); + } + memoizedSize = size; + return size; + } + + private static final long serialVersionUID = 0L; + public static org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.Facts parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.Facts parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.Facts parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.Facts parseFrom( + byte[] data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.Facts parseFrom(java.io.InputStream input) + throws java.io.IOException { + return PARSER.parseFrom(input); + } + public static org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.Facts parseFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return PARSER.parseFrom(input, extensionRegistry); + } + public static org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.Facts parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + return PARSER.parseDelimitedFrom(input); + } + public static org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.Facts parseDelimitedFrom( + java.io.InputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return PARSER.parseDelimitedFrom(input, extensionRegistry); + } + public static org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.Facts parseFrom( + com.google.protobuf.CodedInputStream input) + throws java.io.IOException { + return PARSER.parseFrom(input); + } + public static org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.Facts parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return PARSER.parseFrom(input, extensionRegistry); + } + + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder() { + return DEFAULT_INSTANCE.toBuilder(); + } + public static Builder newBuilder(org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.Facts prototype) { + return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); + } + public Builder toBuilder() { + return this == DEFAULT_INSTANCE + ? new Builder() : new Builder().mergeFrom(this); + } + + @java.lang.Override + protected Builder newBuilderForType( + com.google.protobuf.GeneratedMessage.BuilderParent parent) { + Builder builder = new Builder(parent); + return builder; + } + /** + * Protobuf type {@code org.hyperledger.chaintool.meta.Facts} + */ + public static final class Builder extends + com.google.protobuf.GeneratedMessage.Builder implements + // @@protoc_insertion_point(builder_implements:org.hyperledger.chaintool.meta.Facts) + org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.FactsOrBuilder { + public static final com.google.protobuf.Descriptors.Descriptor + getDescriptor() { + return org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.internal_static_org_hyperledger_chaintool_meta_Facts_descriptor; + } + + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.internal_static_org_hyperledger_chaintool_meta_Facts_fieldAccessorTable + .ensureFieldAccessorsInitialized( + org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.Facts.class, org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.Facts.Builder.class); + } + + // Construct using org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.Facts.newBuilder() + private Builder() { + maybeForceBuilderInitialization(); + } + + private Builder( + com.google.protobuf.GeneratedMessage.BuilderParent parent) { + super(parent); + maybeForceBuilderInitialization(); + } + private void maybeForceBuilderInitialization() { + if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) { + getFactsFieldBuilder(); + } + } + public Builder clear() { + super.clear(); + if (factsBuilder_ == null) { + facts_ = java.util.Collections.emptyList(); + bitField0_ = (bitField0_ & ~0x00000001); + } else { + factsBuilder_.clear(); + } + return this; + } + + public com.google.protobuf.Descriptors.Descriptor + getDescriptorForType() { + return org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.internal_static_org_hyperledger_chaintool_meta_Facts_descriptor; + } + + public org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.Facts getDefaultInstanceForType() { + return org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.Facts.getDefaultInstance(); + } + + public org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.Facts build() { + org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.Facts result = buildPartial(); + if (!result.isInitialized()) { + throw newUninitializedMessageException(result); + } + return result; + } + + public org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.Facts buildPartial() { + org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.Facts result = new org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.Facts(this); + int from_bitField0_ = bitField0_; + if (factsBuilder_ == null) { + if (((bitField0_ & 0x00000001) == 0x00000001)) { + facts_ = java.util.Collections.unmodifiableList(facts_); + bitField0_ = (bitField0_ & ~0x00000001); + } + result.facts_ = facts_; + } else { + result.facts_ = factsBuilder_.build(); + } + onBuilt(); + return result; + } + + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.Facts) { + return mergeFrom((org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.Facts)other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.Facts other) { + if (other == org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.Facts.getDefaultInstance()) return this; + if (factsBuilder_ == null) { + if (!other.facts_.isEmpty()) { + if (facts_.isEmpty()) { + facts_ = other.facts_; + bitField0_ = (bitField0_ & ~0x00000001); + } else { + ensureFactsIsMutable(); + facts_.addAll(other.facts_); + } + onChanged(); + } + } else { + if (!other.facts_.isEmpty()) { + if (factsBuilder_.isEmpty()) { + factsBuilder_.dispose(); + factsBuilder_ = null; + facts_ = other.facts_; + bitField0_ = (bitField0_ & ~0x00000001); + factsBuilder_ = + com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders ? + getFactsFieldBuilder() : null; + } else { + factsBuilder_.addAllMessages(other.facts_); + } + } + } + onChanged(); + return this; + } + + public final boolean isInitialized() { + return true; + } + + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.Facts parsedMessage = null; + try { + parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry); + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + parsedMessage = (org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.Facts) e.getUnfinishedMessage(); + throw e; + } finally { + if (parsedMessage != null) { + mergeFrom(parsedMessage); + } + } + return this; + } + private int bitField0_; + + private java.util.List facts_ = + java.util.Collections.emptyList(); + private void ensureFactsIsMutable() { + if (!((bitField0_ & 0x00000001) == 0x00000001)) { + facts_ = new java.util.ArrayList(facts_); + bitField0_ |= 0x00000001; + } + } + + private com.google.protobuf.RepeatedFieldBuilder< + org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.Facts.Fact, org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.Facts.Fact.Builder, org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.Facts.FactOrBuilder> factsBuilder_; + + /** + * repeated .org.hyperledger.chaintool.meta.Facts.Fact facts = 1; + */ + public java.util.List getFactsList() { + if (factsBuilder_ == null) { + return java.util.Collections.unmodifiableList(facts_); + } else { + return factsBuilder_.getMessageList(); + } + } + /** + * repeated .org.hyperledger.chaintool.meta.Facts.Fact facts = 1; + */ + public int getFactsCount() { + if (factsBuilder_ == null) { + return facts_.size(); + } else { + return factsBuilder_.getCount(); + } + } + /** + * repeated .org.hyperledger.chaintool.meta.Facts.Fact facts = 1; + */ + public org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.Facts.Fact getFacts(int index) { + if (factsBuilder_ == null) { + return facts_.get(index); + } else { + return factsBuilder_.getMessage(index); + } + } + /** + * repeated .org.hyperledger.chaintool.meta.Facts.Fact facts = 1; + */ + public Builder setFacts( + int index, org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.Facts.Fact value) { + if (factsBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + ensureFactsIsMutable(); + facts_.set(index, value); + onChanged(); + } else { + factsBuilder_.setMessage(index, value); + } + return this; + } + /** + * repeated .org.hyperledger.chaintool.meta.Facts.Fact facts = 1; + */ + public Builder setFacts( + int index, org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.Facts.Fact.Builder builderForValue) { + if (factsBuilder_ == null) { + ensureFactsIsMutable(); + facts_.set(index, builderForValue.build()); + onChanged(); + } else { + factsBuilder_.setMessage(index, builderForValue.build()); + } + return this; + } + /** + * repeated .org.hyperledger.chaintool.meta.Facts.Fact facts = 1; + */ + public Builder addFacts(org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.Facts.Fact value) { + if (factsBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + ensureFactsIsMutable(); + facts_.add(value); + onChanged(); + } else { + factsBuilder_.addMessage(value); + } + return this; + } + /** + * repeated .org.hyperledger.chaintool.meta.Facts.Fact facts = 1; + */ + public Builder addFacts( + int index, org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.Facts.Fact value) { + if (factsBuilder_ == null) { + if (value == null) { + throw new NullPointerException(); + } + ensureFactsIsMutable(); + facts_.add(index, value); + onChanged(); + } else { + factsBuilder_.addMessage(index, value); + } + return this; + } + /** + * repeated .org.hyperledger.chaintool.meta.Facts.Fact facts = 1; + */ + public Builder addFacts( + org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.Facts.Fact.Builder builderForValue) { + if (factsBuilder_ == null) { + ensureFactsIsMutable(); + facts_.add(builderForValue.build()); + onChanged(); + } else { + factsBuilder_.addMessage(builderForValue.build()); + } + return this; + } + /** + * repeated .org.hyperledger.chaintool.meta.Facts.Fact facts = 1; + */ + public Builder addFacts( + int index, org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.Facts.Fact.Builder builderForValue) { + if (factsBuilder_ == null) { + ensureFactsIsMutable(); + facts_.add(index, builderForValue.build()); + onChanged(); + } else { + factsBuilder_.addMessage(index, builderForValue.build()); + } + return this; + } + /** + * repeated .org.hyperledger.chaintool.meta.Facts.Fact facts = 1; + */ + public Builder addAllFacts( + java.lang.Iterable values) { + if (factsBuilder_ == null) { + ensureFactsIsMutable(); + com.google.protobuf.AbstractMessageLite.Builder.addAll( + values, facts_); + onChanged(); + } else { + factsBuilder_.addAllMessages(values); + } + return this; + } + /** + * repeated .org.hyperledger.chaintool.meta.Facts.Fact facts = 1; + */ + public Builder clearFacts() { + if (factsBuilder_ == null) { + facts_ = java.util.Collections.emptyList(); + bitField0_ = (bitField0_ & ~0x00000001); + onChanged(); + } else { + factsBuilder_.clear(); + } + return this; + } + /** + * repeated .org.hyperledger.chaintool.meta.Facts.Fact facts = 1; + */ + public Builder removeFacts(int index) { + if (factsBuilder_ == null) { + ensureFactsIsMutable(); + facts_.remove(index); + onChanged(); + } else { + factsBuilder_.remove(index); + } + return this; + } + /** + * repeated .org.hyperledger.chaintool.meta.Facts.Fact facts = 1; + */ + public org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.Facts.Fact.Builder getFactsBuilder( + int index) { + return getFactsFieldBuilder().getBuilder(index); + } + /** + * repeated .org.hyperledger.chaintool.meta.Facts.Fact facts = 1; + */ + public org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.Facts.FactOrBuilder getFactsOrBuilder( + int index) { + if (factsBuilder_ == null) { + return facts_.get(index); } else { + return factsBuilder_.getMessageOrBuilder(index); + } + } + /** + * repeated .org.hyperledger.chaintool.meta.Facts.Fact facts = 1; + */ + public java.util.List + getFactsOrBuilderList() { + if (factsBuilder_ != null) { + return factsBuilder_.getMessageOrBuilderList(); + } else { + return java.util.Collections.unmodifiableList(facts_); + } + } + /** + * repeated .org.hyperledger.chaintool.meta.Facts.Fact facts = 1; + */ + public org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.Facts.Fact.Builder addFactsBuilder() { + return getFactsFieldBuilder().addBuilder( + org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.Facts.Fact.getDefaultInstance()); + } + /** + * repeated .org.hyperledger.chaintool.meta.Facts.Fact facts = 1; + */ + public org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.Facts.Fact.Builder addFactsBuilder( + int index) { + return getFactsFieldBuilder().addBuilder( + index, org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.Facts.Fact.getDefaultInstance()); + } + /** + * repeated .org.hyperledger.chaintool.meta.Facts.Fact facts = 1; + */ + public java.util.List + getFactsBuilderList() { + return getFactsFieldBuilder().getBuilderList(); + } + private com.google.protobuf.RepeatedFieldBuilder< + org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.Facts.Fact, org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.Facts.Fact.Builder, org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.Facts.FactOrBuilder> + getFactsFieldBuilder() { + if (factsBuilder_ == null) { + factsBuilder_ = new com.google.protobuf.RepeatedFieldBuilder< + org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.Facts.Fact, org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.Facts.Fact.Builder, org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.Facts.FactOrBuilder>( + facts_, + ((bitField0_ & 0x00000001) == 0x00000001), + getParentForChildren(), + isClean()); + facts_ = null; + } + return factsBuilder_; + } + public final Builder setUnknownFields( + final com.google.protobuf.UnknownFieldSet unknownFields) { + return this; + } + + public final Builder mergeUnknownFields( + final com.google.protobuf.UnknownFieldSet unknownFields) { + return this; + } + + + // @@protoc_insertion_point(builder_scope:org.hyperledger.chaintool.meta.Facts) + } + + // @@protoc_insertion_point(class_scope:org.hyperledger.chaintool.meta.Facts) + private static final org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.Facts DEFAULT_INSTANCE; + static { + DEFAULT_INSTANCE = new org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.Facts(); + } + + public static org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.Facts getDefaultInstance() { + return DEFAULT_INSTANCE; + } + + private static final com.google.protobuf.Parser + PARSER = new com.google.protobuf.AbstractParser() { + public Facts parsePartialFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + try { + return new Facts(input, extensionRegistry); + } catch (RuntimeException e) { + if (e.getCause() instanceof + com.google.protobuf.InvalidProtocolBufferException) { + throw (com.google.protobuf.InvalidProtocolBufferException) + e.getCause(); + } + throw e; + } + } + }; + + public static com.google.protobuf.Parser parser() { + return PARSER; + } + + @java.lang.Override + public com.google.protobuf.Parser getParserForType() { + return PARSER; + } + + public org.hyperledger.chaintool.meta.OrgHyperledgerChaintoolMeta.Facts getDefaultInstanceForType() { + return DEFAULT_INSTANCE; + } + + } + + private static com.google.protobuf.Descriptors.Descriptor + internal_static_org_hyperledger_chaintool_meta_InterfaceDescriptor_descriptor; + private static + com.google.protobuf.GeneratedMessage.FieldAccessorTable + internal_static_org_hyperledger_chaintool_meta_InterfaceDescriptor_fieldAccessorTable; + private static com.google.protobuf.Descriptors.Descriptor + internal_static_org_hyperledger_chaintool_meta_Interfaces_descriptor; + private static + com.google.protobuf.GeneratedMessage.FieldAccessorTable + internal_static_org_hyperledger_chaintool_meta_Interfaces_fieldAccessorTable; + private static com.google.protobuf.Descriptors.Descriptor + internal_static_org_hyperledger_chaintool_meta_GetInterfacesParams_descriptor; + private static + com.google.protobuf.GeneratedMessage.FieldAccessorTable + internal_static_org_hyperledger_chaintool_meta_GetInterfacesParams_fieldAccessorTable; + private static com.google.protobuf.Descriptors.Descriptor + internal_static_org_hyperledger_chaintool_meta_GetInterfaceParams_descriptor; + private static + com.google.protobuf.GeneratedMessage.FieldAccessorTable + internal_static_org_hyperledger_chaintool_meta_GetInterfaceParams_fieldAccessorTable; + private static com.google.protobuf.Descriptors.Descriptor + internal_static_org_hyperledger_chaintool_meta_GetFactsParams_descriptor; + private static + com.google.protobuf.GeneratedMessage.FieldAccessorTable + internal_static_org_hyperledger_chaintool_meta_GetFactsParams_fieldAccessorTable; + private static com.google.protobuf.Descriptors.Descriptor + internal_static_org_hyperledger_chaintool_meta_Facts_descriptor; + private static + com.google.protobuf.GeneratedMessage.FieldAccessorTable + internal_static_org_hyperledger_chaintool_meta_Facts_fieldAccessorTable; + private static com.google.protobuf.Descriptors.Descriptor + internal_static_org_hyperledger_chaintool_meta_Facts_Fact_descriptor; + private static + com.google.protobuf.GeneratedMessage.FieldAccessorTable + internal_static_org_hyperledger_chaintool_meta_Facts_Fact_fieldAccessorTable; + + public static com.google.protobuf.Descriptors.FileDescriptor + getDescriptor() { + return descriptor; + } + private static com.google.protobuf.Descriptors.FileDescriptor + descriptor; + static { + java.lang.String[] descriptorData = { + "\n+target/org.hyperledger.chaintool.meta." + + "proto\022\036org.hyperledger.chaintool.meta\"1\n" + + "\023InterfaceDescriptor\022\014\n\004name\030\001 \001(\t\022\014\n\004da" + + "ta\030\002 \001(\014\"V\n\nInterfaces\022H\n\013descriptors\030\001 " + + "\003(\01323.org.hyperledger.chaintool.meta.Int" + + "erfaceDescriptor\"-\n\023GetInterfacesParams\022" + + "\026\n\016IncludeContent\030\001 \001(\010\"\"\n\022GetInterfaceP" + + "arams\022\014\n\004name\030\001 \001(\t\"\020\n\016GetFactsParams\"g\n" + + "\005Facts\0229\n\005facts\030\001 \003(\0132*.org.hyperledger." + + "chaintool.meta.Facts.Fact\032#\n\004Fact\022\014\n\004nam", + "e\030\001 \001(\t\022\r\n\005value\030\002 \001(\tb\006proto3" + }; + com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner = + new com.google.protobuf.Descriptors.FileDescriptor. InternalDescriptorAssigner() { + public com.google.protobuf.ExtensionRegistry assignDescriptors( + com.google.protobuf.Descriptors.FileDescriptor root) { + descriptor = root; + return null; + } + }; + com.google.protobuf.Descriptors.FileDescriptor + .internalBuildGeneratedFileFrom(descriptorData, + new com.google.protobuf.Descriptors.FileDescriptor[] { + }, assigner); + internal_static_org_hyperledger_chaintool_meta_InterfaceDescriptor_descriptor = + getDescriptor().getMessageTypes().get(0); + internal_static_org_hyperledger_chaintool_meta_InterfaceDescriptor_fieldAccessorTable = new + com.google.protobuf.GeneratedMessage.FieldAccessorTable( + internal_static_org_hyperledger_chaintool_meta_InterfaceDescriptor_descriptor, + new java.lang.String[] { "Name", "Data", }); + internal_static_org_hyperledger_chaintool_meta_Interfaces_descriptor = + getDescriptor().getMessageTypes().get(1); + internal_static_org_hyperledger_chaintool_meta_Interfaces_fieldAccessorTable = new + com.google.protobuf.GeneratedMessage.FieldAccessorTable( + internal_static_org_hyperledger_chaintool_meta_Interfaces_descriptor, + new java.lang.String[] { "Descriptors", }); + internal_static_org_hyperledger_chaintool_meta_GetInterfacesParams_descriptor = + getDescriptor().getMessageTypes().get(2); + internal_static_org_hyperledger_chaintool_meta_GetInterfacesParams_fieldAccessorTable = new + com.google.protobuf.GeneratedMessage.FieldAccessorTable( + internal_static_org_hyperledger_chaintool_meta_GetInterfacesParams_descriptor, + new java.lang.String[] { "IncludeContent", }); + internal_static_org_hyperledger_chaintool_meta_GetInterfaceParams_descriptor = + getDescriptor().getMessageTypes().get(3); + internal_static_org_hyperledger_chaintool_meta_GetInterfaceParams_fieldAccessorTable = new + com.google.protobuf.GeneratedMessage.FieldAccessorTable( + internal_static_org_hyperledger_chaintool_meta_GetInterfaceParams_descriptor, + new java.lang.String[] { "Name", }); + internal_static_org_hyperledger_chaintool_meta_GetFactsParams_descriptor = + getDescriptor().getMessageTypes().get(4); + internal_static_org_hyperledger_chaintool_meta_GetFactsParams_fieldAccessorTable = new + com.google.protobuf.GeneratedMessage.FieldAccessorTable( + internal_static_org_hyperledger_chaintool_meta_GetFactsParams_descriptor, + new java.lang.String[] { }); + internal_static_org_hyperledger_chaintool_meta_Facts_descriptor = + getDescriptor().getMessageTypes().get(5); + internal_static_org_hyperledger_chaintool_meta_Facts_fieldAccessorTable = new + com.google.protobuf.GeneratedMessage.FieldAccessorTable( + internal_static_org_hyperledger_chaintool_meta_Facts_descriptor, + new java.lang.String[] { "Facts", }); + internal_static_org_hyperledger_chaintool_meta_Facts_Fact_descriptor = + internal_static_org_hyperledger_chaintool_meta_Facts_descriptor.getNestedTypes().get(0); + internal_static_org_hyperledger_chaintool_meta_Facts_Fact_fieldAccessorTable = new + com.google.protobuf.GeneratedMessage.FieldAccessorTable( + internal_static_org_hyperledger_chaintool_meta_Facts_Fact_descriptor, + new java.lang.String[] { "Name", "Value", }); + } + + // @@protoc_insertion_point(outer_class_scope) +} diff --git a/test/chaintool/build/test_interface.clj b/test/chaintool/build/test_interface.clj new file mode 100644 index 0000000..ec944ac --- /dev/null +++ b/test/chaintool/build/test_interface.clj @@ -0,0 +1,161 @@ +;; Copyright London Stock Exchange Group 2016 All Rights Reserved. +;; +;; Licensed under the Apache License, Version 2.0 (the "License"); +;; you may not use this file except in compliance with the License. +;; You may obtain a copy of the License at +;; +;; http://www.apache.org/licenses/LICENSE-2.0 +;; +;; Unless required by applicable law or agreed to in writing, software +;; distributed under the License is distributed on an "AS IS" BASIS, +;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +;; See the License for the specific language governing permissions and +;; limitations under the License. + +(ns chaintool.build.test_interface + (:require [clojure.test :refer :all] + [chaintool.build.interface :refer :all] + [slingshot.slingshot :as slingshot]) + (:refer-clojure :exclude [compile])) + +(def example1-cci + " + # This is a comment + // So is this + + message ActiveMessage { + // mid-message comment + string param1 = 1; # trailing comment + int32 param2 = 2; + int64 param3 = 3; + } + + //message CommentedMessage { + // int32 param1 = 1; + //} + ") + +(def example1-expected-result + [[:interface [:message "ActiveMessage" [:field [:type [:scalar "string"]] [:fieldName "param1"] [:index "1"]] [:field [:type [:scalar "int32"]] [:fieldName "param2"] [:index "2"]] [:field [:type [:scalar "int64"]] [:fieldName "param3"] [:index "3"]]]] nil]) + +(def example2-cci + " + message NestedMessage { + message Entry { + string key = 1; + int32 value = 2; + } + + repeated Entry entries = 1; + } + + ") + +(def example2-expected-result + [[:interface [:message "NestedMessage" [:message "Entry" [:field [:type [:scalar "string"]] [:fieldName "key"] [:index "1"]] [:field [:type [:scalar "int32"]] [:fieldName "value"] [:index "2"]]] [:field [:modifier "repeated"] [:type [:userType "Entry"]] [:fieldName "entries"] [:index "1"]]]] nil]) + +(deftest test-parser-output + (is (= example1-expected-result (parse example1-cci))) + (is (= example2-expected-result (parse example2-cci)))) + +(def example-undefined-type-cci + " + message BadMessage { + message Entry { + string key = 1; + UnknownType value = 2; + } + + repeated Entry entries = 1; + } + + ") + +(deftest test-parser-validation + (let [intf (parse example-undefined-type-cci)] + (is (some? (verify-intf intf))))) + +(def example-type-resolution + " + message Party { + string entity = 1; + int32 value = 2; + } + + message Init { + Party partyA = 1; + Party partyB = 2; + } + ") + +(deftest test-type-resolution + (let [intf (parse example-type-resolution)] + (is (nil? (verify-intf intf))))) + +(def example-conflicting-index + " + message Conflict { + string foo = 1; + int32 bar = 2; + int32 baz = 1; + } + + ") + +(deftest test-conflict-detection + (let [intf (parse example-conflicting-index)] + (is (some? (verify-intf intf))))) + +(def example-enum + " + enum MyEnum { + ZERO = 0; + ONE = 1; + TWO = 2; + } + + ") + +(deftest test-enum + (let [intf (parse example-enum)] + (is (nil? (verify-intf intf))))) + +(def example-conflicting-enum + " + enum ConflictingEnum { + ZERO = 0; + ONE = 1; + TWO = 1; + } + + ") + +(deftest test-conflicting-enum + (let [intf (parse example-conflicting-enum)] + (is (some? (verify-intf intf))))) + +(def example-bad-default-enum + " + enum BadDefaultEnum { + ZERO = 1; + ONE = 2; + TWO = 3; + } + + ") + +(deftest test-bad-default-enum + (let [intf (parse example-bad-default-enum)] + (is (some? (verify-intf intf))))) + +(def example-no-parameters + " + queries { + string Parameterless() = 1; + } + + ") + +(deftest test-no-parameters + (let [intf (parse example-no-parameters)] + (is (nil? (verify-intf intf))))) diff --git a/test/chaintool/platforms/golang/test_core.clj b/test/chaintool/platforms/golang/test_core.clj new file mode 100644 index 0000000..c33e34c --- /dev/null +++ b/test/chaintool/platforms/golang/test_core.clj @@ -0,0 +1,22 @@ +;; Copyright London Stock Exchange Group 2016 All Rights Reserved. +;; +;; Licensed under the Apache License, Version 2.0 (the "License"); +;; you may not use this file except in compliance with the License. +;; You may obtain a copy of the License at +;; +;; http://www.apache.org/licenses/LICENSE-2.0 +;; +;; Unless required by applicable law or agreed to in writing, software +;; distributed under the License is distributed on an "AS IS" BASIS, +;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +;; See the License for the specific language governing permissions and +;; limitations under the License. + +(ns chaintool.platforms.golang.test_core + (:require [clojure.test :refer :all] + [chaintool.platforms.golang.core :refer :all]) + (:refer-clojure :exclude [compile])) + +(deftest test-buildgopath + (let [gopath (buildgopath "foo")] + (is (some? gopath)))) diff --git a/test/chaintool/platforms/golang/test_system.clj b/test/chaintool/platforms/golang/test_system.clj new file mode 100644 index 0000000..af067f7 --- /dev/null +++ b/test/chaintool/platforms/golang/test_system.clj @@ -0,0 +1,28 @@ +;; Copyright London Stock Exchange Group 2016 All Rights Reserved. +;; +;; Licensed under the Apache License, Version 2.0 (the "License"); +;; you may not use this file except in compliance with the License. +;; You may obtain a copy of the License at +;; +;; http://www.apache.org/licenses/LICENSE-2.0 +;; +;; Unless required by applicable law or agreed to in writing, software +;; distributed under the License is distributed on an "AS IS" BASIS, +;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +;; See the License for the specific language governing permissions and +;; limitations under the License. + +(ns chaintool.platforms.golang.test_system + (:require [clojure.test :refer :all] + [chaintool.platforms.golang.system :refer :all]) + (:refer-clojure :exclude [compile])) + +(deftest test-standalone-gopath-computation + (let [gopath (compute-gopath "/local-dev/git/chaintool/testdata/sample_syscc" + "_/local-dev/git/chaintool/testdata/sample_syscc")] + (is (= gopath "/")))) + +(deftest test-gopath-computation + (let [gopath (compute-gopath "/opt/gopath/src/github.com/hyperledger/fabric/core/system_chaincode/sample" + "github.com/hyperledger/fabric/core/system_chaincode/sample")] + (is (= gopath "/opt/gopath/src")))) diff --git a/test/chaintool/protobuf/test_generate.clj b/test/chaintool/protobuf/test_generate.clj new file mode 100644 index 0000000..2742913 --- /dev/null +++ b/test/chaintool/protobuf/test_generate.clj @@ -0,0 +1,103 @@ +;; Copyright London Stock Exchange Group 2016 All Rights Reserved. +;; +;; Licensed under the Apache License, Version 2.0 (the "License"); +;; you may not use this file except in compliance with the License. +;; You may obtain a copy of the License at +;; +;; http://www.apache.org/licenses/LICENSE-2.0 +;; +;; Unless required by applicable law or agreed to in writing, software +;; distributed under the License is distributed on an "AS IS" BASIS, +;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +;; See the License for the specific language governing permissions and +;; limitations under the License. + +(ns chaintool.protobuf.test_generate + (:require [clojure.test :refer :all] + [clojure.java.io :as io] + [clojure.zip :as zip] + [instaparse.core :as insta] + [chaintool.ast :as ast] + [chaintool.protobuf.generate :as pb] + [slingshot.slingshot :as slingshot]) + (:refer-clojure :exclude [compile])) + +(def skipper (insta/parser (io/resource "parsers/proto/skip.bnf"))) +(def grammar (insta/parser (io/resource "parsers/proto/grammar.bnf") :auto-whitespace skipper)) + +(defn- parse [intf] + (let [result (insta/add-line-and-column-info-to-metadata intf (grammar intf))] + (if (insta/failure? result) + (let [{:keys [line column text]} result] + (str "could not parse \"" text "\": line=" line " column=" column)) + (zip/vector-zip result)))) + +(defn- find + "Finds an arbitrary item in the tree based on (pred)" + [ast pred] + (loop [loc ast] + (cond + + (or (nil? loc) (zip/end? loc)) + nil + + (pred loc) + loc + + :else + (recur (zip/next loc))))) + +(defn- tree-depth + "Counts the zipper depth of the node represented by ast" + [ast] + (loop [loc ast depth 0] + (cond + + (or (nil? loc) (zip/end? loc)) + depth + + :else + (recur (zip/up loc) (inc depth))))) + +(defn- round-about + "takes an AST, exports it to protobuf, and then reparses the protobuf back to a new AST" + [ast] + (let [pb (->> ["fictional.interface" ast] (pb/to-string "fictional.package"))] + (parse pb))) + +(def nested-input + (zip/vector-zip + [:interface + [:message "NestedMessage" + [:message "Entry" + [:field [:type [:scalar "string"]] [:fieldName "key"] [:index "1"]] + [:field [:type [:scalar "int32"]] [:fieldName "value"] [:index "2"]]] + [:field [:modifier "repeated"] [:type [:userType "Entry"]] [:fieldName "entries"] [:index "1"]] + [:message "Level1" + [:message "Level2" + [:message "Level3" + [:message "Level4"]]]]]])) + +(deftest nested-messages + (let [result (round-about nested-input) + level4 (find result (fn [loc] (= (zip/node loc) "Level4")))] + (is level4) + (is (= (tree-depth level4) 7)))) + +(def enum-input + (zip/vector-zip + [:interface [:enum "MyEnum" [:enumField "ZERO" 0] [:enumField "ONE" 1] [:enumField "TWO" 2]]])) + +(deftest enum-test + (let [result (round-about enum-input)] + (is (= (->> result zip/down zip/node) :proto)) + (is (= (->> result (ast/find :syntax) zip/down zip/right zip/node) "proto3")) + (is (= (->> result (ast/find :enum) zip/down zip/right zip/right zip/node) [:enumField "ZERO" "0"])))) + +(def parameterless-function + (zip/vector-zip + [:interface [:queries [:function [:rettype "string"] [:functionName "Parameterless"] [:index "1"]]]])) + +(deftest parameterless-test + (let [result (round-about parameterless-function)] + (some? result)))