├── .dockerignore ├── .env ├── .github ├── settings.yml └── workflows │ ├── 0-4-cron-update-status.yaml │ ├── 0-4-cron.yaml │ ├── build-debs.yaml │ ├── build-docs.yaml │ ├── lint-transact.yaml │ ├── merge.yaml │ ├── publish-crates.yaml │ └── test-transact.yaml ├── .gitignore ├── CODEOWNERS ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── Cargo.toml ├── LICENSE ├── MAINTAINERS.md ├── README.md ├── RELEASE_NOTES.md ├── SECURITY.md ├── VERSION ├── bin └── get_version ├── ci ├── publish-crates └── publish-transact-crates ├── cli ├── Cargo.toml ├── Dockerfile ├── build.rs ├── man │ ├── TEMPLATE.1.md.example │ ├── transact-command-get-state.1.md │ ├── transact-command-set-state.1.md │ ├── transact-command-show-state.1.md │ ├── transact-command.1.md │ ├── transact-playlist-batch.1.md │ ├── transact-playlist-create.1.md │ ├── transact-playlist-process.1.md │ ├── transact-playlist-submit.1.md │ ├── transact-playlist.1.md │ ├── transact-workload.1.md │ └── transact.1.md ├── packaging │ └── man │ │ └── README.md └── src │ ├── action │ ├── command.rs │ ├── mod.rs │ ├── playlist.rs │ ├── time.rs │ └── workload.rs │ ├── error.rs │ ├── main.rs │ └── request_logger.rs ├── docker-compose-installed.yaml ├── docker ├── Dockerfile └── compose │ ├── .env │ ├── copy-debs.yaml │ └── docker-compose.yaml ├── examples ├── address_generator │ ├── Cargo.toml │ └── src │ │ └── main.rs ├── sabre_command │ ├── Cargo.toml │ ├── Dockerfile-scar │ ├── packaging │ │ └── scar │ │ │ └── manifest.yaml │ └── src │ │ └── main.rs ├── sabre_command_executor │ ├── Cargo.toml │ └── src │ │ ├── error.rs │ │ └── main.rs ├── sabre_smallbank │ ├── Cargo.toml │ ├── Dockerfile-scar │ ├── packaging │ │ └── scar │ │ │ └── manifest.yaml │ └── src │ │ └── main.rs └── simple_xo │ ├── Cargo.toml │ └── src │ └── main.rs ├── justfile └── libtransact ├── Cargo.toml ├── build.rs ├── protos ├── batch.proto ├── command.proto ├── events.proto ├── key_value_state.proto ├── merkle.proto ├── sabre_contract.proto ├── sabre_contract_registry.proto ├── sabre_namespace_registry.proto ├── sabre_payload.proto ├── smallbank.proto ├── transaction.proto └── transaction_receipt.proto ├── src ├── collections │ ├── mod.rs │ └── ref_map.rs ├── context │ ├── error.rs │ ├── manager │ │ ├── mod.rs │ │ └── sync.rs │ └── mod.rs ├── contract │ ├── address │ │ ├── double_key_hash.rs │ │ ├── error.rs │ │ ├── key_hash.rs │ │ ├── mod.rs │ │ └── triple_key_hash.rs │ ├── archive │ │ ├── error.rs │ │ └── mod.rs │ ├── context │ │ ├── error.rs │ │ ├── key_value.rs │ │ └── mod.rs │ └── mod.rs ├── database │ ├── btree.rs │ ├── error.rs │ ├── lmdb.rs │ └── mod.rs ├── error │ ├── internal.rs │ ├── invalid_state.rs │ └── mod.rs ├── execution │ ├── adapter │ │ ├── error.rs │ │ ├── mod.rs │ │ ├── static_adapter.rs │ │ └── test_adapter.rs │ ├── executor │ │ ├── error.rs │ │ ├── internal.rs │ │ ├── mod.rs │ │ └── reader.rs │ └── mod.rs ├── families │ ├── command │ │ ├── handler.rs │ │ ├── mod.rs │ │ ├── transaction_builder.rs │ │ └── workload │ │ │ ├── command_iter.rs │ │ │ └── mod.rs │ ├── mod.rs │ ├── sabre │ │ ├── addressing.rs │ │ ├── admin │ │ │ ├── allow_all.rs │ │ │ ├── mod.rs │ │ │ └── settings.rs │ │ ├── handler.rs │ │ ├── mod.rs │ │ ├── payload.rs │ │ ├── state.rs │ │ └── wasm_executor │ │ │ ├── mod.rs │ │ │ ├── wasm_externals.rs │ │ │ └── wasm_module.rs │ ├── smallbank │ │ ├── handler.rs │ │ ├── mod.rs │ │ └── workload │ │ │ ├── error.rs │ │ │ ├── mod.rs │ │ │ └── playlist.rs │ └── xo.rs ├── handler │ ├── error.rs │ ├── mod.rs │ └── sabre.rs ├── lib.rs ├── protocol │ ├── batch.rs │ ├── command.rs │ ├── key_value_state.rs │ ├── mod.rs │ ├── receipt.rs │ ├── sabre │ │ ├── mod.rs │ │ ├── payload.rs │ │ └── state.rs │ └── transaction.rs ├── protos.rs ├── sawtooth.rs ├── scheduler │ ├── mod.rs │ ├── multi │ │ ├── core.rs │ │ ├── mod.rs │ │ └── shared.rs │ ├── parallel │ │ ├── mod.rs │ │ └── tree.rs │ └── serial │ │ ├── core.rs │ │ ├── execution.rs │ │ ├── mod.rs │ │ └── shared.rs ├── state │ ├── committer.rs │ ├── dry_run_committer.rs │ ├── error.rs │ ├── hashmap.rs │ ├── merkle │ │ ├── error.rs │ │ ├── kv │ │ │ ├── change_log.rs │ │ │ ├── error.rs │ │ │ ├── mod.rs │ │ │ └── state_trait_impls │ │ │ │ ├── committer.rs │ │ │ │ ├── dry_run_committer.rs │ │ │ │ ├── mod.rs │ │ │ │ ├── pruner.rs │ │ │ │ └── reader.rs │ │ ├── mod.rs │ │ ├── node.rs │ │ └── sql │ │ │ ├── backend │ │ │ ├── mod.rs │ │ │ ├── postgres.rs │ │ │ └── sqlite.rs │ │ │ ├── cache.rs │ │ │ ├── error.rs │ │ │ ├── migration │ │ │ ├── mod.rs │ │ │ ├── postgres │ │ │ │ ├── migrations │ │ │ │ │ ├── 2021-09-09-121000-initialize-tables │ │ │ │ │ │ ├── down.sql │ │ │ │ │ │ └── up.sql │ │ │ │ │ └── 2022-03-06-add-pruned-column │ │ │ │ │ │ ├── down.sql │ │ │ │ │ │ └── up.sql │ │ │ │ └── mod.rs │ │ │ └── sqlite │ │ │ │ ├── migrations │ │ │ │ ├── 2021-09-09-121000-initialize-tables │ │ │ │ │ ├── down.sql │ │ │ │ │ └── up.sql │ │ │ │ ├── 2022-01-06-101500-correct-column-type │ │ │ │ │ ├── down.sql │ │ │ │ │ └── up.sql │ │ │ │ └── 2022-03-06-add-pruned-column │ │ │ │ │ ├── down.sql │ │ │ │ │ └── up.sql │ │ │ │ └── mod.rs │ │ │ ├── mod.rs │ │ │ ├── postgres.rs │ │ │ ├── sqlite.rs │ │ │ └── store │ │ │ ├── mod.rs │ │ │ ├── models │ │ │ ├── mod.rs │ │ │ ├── postgres.rs │ │ │ └── sqlite.rs │ │ │ ├── operations │ │ │ ├── delete_tree.rs │ │ │ ├── get_leaves.rs │ │ │ ├── get_or_create_tree.rs │ │ │ ├── get_path.rs │ │ │ ├── get_tree_by_name.rs │ │ │ ├── has_root.rs │ │ │ ├── list_leaves.rs │ │ │ ├── list_trees.rs │ │ │ ├── mod.rs │ │ │ ├── prepared_stmt.rs │ │ │ ├── prune_entries.rs │ │ │ ├── remove_pruned_entries.rs │ │ │ └── write_changes.rs │ │ │ ├── postgres.rs │ │ │ ├── schema.rs │ │ │ └── sqlite.rs │ ├── mod.rs │ ├── pruner.rs │ ├── reader.rs │ └── state_trait.rs └── workload │ ├── batch_gen.rs │ ├── batch_reader │ ├── mod.rs │ └── protobuf.rs │ ├── error.rs │ ├── mod.rs │ ├── runner.rs │ └── transaction_reader │ ├── mod.rs │ └── protobuf.rs └── tests ├── mod.rs └── state ├── merkle ├── btree.rs ├── lmdb.rs ├── mod.rs ├── sql_postgres.rs ├── sql_sqlite.rs └── sqlitedb.rs └── mod.rs /.dockerignore: -------------------------------------------------------------------------------- 1 | **/*.rs.bk 2 | **/target/ 3 | *.swp 4 | -------------------------------------------------------------------------------- /.env: -------------------------------------------------------------------------------- 1 | ISOLATION_ID=latest 2 | REPO_VERSION=0.5.1-dev 3 | -------------------------------------------------------------------------------- /.github/settings.yml: -------------------------------------------------------------------------------- 1 | repository: 2 | name: transact 3 | description: Transact is a transaction execution platform designed to be used 4 | as a library or component when implementing distributed ledgers, including 5 | blockchains. 6 | homepage: https://wiki.hyperledger.org/display/transact 7 | topics: distributed ledger, smart contract, blockchain 8 | private: false 9 | has_issues: true 10 | has_projects: false 11 | has_wiki: false 12 | has_downloads: false 13 | default_branch: main 14 | allow_squash_merge: false 15 | allow_merge_commit: true 16 | allow_rebase_merge: true 17 | -------------------------------------------------------------------------------- /.github/workflows/0-4-cron-update-status.yaml: -------------------------------------------------------------------------------- 1 | name: 0-4 Update Branch Status 2 | 3 | on: 4 | workflow_run: 5 | workflows: ["0-4 Cron"] 6 | types: 7 | - completed 8 | 9 | jobs: 10 | update_status: 11 | runs-on: ubuntu-18.04 12 | steps: 13 | - uses: actions/checkout@v2 14 | with: 15 | fetch-depth: 0 16 | ref: 0-4 17 | 18 | - name: get SHA 19 | run: echo "SHA=$(git rev-parse HEAD)" >> $GITHUB_ENV 20 | 21 | - name: Update commit status 22 | run: | 23 | env 24 | curl \ 25 | -X POST \ 26 | -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \ 27 | -H "Accept: application/vnd.github.v3+json" \ 28 | https://api.github.com/repos/${{ github.repository }}/statuses/${{ env.SHA }} \ 29 | -d '{"state": "${{ github.event.workflow_run.conclusion }}", "context": "Cron"}' 30 | -------------------------------------------------------------------------------- /.github/workflows/build-debs.yaml: -------------------------------------------------------------------------------- 1 | name: Build Debs 2 | 3 | on: 4 | pull_request: 5 | 6 | env: 7 | CARGO_TERM_COLOR: always 8 | 9 | concurrency: 10 | group: "${{ github.ref }}-${{ github.workflow }}" 11 | cancel-in-progress: true 12 | 13 | jobs: 14 | build_debs: 15 | runs-on: ubuntu-latest 16 | steps: 17 | - uses: actions/checkout@v2 18 | with: 19 | fetch-depth: 0 20 | 21 | - name: Display envvars 22 | run: env 23 | 24 | - name: Install Just 25 | run: curl --proto '=https' --tlsv1.2 -sSf https://just.systems/install.sh | sudo bash -s -- --to /usr/local/bin 26 | 27 | - name: Build Debs 28 | run: just ci-debs 29 | -------------------------------------------------------------------------------- /.github/workflows/build-docs.yaml: -------------------------------------------------------------------------------- 1 | name: Build Docs 2 | 3 | on: 4 | pull_request: 5 | 6 | env: 7 | CARGO_TERM_COLOR: always 8 | 9 | concurrency: 10 | group: "${{ github.ref }}-${{ github.workflow }}" 11 | cancel-in-progress: true 12 | 13 | jobs: 14 | build_docs: 15 | runs-on: ubuntu-latest 16 | steps: 17 | - uses: actions/checkout@v2 18 | 19 | - name: Display envvars 20 | run: env 21 | 22 | - name: Install Just 23 | run: curl --proto '=https' --tlsv1.2 -sSf https://just.systems/install.sh | sudo bash -s -- --to /usr/local/bin 24 | 25 | - name: Build Docs 26 | run: just ci-doc 27 | -------------------------------------------------------------------------------- /.github/workflows/lint-transact.yaml: -------------------------------------------------------------------------------- 1 | name: Lint Transact 2 | 3 | on: 4 | pull_request: 5 | 6 | env: 7 | CARGO_TERM_COLOR: always 8 | 9 | concurrency: 10 | group: "${{ github.ref }}-${{ github.workflow }}" 11 | cancel-in-progress: true 12 | 13 | jobs: 14 | lint_transact: 15 | runs-on: ubuntu-latest 16 | steps: 17 | - uses: actions/checkout@v2 18 | 19 | - name: Display envvars 20 | run: env 21 | 22 | - name: Install Just 23 | run: curl --proto '=https' --tlsv1.2 -sSf https://just.systems/install.sh | sudo bash -s -- --to /usr/local/bin 24 | 25 | - name: Run Lint/Clippy on Transact 26 | run: just ci-lint 27 | -------------------------------------------------------------------------------- /.github/workflows/publish-crates.yaml: -------------------------------------------------------------------------------- 1 | name: Publish Crates 2 | 3 | on: 4 | push: 5 | tags: 6 | - '*' 7 | 8 | env: 9 | slack-channel: 'alerts' 10 | 11 | jobs: 12 | 13 | test_transact: 14 | if: >- 15 | github.repository_owner == 'hyperledger' 16 | runs-on: ubuntu-latest 17 | steps: 18 | - uses: actions/checkout@v2 19 | with: 20 | fetch-depth: 0 21 | 22 | - name: Display envvars 23 | run: env 24 | 25 | - name: Install Just 26 | run: curl --proto '=https' --tlsv1.2 -sSf https://just.systems/install.sh | sudo bash -s -- --to /usr/local/bin 27 | 28 | - name: Run tests 29 | run: just ci-test 30 | 31 | publish_to_crates: 32 | needs: test_transact 33 | if: >- 34 | github.repository_owner == 'hyperledger' 35 | runs-on: ubuntu-latest 36 | steps: 37 | - uses: actions/checkout@v2 38 | with: 39 | fetch-depth: 0 40 | 41 | - name: Display envvars 42 | run: env 43 | 44 | - name: Publish release to crates 45 | run: | 46 | git fetch --tags --force 47 | CARGO_TOKEN=${{ secrets.CARGO_TOKEN }} ./ci/publish-crates 48 | - name: Notify Slack of Failure 49 | if: failure() 50 | uses: 8398a7/action-slack@v3 51 | with: 52 | status: ${{ job.status }} 53 | fields: repo,message,author,job 54 | env: 55 | SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }} 56 | -------------------------------------------------------------------------------- /.github/workflows/test-transact.yaml: -------------------------------------------------------------------------------- 1 | name: Test Transact 2 | 3 | on: 4 | pull_request: 5 | 6 | env: 7 | CARGO_TERM_COLOR: always 8 | 9 | concurrency: 10 | group: "${{ github.ref }}-${{ github.workflow }}" 11 | cancel-in-progress: true 12 | 13 | jobs: 14 | test_transact: 15 | runs-on: ubuntu-latest 16 | steps: 17 | - uses: actions/checkout@v2 18 | 19 | - name: Display envvars 20 | run: env 21 | 22 | - name: Install Just 23 | run: curl --proto '=https' --tlsv1.2 -sSf https://just.systems/install.sh | sudo bash -s -- --to /usr/local/bin 24 | 25 | - name: Test Transact 26 | run: just ci-test 27 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | **/*.rs.bk 2 | 3 | **/target 4 | /Cargo.lock 5 | 6 | /cli/packaging/man/*.1 7 | 8 | /examples/sabre_command/target 9 | /examples/sabre_command/Cargo.lock 10 | /examples/sabre_command_executor/target 11 | /examples/sabre_command_executor/Cargo.lock 12 | /examples/sabre_smallbank/target 13 | /examples/sabre_smallbank/Cargo.lock 14 | 15 | # Editor files 16 | .idea/ 17 | 18 | /build/ 19 | -------------------------------------------------------------------------------- /CODEOWNERS: -------------------------------------------------------------------------------- 1 | * @agunde406 @isabeltomb @jsmitchell @ltseeley @peterschwarz @rberg2 @rbuysse @ryanlassigbanks @shannynalayna @vaporos 2 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | Code of Conduct Guidelines 2 | ========================== 3 | 4 | Please review the Hyperledger [Code of 5 | Conduct](https://tsc.hyperledger.org/code-of-conduct.html) before participating 6 | and abide by these community standards. 7 | 8 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | Contributions Guide 2 | =================== 3 | 4 | We welcome contributions, eagerly. The contributions to Transact 5 | follow a similar process to 6 | [Sawtooth](https://sawtooth.hyperledger.org/docs/core/releases/latest/community/contributing.html). 7 | 8 | 9 | Creative Commons License 12 | 13 |
This work is licensed under a 14 | Creative 16 | Commons Attribution 4.0 International License. -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [workspace] 2 | members = [ 3 | "libtransact", 4 | "examples/simple_xo", 5 | "examples/address_generator", 6 | "examples/sabre_command", 7 | "examples/sabre_command_executor", 8 | "examples/sabre_smallbank", 9 | "cli" 10 | ] 11 | 12 | # Exclude sabre_smallbank and sabre_command to avoid incompatible features 13 | # `sabre-compat` and `log` 14 | exclude = ["examples/sabre_smallbank", "examples/sabre_command"] 15 | -------------------------------------------------------------------------------- /MAINTAINERS.md: -------------------------------------------------------------------------------- 1 | ## Maintainers 2 | 3 | ### Active Maintainers 4 | | Name | GitHub | 5 | | --- | --- | 6 | | Andi Gunderson | agunde406 | 7 | | Isabel Tomb | isabeltomb | 8 | | James Mitchell | jsmitchell | 9 | | Logan Seeley | ltseeley | 10 | | Peter Schwarz | peterschwarz | 11 | | Richard Berg | rberg2 | 12 | | Ryan Beck-Buysse | rbuysse | 13 | | Ryan Banks | ryanlassigbanks | 14 | | Shannyn Telander | shannynalayna | 15 | | Shawn Amundson | vaporos | 16 | 17 | ### Retired Maintainers 18 | | Name | GitHub | 19 | | --- | --- | 20 | | Eloá Franca Verona | eloaverona | 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | > ⚠️ 2 | > 3 | > Transact is now maintained as part of the Splinter Community. The 4 | > Hyperledger Transact incarnation has been moved to ARCHIVED status. 5 | > 6 | > More information about Transact can be found at its new home: 7 | > https://github.com/splintercommunity/transact 8 | 9 | --- 10 | 11 | # Hyperledger Transact 12 | 13 | Hyperledger Transact is a platform-agnostic library for executing transactions 14 | with smart contracts. 15 | 16 | The Hyperledger Transact project includes several repositories: 17 | 18 | - [This repository](https://github.com/hyperledger/transact) contains the core 19 | Transact Rust library. 20 | 21 | - The [transact-contrib](https://github.com/hyperledger/transact-contrib) 22 | repository contains examples and reference implementations. 23 | 24 | - The [transact-rfcs](https://github.com/hyperledger/transact-rfcs) repository 25 | contains RFCs (requests for comments) for proposed and approved changes to 26 | Hyperledger Transact. 27 | 28 | ## How to Participate 29 | 30 | We welcome contributors, both organizations and individuals, to help shape 31 | project direction, contribute ideas, provide use cases, and work on specific 32 | tools and examples. Please join the discussion in the [mailing 33 | list](https://lists.hyperledger.org/g/transact) and 34 | [#transact](https://chat.hyperledger.org/channel/transact) channel. 35 | 36 | ### Inclusive Language 37 | 38 | - Consider that users who will read the docs are from different background and 39 | cultures and that they have different preferences. 40 | - Avoid potential offensive terms and, for instance, prefer "allow list and 41 | deny list" to "white list and black list". 42 | - We believe that we all have a role to play to improve our world, and even if 43 | writing inclusive doc might not look like a huge improvement, it's a first 44 | step in the right direction. 45 | - We suggest to refer to [Microsoft bias free writing 46 | guidelines](https://learn.microsoft.com/en-us/style-guide/bias-free-communication) 47 | and [Google inclusive doc writing 48 | guide](https://developers.google.com/style/inclusive-documentation) 49 | as starting points. 50 | 51 | ## More Information 52 | 53 | - [Rust crate and documentation](https://crates.io/crates/transact) 54 | - [Hyperledger Transact mailing list](https://lists.hyperledger.org/g/transact) 55 | - [#transact discussion channel](https://chat.hyperledger.org/channel/transact) 56 | - [Hyperledger Transact project overview](https://www.hyperledger.org/projects/transact) at 57 | [hyperledger.org](https://www.hyperledger.org) 58 | 59 | ## License 60 | 61 | Hyperledger Transact software is licensed under the [Apache License Version 62 | 2.0](LICENSE) software license. 63 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Hyperledger Security Policy 2 | 3 | ## Reporting a Security Bug 4 | 5 | If you think you have discovered a security issue in any of the Hyperledger 6 | projects, we'd love to hear from you. We will take all security bugs 7 | seriously and if confirmed upon investigation we will patch it within a 8 | reasonable amount of time and release a public security bulletin discussing 9 | the impact and credit the discoverer. 10 | 11 | There are two ways to report a security bug. The easiest is to email a 12 | description of the flaw and any related information (e.g. reproduction 13 | steps, version) to 14 | [security at hyperledger dot org](mailto:security@hyperledger.org). 15 | 16 | The other way is to file a confidential security bug in our 17 | [JIRA bug tracking system](https://jira.hyperledger.org). 18 | Be sure to set the “Security Level” to “Security issue”. 19 | 20 | The process by which the Hyperledger Security Team handles security bugs 21 | is documented further in our 22 | [Defect Response](https://wiki.hyperledger.org/display/HYP/Defect+Response) 23 | page on our [wiki](https://wiki.hyperledger.org). 24 | -------------------------------------------------------------------------------- /VERSION: -------------------------------------------------------------------------------- 1 | 0.5.1 2 | -------------------------------------------------------------------------------- /bin/get_version: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # Copyright 2016, 2017 Intel Corporation 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | # ------------------------------------------------------------------------------ 17 | 18 | import os 19 | import subprocess 20 | import sys 21 | 22 | top_dir = os.path.dirname(os.path.dirname(os.path.realpath(__file__))) 23 | 24 | version_file = top_dir + "/VERSION" 25 | 26 | with open(version_file, 'r') as f: 27 | version_data = f.read().strip() 28 | 29 | 30 | def bump_version(version): 31 | (major, minor, patch) = version.split('.') 32 | if 'rc' in patch: 33 | parts = patch.split('rc') 34 | parts[1] = str(int(parts[1]) + 1) 35 | patch = "rc".join(parts) 36 | else: 37 | patch = str(int(patch) + 1) 38 | return ".".join([major, minor, patch]) 39 | 40 | 41 | def auto_version(default, strict): 42 | output = subprocess.check_output(['git', 'describe', '--dirty']) 43 | parts = output.decode('utf-8').strip().split('-', 3) 44 | parts[0] = parts[0][1:] # strip the leading 'v' 45 | if len(parts) > 1: 46 | parts[0] = bump_version(parts[0]) 47 | if default != parts[0]: 48 | msg = "VERSION file and (bumped?) git describe versions differ: " \ 49 | "{} != {}".format(default, parts[0]) 50 | if strict: 51 | print("ERROR: " + msg, file=sys.stderr) 52 | sys.exit(1) 53 | else: 54 | print("WARNING: " + msg, file=sys.stderr) 55 | parts[0] = default 56 | 57 | if len(parts) > 1: 58 | parts[0] = "-dev".join([parts[0], parts[1].replace("-", ".")]) 59 | if len(parts) == 4: 60 | parts[0] = parts[0] + "-" + parts[3] 61 | return parts[0] 62 | else: 63 | return parts[0] 64 | 65 | 66 | def version(default): 67 | if 'VERSION' in os.environ: 68 | if os.environ['VERSION'] == 'AUTO_STRICT': 69 | version = auto_version(default, strict=True) 70 | elif os.environ['VERSION'] == 'AUTO': 71 | version = auto_version(default, strict=False) 72 | else: 73 | version = os.environ['VERSION'] 74 | else: 75 | version = default + "-dev1" 76 | if 'CARGO_ARGS' in os.environ: 77 | if "experimental" in os.environ['CARGO_ARGS']: 78 | version = version + "-experimental" 79 | return version 80 | 81 | 82 | print(version(version_data)) 83 | -------------------------------------------------------------------------------- /ci/publish-crates: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Copyright 2022 Cargill Incorporated 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | 16 | top_dir=$(cd $(dirname $(dirname $0)) && pwd) 17 | 18 | export VERSION=AUTO_STRICT 19 | export REPO_VERSION=$($top_dir/bin/get_version) 20 | 21 | echo "Publishing $REPO_VERSION to crates.io..." 22 | 23 | docker build -f ci/publish-transact-crates -t publish-transact-crates ci/ 24 | docker run \ 25 | --rm \ 26 | -v $(pwd):/project/transact \ 27 | -e REPO_VERSION=$REPO_VERSION \ 28 | -e CARGO_CRED=$CARGO_TOKEN \ 29 | publish-transact-crates 30 | -------------------------------------------------------------------------------- /ci/publish-transact-crates: -------------------------------------------------------------------------------- 1 | # Copyright 2019 Bitwise IO 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | # ------------------------------------------------------------------------------ 15 | 16 | # Description: 17 | # Builds an environment to publish libtransact to crates.io. 18 | # Your crates api token must be passed in as CARGO_CRED at runtime 19 | # using Docker's -e option. 20 | 21 | # docker build -f ci/publish-transact-crates -t publish-transact-crates ci/ 22 | # docker run --rm -v $(pwd):/project/transact -e CARGO_CRED=%CREDVALUE% publish-transact-crates 23 | 24 | FROM ubuntu:jammy 25 | 26 | ENV DEBIAN_FRONTEND=noninteractive 27 | 28 | SHELL ["/bin/bash", "-o", "pipefail", "-c"] 29 | 30 | RUN apt-get update && \ 31 | apt-get install -y -q --no-install-recommends \ 32 | build-essential \ 33 | ca-certificates \ 34 | curl \ 35 | libpq-dev \ 36 | libsqlite3-dev \ 37 | libssl-dev \ 38 | libzmq3-dev \ 39 | pkg-config \ 40 | protobuf-compiler \ 41 | sqlite3 \ 42 | unzip \ 43 | && apt-get clean \ 44 | && rm -rf /var/lib/apt/lists/* 45 | 46 | # Install Rust 47 | RUN curl https://sh.rustup.rs -sSf > /usr/bin/rustup-init \ 48 | && chmod +x /usr/bin/rustup-init \ 49 | && rustup-init -y \ 50 | # Install protoc 51 | && TARGET_ARCH=$(dpkg --print-architecture) \ 52 | && if [[ $TARGET_ARCH == "arm64" ]]; then \ 53 | PROTOC_ARCH="aarch_64"; \ 54 | elif [[ $TARGET_ARCH == "amd64" ]]; then \ 55 | PROTOC_ARCH="x86_64"; \ 56 | fi \ 57 | && curl -OLsS https://github.com/google/protobuf/releases/download/v3.20.0/protoc-3.20.0-linux-$PROTOC_ARCH.zip \ 58 | && unzip -o protoc-3.20.0-linux-$PROTOC_ARCH.zip -d /usr/local \ 59 | && rm protoc-3.20.0-linux-$PROTOC_ARCH.zip \ 60 | # Install just 61 | && curl --proto '=https' --tlsv1.2 -sSf https://just.systems/install.sh | bash -s -- --to /usr/local/bin 62 | 63 | ENV PATH=$PATH:/root/.cargo/bin 64 | 65 | WORKDIR /project/transact/libtransact 66 | 67 | CMD echo "Publishing version $REPO_VERSION" \ 68 | && cargo login $CARGO_CRED \ 69 | && sed -i -e "0,/version.*$/ s/version.*$/version\ =\ \"$REPO_VERSION\"/" Cargo.toml \ 70 | && rm -f Cargo.lock \ 71 | && cargo clean \ 72 | && cargo test \ 73 | && cargo publish 74 | -------------------------------------------------------------------------------- /cli/Cargo.toml: -------------------------------------------------------------------------------- 1 | # Copyright 2018-2019 Bitwise IO, Inc. 2 | # Copyright 2019-2021 Cargill Incorporated 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | 16 | [package] 17 | name = "transact-cli" 18 | version = "0.5.1" 19 | authors = ["Cargill Incorporated"] 20 | edition = "2018" 21 | license = "Apache-2.0" 22 | readme = "../README.md" 23 | description = """\ 24 | Transact is a transaction execution platform designed to be used as \ 25 | a library or component when implementing distributed ledgers, including \ 26 | blockchains. 27 | """ 28 | repository = "http://github.com/hyperledger/transact" 29 | 30 | [[bin]] 31 | name = "transact" 32 | path = "src/main.rs" 33 | 34 | [dependencies] 35 | clap = "2" 36 | ctrlc = { version = "3.0", optional = true } 37 | cylinder = { version = "0.2.2", features = ["jwt", "key-load"], optional = true } 38 | flexi_logger = { version = "0.20", features = ["use_chrono_for_offset"] } 39 | hex = { version = "0.4", optional = true } 40 | log = "0.4" 41 | protobuf = { version = "2.23", optional = true } 42 | rand = { version = "0.8", optional = true } 43 | reqwest = { version = "0.11", features = ["blocking"], optional = true} 44 | serde = { version = "1.0", features = ["derive"], optional = true } 45 | serde_json = { version = "1.0", optional = true} 46 | transact = {path = "../libtransact", features=["family-smallbank-workload", "family-command-workload"]} 47 | 48 | 49 | [features] 50 | default = [ 51 | "command", 52 | "workload", 53 | ] 54 | 55 | stable = [ 56 | # The stable feature extends default: 57 | "default", 58 | ] 59 | 60 | experimental = [ 61 | # The experimental feature extends stable: 62 | "stable", 63 | # The following features are experimental: 64 | "playlist-smallbank", 65 | "workload-smallbank" 66 | ] 67 | 68 | command = ["cylinder", "hex", "protobuf", "reqwest", "serde", "serde_json"] 69 | playlist-smallbank = ["cylinder", "serde_json", "transact/family-smallbank-workload", "transact/workload-batch-gen"] 70 | workload = ["ctrlc", "cylinder", "rand", "transact/family-command-workload"] 71 | workload-smallbank = ["workload", "transact/family-smallbank-workload"] 72 | 73 | [package.metadata.deb] 74 | maintainer = "The Transact Team" 75 | depends = "$auto, man" 76 | assets = [ 77 | ["packaging/man/*.1", "/usr/share/man/man1", "644"], 78 | ["target/release/transact", "/usr/bin/transact", "755"] 79 | ] 80 | 81 | 82 | [package.metadata.docs.rs] 83 | features = [ 84 | "default", 85 | "experimental", 86 | "stable", 87 | ] 88 | -------------------------------------------------------------------------------- /cli/Dockerfile: -------------------------------------------------------------------------------- 1 | # Copyright 2019-2021 Cargill Incorporated 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | FROM ubuntu:jammy as builder 16 | 17 | ENV TRANSACT_FORCE_PANDOC=true 18 | 19 | RUN apt-get update && \ 20 | apt-get install -y \ 21 | curl \ 22 | gcc \ 23 | git \ 24 | libsqlite3-dev \ 25 | libssl-dev \ 26 | libzmq3-dev \ 27 | pandoc \ 28 | pkg-config \ 29 | protobuf-compiler \ 30 | sqlite3 \ 31 | unzip 32 | 33 | RUN curl https://sh.rustup.rs -sSf > /usr/bin/rustup-init && \ 34 | chmod +x /usr/bin/rustup-init && \ 35 | rustup-init -y 36 | 37 | ENV PATH=$PATH:/root/.cargo/bin 38 | 39 | RUN cargo install cargo-deb 40 | 41 | # Copy over dependencies and source files 42 | COPY libtransact /build/libtransact 43 | COPY README.md /build/README.md 44 | COPY cli /build/cli 45 | 46 | WORKDIR /build/cli 47 | 48 | ARG REPO_VERSION 49 | ARG CARGO_ARGS 50 | RUN sed -i -e "0,/version.*$/ s/version.*$/version\ =\ \"${REPO_VERSION}\"/" Cargo.toml 51 | RUN sed -i -e "0,/readme.*$/ s/readme.*$/readme\ =\ \"\/build\/README.md\"/" Cargo.toml 52 | RUN cargo deb --deb-version $REPO_VERSION $CARGO_ARGS 53 | 54 | RUN mv /build/cli/target/debian/transact-cli*.deb /tmp 55 | 56 | # Log the commit hash 57 | COPY .git/ /tmp/.git/ 58 | WORKDIR /tmp 59 | RUN git rev-parse HEAD > /commit-hash 60 | 61 | # -------------=== transact-cli docker build ===------------- 62 | 63 | FROM ubuntu:jammy 64 | 65 | ARG CARGO_ARGS 66 | RUN echo "CARGO_ARGS = '$CARGO_ARGS'" > CARGO_ARGS 67 | 68 | COPY --from=builder /tmp/transact-cli*.deb /tmp/ 69 | COPY --from=builder /commit-hash /commit-hash 70 | 71 | RUN apt-get update \ 72 | && dpkg --unpack /tmp/transact-cli*.deb \ 73 | && apt-get -f -y install 74 | -------------------------------------------------------------------------------- /cli/man/TEMPLATE.1.md.example: -------------------------------------------------------------------------------- 1 | % COMMAND(1) Cargill, Incorporated | Transact Commands 2 | 7 | 8 | 14 | NAME 15 | ==== 16 | 17 | **command-subcommand** — About blurb from command help 18 | 19 | SYNOPSIS 20 | ======== 21 | | **command** \[**FLAGS**\] \[**OPTIONS**\] 22 | 23 | DESCRIPTION 24 | =========== 25 | Paragraph or two that describes what the command does, explains how it fits in 26 | the Transact environment, provides big-picture information on who uses it and 27 | why (or when), and lists prerequisites or other considerations. 28 | 29 | FLAGS 30 | ===== 31 | 36 | 37 | `-h`, `--help` 38 | : Prints help information 39 | 40 | `-V`, `--version` 41 | : Prints version information 42 | 43 | `-v` 44 | : Increases verbosity (the opposite of -q). Specify multiple times for more 45 | output. 46 | 47 | OPTIONS 48 | ======= 49 | 54 | 55 | `-e`, `--example EXAMPLE` 56 | : Description about example options 57 | 58 | 59 | EXAMPLES 60 | ======== 61 | 65 | 66 | ENVIRONMENT 67 | =========== 68 | The following environment variables affect the execution of the command. 69 | 70 | 74 | 75 | **EXAMPLE_ENV_VAR** 76 | 77 | : Description of environment variable. (See `--example`) 78 | 79 | SEE ALSO 80 | ======== 81 | 84 | | `related-command(1)` 85 | | 86 | | Transact documentation: https://docs.rs/transact/latest 87 | -------------------------------------------------------------------------------- /cli/man/transact-command-get-state.1.md: -------------------------------------------------------------------------------- 1 | % TRANSACT-COMMAND-GET-STATE(1) Cargill, Incorporated | Transact Commands 2 | 7 | 8 | NAME 9 | ==== 10 | 11 | **transact-command-get-state** — Submits a Sabre transaction to request a state 12 | read 13 | 14 | SYNOPSIS 15 | ======== 16 | | **transact command get state** \[**FLAGS**\] \[**OPTIONS**\] 17 | 18 | DESCRIPTION 19 | =========== 20 | This command submits a Sabre transaction to request a state read of the 21 | addresses given. Nothing will be displayed after running this command. This 22 | command submits a state read request but does not return the data that is set 23 | for the given address. 24 | 25 | This command assumes the distributed ledger's REST API supports Cylinder 26 | JWT authentication. 27 | 28 | FLAGS 29 | ===== 30 | `-h`, `--help` 31 | : Prints help information 32 | 33 | `-q`, `--quiet` 34 | : Decrease verbosity (the opposite of -v). When specified, only errors or 35 | warnings will be output. 36 | 37 | `-V`, `--version` 38 | : Prints version information 39 | 40 | `-v` 41 | : Increases verbosity (the opposite of -q). Specify multiple times for more 42 | output. 43 | 44 | OPTIONS 45 | ======= 46 | `-k, --key PRIVATE-KEY-FILE` 47 | : Specifies the full path to the private key file. The key will be used to 48 | sign the batches as well as generate a JWT for authentication. 49 | 50 | `--target TARGET` 51 | : Node URL to submit batches to. The URL should include all of the information 52 | required to append `/batches` to the end. 53 | 54 | `--address ADDRESS` 55 | : State address of the state to be read. This option can be used multiple times 56 | to specify more than one address to be read. 57 | 58 | 59 | EXAMPLES 60 | ======== 61 | The following shows submitting a get state transaction to a Splinter circuit 62 | `vpENT-eSfFZ` with scabbard services. A scabbard service runs a Sabre 63 | transaction handler. The command smart contract must already be uploaded to 64 | scabbard. 65 | 66 | ``` 67 | transact command get-state \ 68 | --key /alice.priv \ 69 | --target "http://0.0.0.0:8080/scabbard/vpENT-eSfFZ/gsAA" \ 70 | --address \ 71 | 06abbcb16ed7d24b3ecbd4164dcdad374e08c0ab7518aa07f9d3683f34c2b3c67a1583 72 | ``` 73 | 74 | The following shows submitting two get state transactions to a Splinter circuit 75 | `kpHVT-sjpQM` with scabbard services. A scabbard service runs a Sabre 76 | transaction handler. The command smart contract must already be uploaded to 77 | scabbard. 78 | 79 | ``` 80 | transact command get-state \ 81 | --key /alice.priv \ 82 | --target "http://0.0.0.0:8080/scabbard/kpHVT-sjpQM/gsAA" \ 83 | --address \ 84 | 06abbcb16ed7d24b3ecbd4164dcdad374e08c0ab7518aa07f9d3683f34c2b3c67a1583 \ 85 | --address \ 86 | 06abbc6d201beeefb589b08ef0672dac82353d0cbd9ad99e1642c83a1601f3d647bcca 87 | ``` 88 | 89 | 90 | SEE ALSO 91 | ======== 92 | | `transact(1)` 93 | | `transact-command(1)` 94 | | `transact-command-set-state(1)` 95 | | `transact-command-show-state(1)` 96 | | 97 | | Transact documentation: https://docs.rs/transact/latest 98 | -------------------------------------------------------------------------------- /cli/man/transact-command-set-state.1.md: -------------------------------------------------------------------------------- 1 | % TRANSACT-COMMAND-SET-STATE(1) Cargill, Incorporated | Transact Commands 2 | 7 | 8 | NAME 9 | ==== 10 | 11 | **transact-command-set-state** — Submits a Sabre transaction to request a state 12 | write 13 | 14 | SYNOPSIS 15 | ======== 16 | | **transact command set state** \[**FLAGS**\] \[**OPTIONS**\] 17 | 18 | DESCRIPTION 19 | =========== 20 | This command submits a Sabre transaction to request one or more state write of 21 | the state entries given. The state entry is a key value pair where the key is a 22 | state address and the value is the value to be set for the given address. 23 | 24 | This command assumes the distributed ledger's REST API supports Cylinder 25 | JWT authentication. 26 | 27 | FLAGS 28 | ===== 29 | `-h`, `--help` 30 | : Prints help information 31 | 32 | `-q`, `--quiet` 33 | : Decrease verbosity (the opposite of -v). When specified, only errors or 34 | warnings will be output. 35 | 36 | `-V`, `--version` 37 | : Prints version information 38 | 39 | `-v` 40 | : Increases verbosity (the opposite of -q). Specify multiple times for more 41 | output. 42 | 43 | OPTIONS 44 | ======= 45 | `-k, --key PRIVATE-KEY-FILE` 46 | : Specifies the full path to the private key file. The key will be used to 47 | sign the batches as well as generate a JWT for authentication. 48 | 49 | `--target TARGET` 50 | : Node URL to submit batches to. The URL should include all of the information 51 | required to append `/batches` to the end. 52 | 53 | `--state-entry STATE-ENTRY` 54 | : Key-value pair where the key is a state address and the value is the value to 55 | be set for that address. (format: address:value) 56 | 57 | 58 | EXAMPLES 59 | ======== 60 | The following shows submitting a set state transaction to a Splinter circuit 61 | `vpENT-eSfFZ` with scabbard services. A scabbard service runs a Sabre 62 | transaction handler. The command smart contract must already be uploaded to 63 | scabbard. 64 | 65 | ``` 66 | transact command set-state \ 67 | --key /alice.priv 68 | --target "http://0.0.0.0:8080/scabbard/vpENT-eSfFZ/gsAA" 69 | --state-entry \ 70 | 06abbcb16ed7d24b3ecbd4164dcdad374e08c0ab7518aa07f9d3683f34c2b3c67a1583:value 71 | ``` 72 | 73 | The following shows submitting two set state transactions to a Splinter circuit 74 | `kpHVT-sjpQM` with scabbard services. A scabbard service runs a Sabre 75 | transaction handler. The command smart contract must already be uploaded to 76 | scabbard. 77 | 78 | ``` 79 | transact command set-state \ 80 | --key /alice.priv \ 81 | --target "http://0.0.0.0:8080/scabbard/kpHVT-sjpQM/gsAA" \ 82 | --state-entry \ 83 | 06abbcb16ed7d24b3ecbd4164dcdad374e08c0ab7518aa07f9d3683f34c2b3c67a1583:value1 \ 84 | --state-entry \ 85 | 06abbc6d201beeefb589b08ef0672dac82353d0cbd9ad99e1642c83a1601f3d647bcca:value2 86 | ``` 87 | 88 | 89 | SEE ALSO 90 | ======== 91 | | `transact(1)` 92 | | `transact-command(1)` 93 | | `transact-command-get-state(1)` 94 | | `transact-command-show-state(1)` 95 | | 96 | | Transact documentation: https://docs.rs/transact/latest 97 | -------------------------------------------------------------------------------- /cli/man/transact-command-show-state.1.md: -------------------------------------------------------------------------------- 1 | % TRANSACT-COMMAND-SHOW-STATE(1) Cargill, Incorporated | Transact Commands 2 | 7 | 8 | NAME 9 | ==== 10 | 11 | **transact-command-show-state** — Displays the state value at a given address 12 | 13 | SYNOPSIS 14 | ======== 15 | | **transact command show state** \[**FLAGS**\] \[**OPTIONS**\] 16 | 17 | DESCRIPTION 18 | =========== 19 | Display the state value at the given state address if it exists. 20 | 21 | This command assumes the distributed ledger's REST API supports Cylinder 22 | JWT authentication. 23 | 24 | FLAGS 25 | ===== 26 | `-h`, `--help` 27 | : Prints help information 28 | 29 | `-q`, `--quiet` 30 | : Decrease verbosity (the opposite of -v). When specified, only errors or 31 | warnings will be output. 32 | 33 | `-t`, `--text` 34 | : Attempt to convert the state value from bytes and display it as an ascii 35 | string. 36 | 37 | `-V`, `--version` 38 | : Prints version information 39 | 40 | `-v` 41 | : Increases verbosity (the opposite of -q). Specify multiple times for more 42 | output. 43 | 44 | OPTIONS 45 | ======= 46 | `-k, --key PRIVATE-KEY-FILE` 47 | : Specifies the full path to the private key file. The key will be used to 48 | sign the batches as well as generate a JWT for authentication. 49 | 50 | `--target TARGET` 51 | : Node URL to retrieve the state value from. 52 | 53 | `--address ADDRESS` 54 | : State address of the state value to be retrieved. 55 | 56 | 57 | EXAMPLES 58 | ======== 59 | The following shows retrieving the state value at the address 60 | `06abbcb16ed7d24b3ecbd4164dcdad374e08c0ab7518aa07f9d3683f34c2b3c67a1583` 61 | from a Splinter circuit `vpENT-eSfFZ` with scabbard services. The command smart 62 | contract must already be uploaded to scabbard. 63 | 64 | ``` 65 | transact command show-state \ 66 | --key /alice.priv \ 67 | --target "http://0.0.0.0:8080/scabbard/vpENT-eSfFZ/gsAA" \ 68 | --address \ 69 | 06abbcb16ed7d24b3ecbd4164dcdad374e08c0ab7518aa07f9d3683f34c2b3c67a1583 70 | ``` 71 | 72 | 73 | SEE ALSO 74 | ======== 75 | | `transact(1)` 76 | | `transact-command(1)` 77 | | `transact-command-set-state(1)` 78 | | `transact-command-get-state(1)` 79 | | 80 | | Transact documentation: https://docs.rs/transact/latest 81 | -------------------------------------------------------------------------------- /cli/man/transact-command.1.md: -------------------------------------------------------------------------------- 1 | % TRANSACT-COMMAND(1) Cargill, Incorporated | Transact Commands 2 | 7 | 8 | **transact-command** — Interacts with the command family smart contract 9 | 10 | SYNOPSIS 11 | ======== 12 | **transact command** \[**FLAGS**\] \[**SUBCOMMAND**\] 13 | 14 | DESCRIPTION 15 | =========== 16 | This command can be used to interact with a command family smart contract on a 17 | Splinter circuit with scabbard services. 18 | 19 | FLAGS 20 | ===== 21 | `-h`, `--help` 22 | : Prints help information 23 | 24 | `-q`, `--quiet` 25 | : Decrease verbosity (the opposite of -v). When specified, only errors or 26 | warnings will be output. 27 | 28 | `-V`, `--version` 29 | : Prints version information 30 | 31 | `-v` 32 | : Increases verbosity (the opposite of -q). Specify multiple times for more 33 | output. 34 | 35 | SUBCOMMANDS 36 | =========== 37 | `get-state` 38 | : Submits a Sabre transaction to request a state read of the addresses given. 39 | 40 | `help` 41 | : Prints this message or the help of the given subcommand(s) 42 | 43 | `set-state` 44 | : Submits a Sabre transaction to request one or more state write of the state 45 | entries given. The state entry is a key value pair where the key is a state 46 | address and the value is the value to be set for the given address. 47 | 48 | `show-state` 49 | : Display the state value at the given state address if it exists. 50 | 51 | SEE ALSO 52 | ======== 53 | | `transact(1)` 54 | | `transact-command-get-state(1)` 55 | | `transact-command-set-state(1)` 56 | | `transact-command-show-state(1)` 57 | | 58 | | Transact documentation: https://docs.rs/transact/latest 59 | -------------------------------------------------------------------------------- /cli/man/transact-playlist-batch.1.md: -------------------------------------------------------------------------------- 1 | % TRANSACT-PLAYLIST-BATCH(1) Cargill, Incorporated | Transact Commands 2 | 7 | 8 | NAME 9 | ==== 10 | 11 | **transact-playlist-batch** — Generates signed batches from transaction input 12 | 13 | SYNOPSIS 14 | ======== 15 | **transact playlist batch** \[**FLAGS**\] \[**SUBCOMMAND**\] 16 | 17 | DESCRIPTION 18 | =========== 19 | This command generates signed batches from transaction input. The transaction 20 | input is expected to be length-delimited protobuf transaction messages, which 21 | should also be pre-signed for submission to the validator. 22 | 23 | FLAGS 24 | ===== 25 | `-h`, `--help` 26 | : Prints help information 27 | 28 | `-q`, `--quiet` 29 | : Decrease verbosity (the opposite of -v). When specified, only errors or 30 | warnings will be output. 31 | 32 | `-V`, `--version` 33 | : Prints version information 34 | 35 | `-v` 36 | : Increases verbosity (the opposite of -q). Specify multiple times for more 37 | output. 38 | 39 | OPTIONS 40 | ======= 41 | `-i, --input FILE` 42 | : The source of input transactions. The transaction input is expected to be 43 | length-delimited protobuf. 44 | 45 | `-k, --key PRIVATE-KEY-FILE` 46 | : Specifies the full path to the private key file. The key will be used to 47 | sign the batches. 48 | 49 | `-n, --max-batch-size NUMBER` 50 | : The maximum number of transactions to include in a batch. (Defaults to 1) 51 | 52 | `-o, --output FILE` 53 | : The target for the signed batches. 54 | 55 | 56 | EXAMPLES 57 | ======== 58 | The following shows providing a transaction file `txns.txt` and creating 59 | `batches.txt` file of length-delimited protobuf batches. 60 | 61 | ``` 62 | transact playlist batch \ 63 | --input txns.dat \ 64 | --key ./alice.priv \ 65 | --output batches.dat 66 | ``` 67 | 68 | 69 | SEE ALSO 70 | ======== 71 | | `transact(1)` 72 | | `transact-playlist(1)` 73 | | `transact-playlist-create(1)` 74 | | `transact-playlist-process(1)` 75 | | `transact-playlist-submit(1)` 76 | | 77 | | Transact documentation: https://docs.rs/transact/latest 78 | -------------------------------------------------------------------------------- /cli/man/transact-playlist-create.1.md: -------------------------------------------------------------------------------- 1 | % TRANSACT-PLAYLIST-CREATE(1) Cargill, Incorporated | Transact Commands 2 | 7 | 8 | NAME 9 | ==== 10 | 11 | **transact-playlist-create** — Generates a workload transaction playlist 12 | 13 | SYNOPSIS 14 | ======== 15 | **transact playlist create ** \[**FLAGS**\] \[**SUBCOMMAND**\] 16 | 17 | DESCRIPTION 18 | =========== 19 | This command generates a workload transaction playlist. A playlist is a series 20 | of transactions, described in YAML. This command generates a playlist and 21 | writes it to file or standard out. 22 | 23 | `transact-playlist-process` takes this playlist and creates signed transactions 24 | for the payloads. 25 | 26 | FLAGS 27 | ===== 28 | `-h`, `--help` 29 | : Prints help information 30 | 31 | `-q`, `--quiet` 32 | : Decrease verbosity (the opposite of -v). When specified, only errors or 33 | warnings will be output. 34 | 35 | `-V`, `--version` 36 | : Prints version information 37 | 38 | `-v` 39 | : Increases verbosity (the opposite of -q). Specify multiple times for more 40 | output. 41 | 42 | OPTIONS 43 | ======= 44 | `-o, --output FILE` 45 | : The target for the generated playlist 46 | 47 | `--smallbank-num-accounts ACCOUNTS` 48 | : The number of smallbank accounts to make. (Defaults to 10) 49 | 50 | `--smallbank-seed SEED` 51 | : An integer to use as a seed generate the same smallbank playlist 52 | 53 | `-n, --transactions NUMBER` 54 | : The number of transactions to generate. This includes the account creation 55 | payloads. (Defaults to 10) 56 | 57 | 58 | `--workload WORKLOAD` 59 | : The workload type to create a playlist for. [possible values: smallbank] 60 | 61 | 62 | EXAMPLES 63 | ======== 64 | The following shows creating a smallbank playlist file `smallbank.yaml` with 20 65 | transactions. 66 | 67 | ``` 68 | transact playlist create \ 69 | --smallbank-num-accounts 10 \ 70 | --output smallbank.yaml \ 71 | --smallbank-seed 10 \ 72 | --transactions 20 \ 73 | --workload smallbank 74 | ``` 75 | 76 | 77 | SEE ALSO 78 | ======== 79 | | `transact(1)` 80 | | `transact-playlist(1)` 81 | | `transact-playlist-batch(1)` 82 | | `transact-playlist-process(1)` 83 | | `transact-playlist-submit(1)` 84 | | 85 | | Transact documentation: https://docs.rs/transact/latest 86 | -------------------------------------------------------------------------------- /cli/man/transact-playlist-process.1.md: -------------------------------------------------------------------------------- 1 | % TRANSACT-PLAYLIST-PROCESS(1) Cargill, Incorporated | Transact Commands 2 | 7 | 8 | NAME 9 | ==== 10 | 11 | **transact-playlist-processe** — Processes a transaction playlist 12 | 13 | SYNOPSIS 14 | ======== 15 | **transact playlist create ** \[**FLAGS**\] \[**SUBCOMMAND**\] 16 | 17 | DESCRIPTION 18 | =========== 19 | Processes a transaction playlist. A playlist is a series of transactions, 20 | described in YAML. This command processes a playlist, converting it into 21 | transactions and writes it to file or standard out. 22 | 23 | `transact-playlist-batch` takes the output file and creates signed batches 24 | for the payloads. 25 | 26 | FLAGS 27 | ===== 28 | `-h`, `--help` 29 | : Prints help information 30 | 31 | `-q`, `--quiet` 32 | : Decrease verbosity (the opposite of -v). When specified, only errors or 33 | warnings will be output. 34 | 35 | `-V`, `--version` 36 | : Prints version information 37 | 38 | `-v` 39 | : Increases verbosity (the opposite of -q). Specify multiple times for more 40 | output. 41 | 42 | OPTIONS 43 | ======= 44 | `-i, --input FILE` 45 | : The source of the input playlist yaml. 46 | 47 | `--k, --key FILE` 48 | : The signing key for the transactions. 49 | 50 | `-o, --output FILE` 51 | : The target for the generated transactions. 52 | 53 | `--workload WORKLOAD` 54 | : The workload type to the playlist is for. [possible values: smallbank] 55 | 56 | 57 | EXAMPLES 58 | ======== 59 | The following shows creating a file, `txns.text` 60 | 61 | ``` 62 | transact playlist process \ 63 | -i smallbank.yaml \ 64 | --key ./alice.priv \ 65 | --output txns.dat \ 66 | --workload smallbank 67 | ``` 68 | 69 | 70 | SEE ALSO 71 | ======== 72 | | `transact(1)` 73 | | `transact-playlist(1)` 74 | | `transact-playlist-create(1)` 75 | | `transact-playlist-batch(1)` 76 | | `transact-playlist-submit(1)` 77 | | 78 | | Transact documentation: https://docs.rs/transact/latest 79 | -------------------------------------------------------------------------------- /cli/man/transact-playlist-submit.1.md: -------------------------------------------------------------------------------- 1 | % TRANSACT-PLAYLIST-SUBMIT(1) Cargill, Incorporated | Transact Commands 2 | 7 | 8 | NAME 9 | ==== 10 | 11 | **transact-paylist-submit** — Submits signed batches to targets from batch input 12 | 13 | SYNOPSIS 14 | ======== 15 | **transact playlist submit** \[**FLAGS**\] \[**SUBCOMMAND**\] 16 | 17 | DESCRIPTION 18 | =========== 19 | This command submits signed batches to one or more targets from batch input. 20 | The batch input is expected to be length-delimited protobuf Batch messages, 21 | which should also be pre-signed for submission to the distributed ledger. 22 | The command will continue to submit the batches at the provided rate until 23 | the source is exhausted. 24 | 25 | The submit tool assumes the distributed ledger's REST API supports Cylinder 26 | JWT authentication. 27 | 28 | FLAGS 29 | ===== 30 | `-h`, `--help` 31 | : Prints help information 32 | 33 | `-q`, `--quiet` 34 | : Decrease verbosity (the opposite of -v). When specified, only errors or 35 | warnings will be output. 36 | 37 | `-V`, `--version` 38 | : Prints version information 39 | 40 | `-v` 41 | : Increases verbosity (the opposite of -q). Specify multiple times for more 42 | output. 43 | 44 | OPTIONS 45 | ======= 46 | `-i, --input FILE` 47 | : The source of batch transactions 48 | 49 | `-k, --key PRIVATE-KEY-FILE` 50 | : Specifies the full path to the private key file. The key will be used to 51 | sign the batches as well as generate a JWT for authentication. 52 | 53 | `--rate RATE` 54 | : Rate of batch submissions, either provide a float, or a rate in form /. ex `5/s`. (default: `1/s`) 55 | 56 | `--targets TARGETS` 57 | : Node URLS to submit batches to, combine groups with `;`. The URL should 58 | include all of the information required to append `/batches` to the end. 59 | 60 | `-u, --update UPDATE ` 61 | : The time in seconds between updates. The command will log the success rate 62 | of submitting the HTTP requests. (default: `30`) 63 | 64 | EXAMPLES 65 | ======== 66 | The following shows submitting a batch source against a Splinter circuit 67 | `jEWSK-jdjSM` with scabbard services. A Scabbard service runs a sabre 68 | transaction handler. The smallbank smart contract must already be submitted to 69 | scabbard. 70 | 71 | ``` 72 | transact playlist submit \ 73 | --input batches.dat \ 74 | --key ./alice.priv \ 75 | --rate 1/s \ 76 | --target "http://0.0.0.0:8089/scabbard/XOHZe-GE1oY/a001" 77 | ``` 78 | 79 | 80 | SEE ALSO 81 | ======== 82 | | `transact(1)` 83 | | `transact-playlist(1)` 84 | | `transact-playlist-batch(1)` 85 | | `transact-playlist-create(1)` 86 | | `transact-playlist-process(1)` 87 | | 88 | | Transact documentation: https://docs.rs/transact/latest 89 | -------------------------------------------------------------------------------- /cli/man/transact-playlist.1.md: -------------------------------------------------------------------------------- 1 | % TRANSACT-PLAYLIST(1) Cargill, Incorporated | Transact Commands 2 | 7 | 8 | **transact-playlist** — Create and process playlists of pregenerated payloads 9 | 10 | SYNOPSIS 11 | ======== 12 | **transact playlist** \[**FLAGS**\] \[**SUBCOMMAND**\] 13 | 14 | DESCRIPTION 15 | =========== 16 | This command can be used to generate files of pregenerated payloads, 17 | transactions, and batches. The file containing the batches can then be submitted 18 | against a distributed ledger. 19 | 20 | Payload, transactions and batch generation can be very expensive and can skew 21 | performance results during testing. Using a pregenerated batch file makes for a 22 | more accurate and repeatable test. 23 | 24 | FLAGS 25 | ===== 26 | `-h`, `--help` 27 | : Prints help information 28 | 29 | `-q`, `--quiet` 30 | : Decrease verbosity (the opposite of -v). When specified, only errors or 31 | warnings will be output. 32 | 33 | `-V`, `--version` 34 | : Prints version information 35 | 36 | `-v` 37 | : Increases verbosity (the opposite of -q). Specify multiple times for more 38 | output. 39 | 40 | SUBCOMMANDS 41 | =========== 42 | `batch` 43 | : Generates signed batches from transaction input. The transaction input is 44 | expected to be length-delimited protobuf Transaction messages, which should 45 | also be pre-signed for submission to the validator. 46 | 47 | `create` 48 | : Generates a workload transaction playlist. A playlist is a series of 49 | transactions, described in YAML. This command generates a playlist and writes 50 | it to file or standard out. 51 | 52 | `help` 53 | : Prints this message or the help of the given subcommand(s) 54 | 55 | `process` 56 | : Processes a transaction playlist. A playlist is a series of transactions, 57 | described in YAML. This command processes a playlist, converting it into 58 | transactions and writes it to file or standard out. 59 | 60 | `submit` 61 | : Submits signed batches to one or more targets from batch input. The batch 62 | input is expected to be length-delimited protobuf Batch messages, which 63 | should also be pre-signed for submission to the validator. 64 | 65 | SEE ALSO 66 | ======== 67 | | `transact(1)` 68 | | `transact-playlist-batch(1)` 69 | | `transact-playlist-create(1)` 70 | | `transact-playlist-process(1)` 71 | | `transact-playlist-submit(1)` 72 | | 73 | | Transact documentation: https://docs.rs/transact/latest 74 | -------------------------------------------------------------------------------- /cli/man/transact.1.md: -------------------------------------------------------------------------------- 1 | % Transact(1) Cargill, Incorporated | Transact Commands 2 | 7 | 8 | NAME 9 | ==== 10 | 11 | **transact** — Command-line interface for Transact 12 | 13 | SYNOPSIS 14 | ======== 15 | 16 | **transact** \[**FLAGS**\] \[**SUBCOMMAND**\] 17 | 18 | DESCRIPTION 19 | =========== 20 | 21 | The `transact` utility is the command-line interface for Transact, a 22 | transaction execution platform designed to be used as a library. This CLI 23 | provides a tool for running workloads against distributed ledgers. 24 | 25 | * Run `transact --help` to see the list of subcommands. 26 | 27 | * Run `transact *SUBCOMMAND* --help` to see information about a specific 28 | subcommand (for example, `transact workload --help`). 29 | 30 | * To view the man page for a Transact subcommand, use the "dashed form" of the 31 | name, where each space is replaced with a hyphen. For example, run 32 | `man transact-workload` to see the man page for `transact workload`. 33 | 34 | SUBCOMMANDS 35 | =========== 36 | 37 | `workload` 38 | : Provides a command to run workloads against a distributed ledger. 39 | 40 | FLAGS 41 | ===== 42 | 43 | Most `transact` subcommands accept the following common flags: 44 | 45 | `-h`, `--help` 46 | : Prints help information 47 | 48 | `-q`, `--quiet` 49 | : Do not display output 50 | 51 | `-V`, `--version` 52 | : Prints version information 53 | 54 | `-v` 55 | : Increases verbosity (the opposite of `-q`). Specify multiple times for more 56 | output. 57 | 58 | SEE ALSO 59 | ======== 60 | | `transact-workload(1)` 61 | | 62 | | Transact documentation: https://docs.rs/transact/latest 63 | -------------------------------------------------------------------------------- /cli/packaging/man/README.md: -------------------------------------------------------------------------------- 1 | This is the directory where the generated man pages for the `transact` CLI will 2 | be located. 3 | -------------------------------------------------------------------------------- /cli/src/error.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2021 Cargill Incorporated 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | use std::error::Error; 16 | use std::fmt; 17 | 18 | use clap::Error as ClapError; 19 | 20 | #[derive(Debug)] 21 | pub enum CliError { 22 | /// A subcommand requires one or more arguments, but none were provided. 23 | RequiresArgs, 24 | /// An argument is malformed and unparsable 25 | UnparseableArg(String), 26 | /// A non-existent subcommand was specified. 27 | InvalidSubcommand, 28 | /// An error was detected by `clap`. 29 | ClapError(ClapError), 30 | /// A general error encountered by a subcommand. 31 | ActionError(String), 32 | /// The environment is not in the correct state to execute the subcommand as requested. 33 | EnvironmentError(String), 34 | } 35 | 36 | impl Error for CliError {} 37 | 38 | impl fmt::Display for CliError { 39 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 40 | match self { 41 | CliError::RequiresArgs => write!( 42 | f, 43 | "The specified subcommand requires arguments, but none were provided" 44 | ), 45 | CliError::UnparseableArg(msg) => write!(f, "An argument could not be parsed: {}", msg), 46 | CliError::InvalidSubcommand => write!(f, "An invalid subcommand was specified"), 47 | CliError::ClapError(err) => f.write_str(&err.message), 48 | CliError::ActionError(msg) => write!(f, "Subcommand encountered an error: {}", msg), 49 | CliError::EnvironmentError(msg) => { 50 | write!(f, "Environment not valid for subcommand: {}", msg) 51 | } 52 | } 53 | } 54 | } 55 | 56 | impl From for CliError { 57 | fn from(err: ClapError) -> Self { 58 | Self::ClapError(err) 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /docker-compose-installed.yaml: -------------------------------------------------------------------------------- 1 | # Copyright 2019-2021 Cargill Incorporated 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | version: '3.6' 16 | 17 | services: 18 | 19 | smallbank-scar: 20 | build: 21 | context: . 22 | dockerfile: examples/sabre_smallbank/Dockerfile-scar 23 | args: 24 | - REPO_VERSION=${REPO_VERSION} 25 | image: smallbank-scar:${ISOLATION_ID} 26 | 27 | command-scar: 28 | build: 29 | context: . 30 | dockerfile: examples/sabre_command/Dockerfile-scar 31 | args: 32 | - REPO_VERSION=${REPO_VERSION} 33 | image: command-scar:${ISOLATION_ID} 34 | 35 | transact-cli: 36 | build: 37 | context: . 38 | dockerfile: cli/Dockerfile 39 | args: 40 | - CARGO_ARGS=${CARGO_ARGS} 41 | - REPO_VERSION=${REPO_VERSION} 42 | image: ${REGISTRY}${NAMESPACE}transact-cli:${ISOLATION_ID} 43 | -------------------------------------------------------------------------------- /docker/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:jammy 2 | 3 | ENV DEBIAN_FRONTEND=noninteractive 4 | 5 | SHELL ["/bin/bash", "-o", "pipefail", "-c"] 6 | 7 | RUN apt-get update && \ 8 | apt-get install -y -q --no-install-recommends \ 9 | build-essential \ 10 | ca-certificates \ 11 | curl \ 12 | unzip \ 13 | libpq-dev \ 14 | libssl-dev \ 15 | pkg-config \ 16 | libzmq3-dev \ 17 | libsqlite3-dev \ 18 | sqlite3 \ 19 | && apt-get clean \ 20 | && rm -rf /var/lib/apt/lists/* 21 | 22 | ENV PATH=$PATH:/root/.cargo/bin 23 | 24 | # Install Rust 25 | RUN curl https://sh.rustup.rs -sSf > /usr/bin/rustup-init \ 26 | && chmod +x /usr/bin/rustup-init \ 27 | && rustup-init -y \ 28 | && rustup target add wasm32-unknown-unknown \ 29 | # Install protoc 30 | && TARGET_ARCH=$(dpkg --print-architecture) \ 31 | && if [[ $TARGET_ARCH == "arm64" ]]; then \ 32 | PROTOC_ARCH="aarch_64"; \ 33 | elif [[ $TARGET_ARCH == "amd64" ]]; then \ 34 | PROTOC_ARCH="x86_64"; \ 35 | fi \ 36 | && curl -OLsS https://github.com/google/protobuf/releases/download/v3.20.0/protoc-3.20.0-linux-$PROTOC_ARCH.zip \ 37 | && unzip -o protoc-3.20.0-linux-$PROTOC_ARCH.zip -d /usr/local \ 38 | && rm protoc-3.20.0-linux-$PROTOC_ARCH.zip \ 39 | # Install just 40 | && curl --proto '=https' --tlsv1.2 -sSf https://just.systems/install.sh | bash -s -- --to /usr/local/bin 41 | 42 | ENV CARGO_INCREMENTAL=0 43 | 44 | WORKDIR /project/transact 45 | -------------------------------------------------------------------------------- /docker/compose/.env: -------------------------------------------------------------------------------- 1 | ISOLATION_ID=latest 2 | REPO_VERSION=0.5.1-dev 3 | -------------------------------------------------------------------------------- /docker/compose/copy-debs.yaml: -------------------------------------------------------------------------------- 1 | # Copyright 2019-2021 Cargill Incorporated 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | version: '3.6' 16 | 17 | services: 18 | 19 | smallbank-scar: 20 | image: smallbank-scar:${ISOLATION_ID} 21 | volumes: 22 | - ../../build/scar:/build/scar 23 | command: | 24 | bash -c " 25 | cp /tmp/*.scar /build/scar 26 | " 27 | 28 | command-scar: 29 | image: command-scar:${ISOLATION_ID} 30 | volumes: 31 | - ../../build/scar:/build/scar 32 | command: | 33 | bash -c " 34 | cp /tmp/*.scar /build/scar 35 | " 36 | 37 | transact-cli: 38 | image: transact-cli:${ISOLATION_ID} 39 | volumes: 40 | - ../../build/debs:/build/debs 41 | command: | 42 | bash -c " 43 | cp /tmp/*.deb /build/debs 44 | " 45 | -------------------------------------------------------------------------------- /docker/compose/docker-compose.yaml: -------------------------------------------------------------------------------- 1 | version: "3.6" 2 | 3 | services: 4 | transact: 5 | build: 6 | context: ../.. 7 | dockerfile: docker/Dockerfile 8 | args: 9 | - http_proxy 10 | - https_proxy 11 | - no_proxy 12 | image: transact:${ISOLATION_ID} 13 | volumes: 14 | - ../..:/project/transact 15 | environment: 16 | TEST_MODE: --verbose --release 17 | STATE_MERKLE_SQL_POSTGRES_TEST_URL: postgres://postgres:test@postgres-db:5432/transact 18 | 19 | postgres-db: 20 | image: postgres 21 | expose: 22 | - 5432 23 | environment: 24 | POSTGRES_DB: transact 25 | POSTGRES_PASSWORD: test 26 | -------------------------------------------------------------------------------- /examples/address_generator/Cargo.toml: -------------------------------------------------------------------------------- 1 | # Copyright 2019-2020 Cargill Incorporated 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | [package] 16 | name = "address-generator" 17 | version = "0.1.0" 18 | authors = ["Cargill Incorporated"] 19 | edition = "2018" 20 | 21 | [dependencies] 22 | clap = "2" 23 | 24 | [dependencies.transact] 25 | path = "../../libtransact" 26 | features = [ 27 | "contract-address-double-key-hash", 28 | "contract-address-key-hash", 29 | "contract-address-triple-key-hash", 30 | ] 31 | 32 | [features] 33 | default = [] 34 | 35 | stable = [ 36 | # The stable feature extends default: 37 | "default", 38 | # The following features are stable: 39 | ] 40 | 41 | experimental = [ 42 | # The experimental feature extends stable: 43 | "stable", 44 | # The following features are experimental: 45 | ] 46 | -------------------------------------------------------------------------------- /examples/sabre_command/Cargo.toml: -------------------------------------------------------------------------------- 1 | # Copyright 2021 Cargill Incorporated 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | [package] 16 | name = "sabre-command" 17 | version = "0.1.0" 18 | authors = ["Cargill Incorporated"] 19 | edition = "2018" 20 | 21 | [dependencies] 22 | protobuf = "2.19" 23 | sabre-sdk = "0.7.1" 24 | 25 | [dependencies.transact] 26 | path = "../../libtransact" 27 | default-features = false 28 | features = ["family-command", "sabre-compat"] 29 | 30 | 31 | [features] 32 | default = [] 33 | 34 | stable = [ 35 | # The stable feature extends default: 36 | "default", 37 | # The following features are stable: 38 | ] 39 | 40 | experimental = [ 41 | # The experimental feature extends stable: 42 | "stable", 43 | # The following features are experimental: 44 | ] 45 | -------------------------------------------------------------------------------- /examples/sabre_command/packaging/scar/manifest.yaml: -------------------------------------------------------------------------------- 1 | # Copyright 2021 Cargill Incorporated 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | name: command 16 | version: '1.0' 17 | inputs: 18 | - '06abbc' 19 | outputs: 20 | - '06abbc' 21 | -------------------------------------------------------------------------------- /examples/sabre_command/src/main.rs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 Cargill Incorporated 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * ----------------------------------------------------------------------------- 16 | */ 17 | 18 | //! A Sabre compatible Command family smart contract 19 | 20 | #[macro_use] 21 | extern crate sabre_sdk; 22 | 23 | use protobuf::Message; 24 | 25 | use sabre_sdk::ApplyError as SabreApplyError; 26 | use sabre_sdk::TpProcessRequest as SabreTpProcessRequest; 27 | use sabre_sdk::TransactionContext as SabreTransactionContext; 28 | use sabre_sdk::{execute_entrypoint, WasmPtr}; 29 | use transact::families::command::CommandTransactionHandler; 30 | use transact::handler::sabre::SabreContext; 31 | use transact::handler::{ApplyError, TransactionHandler}; 32 | use transact::protocol::transaction::Transaction; 33 | use transact::protos::transaction::TransactionHeader; 34 | 35 | fn main() {} 36 | 37 | // Sabre apply must return a bool 38 | fn apply( 39 | request: &SabreTpProcessRequest, 40 | context: &mut dyn SabreTransactionContext, 41 | ) -> Result { 42 | // convert SabreTpProcessRequest into TransactionPair 43 | let commands = request.get_payload().to_vec(); 44 | 45 | let mut header = TransactionHeader::new(); 46 | header.set_signer_public_key(request.get_header().get_signer_public_key().to_string()); 47 | 48 | let header_bytes = header.write_to_bytes().map_err(|_| { 49 | SabreApplyError::InvalidTransaction("Unable to convert header to bytes".to_string()) 50 | })?; 51 | 52 | let txn = Transaction::new(header_bytes, request.get_signature(), commands); 53 | 54 | let txn_pair = txn 55 | .into_pair() 56 | .map_err(|err| SabreApplyError::InvalidTransaction(err.to_string()))?; 57 | 58 | // wrap SabreTransactionContext into SabreContext that can be passed to a transact 59 | // TransactionHandler 60 | let mut context = SabreContext { context }; 61 | 62 | let handler = CommandTransactionHandler::new(); 63 | 64 | match handler.apply(&txn_pair, &mut context) { 65 | Ok(_) => Ok(true), 66 | Err(err) => { 67 | info!("{}", err); 68 | 69 | match err { 70 | ApplyError::InvalidTransaction(msg) => { 71 | Err(SabreApplyError::InvalidTransaction(msg)) 72 | } 73 | ApplyError::InternalError(msg) => Err(SabreApplyError::InternalError(msg)), 74 | } 75 | } 76 | } 77 | } 78 | 79 | /// # Safety 80 | /// 81 | /// This function is required to be able to execute the wasm smart contract 82 | #[no_mangle] 83 | pub unsafe fn entrypoint(payload: WasmPtr, signer: WasmPtr, signature: WasmPtr) -> i32 { 84 | execute_entrypoint(payload, signer, signature, apply) 85 | } 86 | -------------------------------------------------------------------------------- /examples/sabre_command_executor/Cargo.toml: -------------------------------------------------------------------------------- 1 | # Copyright 2021 Cargill Incorporated 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | [package] 16 | name = "sabre-command-executor" 17 | version = "0.1.0" 18 | authors = ["Cargill Incorporated"] 19 | edition = "2018" 20 | 21 | [[bin]] 22 | name = "sabre-command-executor" 23 | path = "src/main.rs" 24 | 25 | [dependencies] 26 | clap = "2" 27 | cylinder = "0.2" 28 | flexi_logger = { version = "0.20", features = ["use_chrono_for_offset"] } 29 | log = "0.4" 30 | protobuf = { version = "2.19" } 31 | sawtooth-sabre = "0.7" 32 | transact = { path = "../../libtransact", features=["execution", "family-command-workload", "sawtooth-compat", "workload", "protocol-sabre"]} 33 | 34 | 35 | [features] 36 | default = [] 37 | 38 | stable = [ 39 | # The stable feature extends default: 40 | "default", 41 | # The following features are stable: 42 | ] 43 | 44 | experimental = [ 45 | # The experimental feature extends stable: 46 | "stable", 47 | # The following features are experimental: 48 | ] 49 | -------------------------------------------------------------------------------- /examples/sabre_command_executor/src/error.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2021 Cargill Incorporated 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License 14 | 15 | use std::error::Error; 16 | use std::fmt; 17 | 18 | use clap::Error as ClapError; 19 | 20 | #[derive(Debug)] 21 | pub enum SabreCommandExecutorError { 22 | /// An error was detected by `clap`. 23 | ClapError(ClapError), 24 | /// An operation could not be completed because the state of the underlying struct is inconsistent. 25 | InvalidState(String), 26 | /// An argument passed to a function did not conform to the expected format. 27 | InvalidArgument(String), 28 | /// A failure occurred within the function due to an internal implementation detail of the function. 29 | Internal(String), 30 | } 31 | 32 | impl Error for SabreCommandExecutorError {} 33 | 34 | impl fmt::Display for SabreCommandExecutorError { 35 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 36 | match self { 37 | SabreCommandExecutorError::ClapError(err) => f.write_str(&err.message), 38 | SabreCommandExecutorError::InvalidState(msg) => write!(f, "Invalid state: {}", msg), 39 | SabreCommandExecutorError::InvalidArgument(msg) => { 40 | write!(f, "Invalid argument: {}", msg) 41 | } 42 | SabreCommandExecutorError::Internal(msg) => write!(f, "Internal error: {}", msg), 43 | } 44 | } 45 | } 46 | 47 | impl From for SabreCommandExecutorError { 48 | fn from(err: ClapError) -> Self { 49 | Self::ClapError(err) 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /examples/sabre_smallbank/Cargo.toml: -------------------------------------------------------------------------------- 1 | # Copyright 2021 Cargill Incorporated 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | [package] 16 | name = "sabre-smallbank" 17 | version = "0.1.0" 18 | authors = ["Cargill Incorporated"] 19 | edition = "2018" 20 | 21 | [dependencies] 22 | protobuf = "2.19" 23 | sabre-sdk = "0.7.1" 24 | 25 | [dependencies.transact] 26 | path = "../../libtransact" 27 | default-features = false 28 | features = ["family-smallbank", "sabre-compat"] 29 | 30 | 31 | [features] 32 | default = [] 33 | 34 | stable = [ 35 | # The stable feature extends default: 36 | "default", 37 | # The following features are stable: 38 | ] 39 | 40 | experimental = [ 41 | # The experimental feature extends stable: 42 | "stable", 43 | # The following features are experimental: 44 | ] 45 | -------------------------------------------------------------------------------- /examples/sabre_smallbank/packaging/scar/manifest.yaml: -------------------------------------------------------------------------------- 1 | # Copyright 2021 Cargill Incorporated 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | name: smallbank 16 | version: '1.0' 17 | inputs: 18 | - '332514' 19 | outputs: 20 | - '332514' 21 | -------------------------------------------------------------------------------- /examples/sabre_smallbank/src/main.rs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 Cargill Incorporated 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * ----------------------------------------------------------------------------- 16 | */ 17 | 18 | //! A Sabre compatible Smallbank smart contract 19 | 20 | #[macro_use] 21 | extern crate sabre_sdk; 22 | 23 | use protobuf::Message; 24 | 25 | use sabre_sdk::ApplyError as SabreApplyError; 26 | use sabre_sdk::TpProcessRequest as SabreTpProcessRequest; 27 | use sabre_sdk::TransactionContext as SabreTransactionContext; 28 | use sabre_sdk::{execute_entrypoint, WasmPtr}; 29 | use transact::families::smallbank::SmallbankTransactionHandler; 30 | use transact::handler::sabre::SabreContext; 31 | use transact::handler::{ApplyError, TransactionHandler}; 32 | use transact::protocol::transaction::Transaction; 33 | use transact::protos::transaction::TransactionHeader; 34 | 35 | fn main() {} 36 | 37 | // Sabre apply must return a bool 38 | fn apply( 39 | request: &SabreTpProcessRequest, 40 | context: &mut dyn SabreTransactionContext, 41 | ) -> Result { 42 | // convert SabreTpProcessRequest into TransactionPair 43 | let mut header = TransactionHeader::new(); 44 | header.set_signer_public_key(request.get_header().get_signer_public_key().to_string()); 45 | 46 | let header_bytes = header.write_to_bytes().map_err(|_| { 47 | SabreApplyError::InvalidTransaction("Unable to convert header to bytes".to_string()) 48 | })?; 49 | let txn = Transaction::new( 50 | header_bytes, 51 | request.get_signature(), 52 | request.get_payload().to_vec(), 53 | ); 54 | let txn_pair = txn 55 | .into_pair() 56 | .map_err(|err| SabreApplyError::InvalidTransaction(err.to_string()))?; 57 | 58 | // wrap SabreTransactionContext into SabreContext that can be passed to a transact 59 | // TransactionHandler 60 | let mut context = SabreContext { context }; 61 | let handler = SmallbankTransactionHandler::new(); 62 | match handler.apply(&txn_pair, &mut context) { 63 | Ok(_) => Ok(true), 64 | Err(err) => { 65 | info!("{}", err); 66 | 67 | match err { 68 | ApplyError::InvalidTransaction(msg) => { 69 | Err(SabreApplyError::InvalidTransaction(msg)) 70 | } 71 | ApplyError::InternalError(msg) => Err(SabreApplyError::InternalError(msg)), 72 | } 73 | } 74 | } 75 | } 76 | 77 | /// # Safety 78 | /// 79 | /// This function is required to be able to execute the wasm smart contract 80 | #[no_mangle] 81 | pub unsafe fn entrypoint(payload: WasmPtr, signer: WasmPtr, signature: WasmPtr) -> i32 { 82 | execute_entrypoint(payload, signer, signature, apply) 83 | } 84 | -------------------------------------------------------------------------------- /examples/simple_xo/Cargo.toml: -------------------------------------------------------------------------------- 1 | # Copyright 2019 IBM Corp. 2 | # Copyright 2020 Cargill Incorporated 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | 16 | [package] 17 | name = "simple-xo" 18 | version = "0.1.0" 19 | authors = ["IBM Corp.", "Cargill Incorporated"] 20 | edition = "2018" 21 | 22 | [dependencies] 23 | cylinder = "0.2" 24 | transact = { path = "../../libtransact", features = ["sawtooth-compat"] } 25 | sawtooth-xo = "0.5" 26 | hex = "0.4" 27 | sha2 = "0.9" 28 | 29 | [features] 30 | default = [] 31 | 32 | stable = [ 33 | # The stable feature extends default: 34 | "default", 35 | # The following features are stable: 36 | ] 37 | 38 | experimental = [ 39 | # The experimental feature extends stable: 40 | "stable", 41 | # The following features are experimental: 42 | ] 43 | -------------------------------------------------------------------------------- /libtransact/build.rs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 Bitwise IO, Inc. 3 | * Copyright 2020 Cargill Incorporated 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * ----------------------------------------------------------------------------- 17 | */ 18 | 19 | extern crate protoc_rust; 20 | 21 | use protoc_rust::Customize; 22 | 23 | use std::env; 24 | use std::fs; 25 | use std::fs::File; 26 | use std::io::Write; 27 | use std::path::Path; 28 | 29 | fn main() { 30 | let out_dir = env::var("OUT_DIR").unwrap(); 31 | let dest_path = Path::new(&out_dir).join("protos"); 32 | let proto_path = Path::new("./protos"); 33 | fs::create_dir_all(&dest_path).unwrap(); 34 | 35 | // Run protoc 36 | protoc_rust::Codegen::new() 37 | .out_dir(&dest_path.to_str().unwrap()) 38 | .inputs(&[ 39 | proto_path.join("batch.proto").to_str().unwrap(), 40 | proto_path.join("transaction.proto").to_str().unwrap(), 41 | proto_path.join("events.proto").to_str().unwrap(), 42 | proto_path 43 | .join("transaction_receipt.proto") 44 | .to_str() 45 | .unwrap(), 46 | proto_path.join("merkle.proto").to_str().unwrap(), 47 | proto_path.join("command.proto").to_str().unwrap(), 48 | proto_path 49 | .join("sabre_contract_registry.proto") 50 | .to_str() 51 | .unwrap(), 52 | proto_path.join("sabre_contract.proto").to_str().unwrap(), 53 | proto_path 54 | .join("sabre_namespace_registry.proto") 55 | .to_str() 56 | .unwrap(), 57 | proto_path.join("sabre_payload.proto").to_str().unwrap(), 58 | proto_path.join("smallbank.proto").to_str().unwrap(), 59 | #[cfg(feature = "key-value-state")] 60 | proto_path.join("key_value_state.proto").to_str().unwrap(), 61 | ]) 62 | .includes(&[proto_path.to_str().unwrap()]) 63 | .customize(Customize::default()) 64 | .run() 65 | .expect("Protoc Error"); 66 | 67 | // Create mod.rs accordingly 68 | let mut mod_file = File::create(dest_path.join("mod.rs")).unwrap(); 69 | mod_file 70 | .write_all( 71 | b"pub mod batch;\npub mod events;\n \ 72 | #[cfg(feature = \"key-value-state\")]\npub mod key_value_state;\n \ 73 | pub mod transaction;\npub mod transaction_receipt;\npub mod merkle;\n \ 74 | pub mod command;\npub mod sabre_contract;\npub mod sabre_contract_registry;\n \n 75 | \npub mod sabre_namespace_registry;\npub mod sabre_payload;pub mod smallbank;\n", 76 | ) 77 | .unwrap(); 78 | } 79 | -------------------------------------------------------------------------------- /libtransact/protos/batch.proto: -------------------------------------------------------------------------------- 1 | // Copyright 2016 Intel Corporation 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // ----------------------------------------------------------------------------- 15 | 16 | syntax = "proto3"; 17 | 18 | import "transaction.proto"; 19 | 20 | message BatchHeader { 21 | // Public key for the client that signed the BatchHeader 22 | string signer_public_key = 1; 23 | 24 | // List of transaction.header_signatures that match the order of 25 | // transactions required for the batch 26 | repeated string transaction_ids = 2; 27 | } 28 | 29 | message Batch { 30 | // The serialized version of the BatchHeader 31 | bytes header = 1; 32 | 33 | // The signature derived from signing the header 34 | string header_signature = 2; 35 | 36 | // A list of the transactions that match the list of 37 | // transaction_ids listed in the batch header 38 | repeated Transaction transactions = 3; 39 | 40 | // A debugging flag which indicates this batch should be traced through the 41 | // system, resulting in a higher level of debugging output. 42 | bool trace = 4; 43 | } 44 | 45 | message BatchList { 46 | repeated Batch batches = 1; 47 | } 48 | -------------------------------------------------------------------------------- /libtransact/protos/events.proto: -------------------------------------------------------------------------------- 1 | // Copyright 2017 Intel Corporation 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // ----------------------------------------------------------------------------- 15 | 16 | syntax = "proto3"; 17 | 18 | message Event { 19 | // Used to subscribe to events and servers as a hint for how to deserialize 20 | // event_data and what pairs to expect in attributes. 21 | string event_type = 1; 22 | 23 | // Transparent data defined by the event_type. 24 | message Attribute { 25 | string key = 1; 26 | string value = 2; 27 | } 28 | repeated Attribute attributes = 2; 29 | 30 | // Opaque data defined by the event_type. 31 | bytes data = 3; 32 | } 33 | 34 | message EventList { 35 | repeated Event events = 1; 36 | } 37 | 38 | message EventFilter { 39 | // EventFilter is used when subscribing to events to limit the events 40 | // received within a given event type. See 41 | // validator/server/events/subscription.py for further explanation. 42 | string key = 1; 43 | string match_string = 2; 44 | 45 | enum FilterType { 46 | FILTER_TYPE_UNSET = 0; 47 | SIMPLE_ANY = 1; 48 | SIMPLE_ALL = 2; 49 | REGEX_ANY = 3; 50 | REGEX_ALL = 4; 51 | } 52 | FilterType filter_type = 3; 53 | } 54 | 55 | message EventSubscription { 56 | // EventSubscription is used when subscribing to events to specify the type 57 | // of events being subscribed to, along with any additional filters. See 58 | // validator/server/events/subscription.py for further explanation. 59 | string event_type = 1; 60 | repeated EventFilter filters = 2; 61 | } 62 | -------------------------------------------------------------------------------- /libtransact/protos/key_value_state.proto: -------------------------------------------------------------------------------- 1 | // Copyright 2019 Cargill Incorporated 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // ----------------------------------------------------------------------------- 15 | 16 | syntax = "proto3"; 17 | 18 | message StateEntryValue { 19 | enum ValueType { 20 | TYPE_UNSET = 0; 21 | INT64 = 1; 22 | INT32 = 2; 23 | UINT64 = 3; 24 | UINT32 = 4; 25 | STRING = 5; 26 | BYTES = 6; 27 | } 28 | string key = 1; 29 | 30 | ValueType value_type = 2; 31 | 32 | int32 int32_value = 3; 33 | int64 int64_value = 4; 34 | uint32 uint32_value = 5; 35 | uint64 uint64_value = 6; 36 | string string_value = 7; 37 | bytes bytes_value = 8; 38 | } 39 | 40 | 41 | message StateEntry { 42 | string normalized_key = 1; 43 | repeated StateEntryValue state_entry_values = 2; 44 | } 45 | 46 | message StateEntryList { 47 | repeated StateEntry entries = 1; 48 | } 49 | -------------------------------------------------------------------------------- /libtransact/protos/merkle.proto: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Intel Corporation 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // ----------------------------------------------------------------------------- 15 | syntax = "proto3"; 16 | 17 | 18 | // An Entry in the change log for a given state root. 19 | message ChangeLogEntry { 20 | // A state root that succeed this root. 21 | message Successor { 22 | // A root hash of a merkle trie based of off this root. 23 | bytes successor = 1; 24 | 25 | // The keys (i.e. hashes) that were replaced (i.e. deleted) by this 26 | // successor. These may be deleted during pruning. 27 | repeated bytes deletions = 2; 28 | } 29 | 30 | // A root hash of a merkle trie this tree was based off. 31 | bytes parent = 1; 32 | 33 | // The hashes that were added for this root. These may be deleted during 34 | // pruning, if this root is being abandoned. 35 | repeated bytes additions = 2; 36 | 37 | // The list of successors. 38 | repeated Successor successors = 3; 39 | } 40 | -------------------------------------------------------------------------------- /libtransact/protos/sabre_contract.proto: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Cargill Incorporated 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | syntax = "proto3"; 16 | 17 | // A contract is stored using its name and version, with the following 18 | // address: 19 | // 20 | // 00ec02 + hash(name + "," + version) 21 | // 22 | // The stored contents are a serialized ContractList message to handle 23 | // hash collisions. 24 | // 25 | // To retrieve the latest contract with a given name, first look up the 26 | // contract in the contract registry and sort to determine the latest. 27 | 28 | message Contract { 29 | string name = 1; 30 | string version = 2; 31 | repeated string inputs = 3; 32 | repeated string outputs = 4; 33 | string creator = 5; 34 | bytes contract = 6; 35 | } 36 | 37 | message ContractList { 38 | repeated Contract contracts = 1; 39 | } 40 | -------------------------------------------------------------------------------- /libtransact/protos/sabre_contract_registry.proto: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Cargill Incorporated 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | syntax = "proto3"; 16 | 17 | // A contract registry is stored using the name of the contract, with the 18 | // following address: 19 | // 20 | // 00ec01 + hash(name) 21 | // 22 | // The stored contents are a serialized ContractRegistryList message to handle 23 | // hash collisions. 24 | 25 | message ContractRegistry { 26 | message Version { 27 | string version = 1; 28 | 29 | // used to verify a contract is same as the one the client intended to 30 | // invoke 31 | string contract_sha512 = 2; 32 | 33 | // for client information purposes only - the key that created this 34 | // contract on the chain 35 | string creator = 3; 36 | } 37 | 38 | string name = 1; 39 | repeated Version versions = 2; 40 | repeated string owners = 3; 41 | } 42 | 43 | message ContractRegistryList { 44 | repeated ContractRegistry registries = 1; 45 | } 46 | -------------------------------------------------------------------------------- /libtransact/protos/sabre_namespace_registry.proto: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Cargill Incorporated 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | syntax = "proto3"; 16 | 17 | // A namespace registry is stored using the namespace, prefixed with zero 18 | // padding: 19 | // 20 | // 00ec00 + hash(substr(namespace, 6)) 21 | // 22 | // The stored contents are a serialized NamespaceRegistryList message to handle 23 | // hash collisions. 24 | // 25 | // Creating a namespace registry requires being in the setting for 26 | // 'sawtooth.swa.administrators' (a list of public keys). 27 | // 28 | // Once created, only an owner or a member of the sawtooth.swa.administrators 29 | // can modify the registry entry. 30 | 31 | message NamespaceRegistry { 32 | message Permission { 33 | string contract_name = 1; 34 | bool read = 2; 35 | bool write = 3; 36 | } 37 | 38 | string namespace = 1; 39 | repeated string owners = 2; 40 | 41 | repeated Permission permissions = 3; 42 | } 43 | 44 | message NamespaceRegistryList { 45 | repeated NamespaceRegistry registries = 1; 46 | } 47 | -------------------------------------------------------------------------------- /libtransact/protos/transaction.proto: -------------------------------------------------------------------------------- 1 | // Copyright 2016 Intel Corporation 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // ----------------------------------------------------------------------------- 15 | 16 | syntax = "proto3"; 17 | 18 | message TransactionHeader { 19 | // Public key for the client who added this transaction to a batch 20 | string batcher_public_key = 1; 21 | 22 | // A list of transaction signatures that describe the transactions that 23 | // must be processed before this transaction can be valid 24 | repeated string dependencies = 2; 25 | 26 | // The family name correlates to the transaction processor's family name 27 | // that this transaction can be processed on, for example 'intkey' 28 | string family_name = 3; 29 | 30 | // The family version correlates to the transaction processor's family 31 | // version that this transaction can be processed on, for example "1.0" 32 | string family_version = 4; 33 | 34 | // A list of addresses that are given to the context manager and control 35 | // what addresses the transaction processor is allowed to read from. 36 | repeated string inputs = 5; 37 | 38 | // A random string that provides uniqueness for transactions with 39 | // otherwise identical fields. 40 | string nonce = 6; 41 | 42 | // A list of addresses that are given to the context manager and control 43 | // what addresses the transaction processor is allowed to write to. 44 | repeated string outputs = 7; 45 | 46 | //The sha512 hash of the encoded payload 47 | string payload_sha512 = 9; 48 | 49 | // Public key for the client that signed the TransactionHeader 50 | string signer_public_key = 10; 51 | } 52 | 53 | message Transaction { 54 | // The serialized version of the TransactionHeader 55 | bytes header = 1; 56 | 57 | // The signature derived from signing the header 58 | string header_signature = 2; 59 | 60 | // The payload is the encoded family specific information of the 61 | // transaction. Example cbor({'Verb': verb, 'Name': name,'Value': value}) 62 | bytes payload = 3; 63 | } 64 | 65 | // A simple list of transactions that needs to be serialized before 66 | // it can be transmitted to a batcher. 67 | message TransactionList { 68 | repeated Transaction transactions = 1; 69 | } 70 | -------------------------------------------------------------------------------- /libtransact/protos/transaction_receipt.proto: -------------------------------------------------------------------------------- 1 | // Copyright 2017 Intel Corporation 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | // ----------------------------------------------------------------------------- 15 | 16 | syntax = "proto3"; 17 | 18 | import "events.proto"; 19 | 20 | message TransactionReceipt { 21 | enum Result { 22 | RESULT_UNSET = 0; 23 | VALID = 1; 24 | INVALID = 2; 25 | } 26 | 27 | // FIELDS FOR ALL RECEIPTS 28 | 29 | string transaction_id = 4; 30 | Result result = 5; 31 | 32 | // FIELDS FOR VALID RECEIPTS 33 | 34 | // State changes made by this transaction 35 | // StateChange is defined in protos/transaction_receipt.proto 36 | repeated StateChange state_changes = 1; 37 | // Events fired by this transaction 38 | // Event is defined in protos/events.proto 39 | repeated Event events = 2; 40 | // Transaction family defined data 41 | repeated bytes data = 3; 42 | 43 | // FIELDS FOR INVALID RECEIPTS 44 | 45 | // Human-readable reason for why the transaction was invalid 46 | string error_message = 6; 47 | // Transaction-specific error data that can be interpreted by clients familiar 48 | // with the transaction family 49 | bytes error_data = 7; 50 | } 51 | 52 | // StateChange objects have the type of SET, which is either an insert or 53 | // update, or DELETE. Items marked as a DELETE will have no byte value. 54 | message StateChange { 55 | enum Type { 56 | TYPE_UNSET = 0; 57 | SET = 1; 58 | DELETE = 2; 59 | } 60 | string address = 1; 61 | bytes value = 2; 62 | Type type = 3; 63 | } 64 | 65 | // A collection of state changes. 66 | message StateChangeList { 67 | repeated StateChange state_changes = 1; 68 | } 69 | -------------------------------------------------------------------------------- /libtransact/src/collections/mod.rs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018-2021 Cargill Incorporated 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * ----------------------------------------------------------------------------- 16 | */ 17 | 18 | mod ref_map; 19 | 20 | pub use ref_map::RefMap; 21 | -------------------------------------------------------------------------------- /libtransact/src/context/error.rs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Bitwise IO, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * ----------------------------------------------------------------------------- 16 | */ 17 | use std::error::Error; 18 | 19 | use crate::protocol::receipt::TransactionReceiptBuilderError; 20 | use crate::state::error::StateReadError; 21 | 22 | #[derive(Debug)] 23 | pub enum ContextManagerError { 24 | MissingContextError(String), 25 | TransactionReceiptBuilderError(TransactionReceiptBuilderError), 26 | StateReadError(StateReadError), 27 | } 28 | 29 | impl Error for ContextManagerError { 30 | fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { 31 | match *self { 32 | ContextManagerError::MissingContextError(_) => Some(self), 33 | ContextManagerError::TransactionReceiptBuilderError(ref err) => Some(err), 34 | ContextManagerError::StateReadError(ref err) => Some(err), 35 | } 36 | } 37 | } 38 | 39 | impl std::fmt::Display for ContextManagerError { 40 | fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { 41 | match *self { 42 | ContextManagerError::MissingContextError(ref s) => { 43 | write!(f, "Unable to find specified Context: {:?}", s) 44 | } 45 | ContextManagerError::TransactionReceiptBuilderError(ref err) => { 46 | write!(f, "A TransactionReceiptBuilder error occured: {}", err) 47 | } 48 | ContextManagerError::StateReadError(ref err) => { 49 | write!(f, "A State Read error occured: {}", err) 50 | } 51 | } 52 | } 53 | } 54 | 55 | impl From for ContextManagerError { 56 | fn from(err: TransactionReceiptBuilderError) -> Self { 57 | ContextManagerError::TransactionReceiptBuilderError(err) 58 | } 59 | } 60 | 61 | impl From for ContextManagerError { 62 | fn from(err: StateReadError) -> Self { 63 | ContextManagerError::StateReadError(err) 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /libtransact/src/contract/address/error.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 Cargill Incorporated 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #[derive(Debug)] 16 | pub struct AddresserError { 17 | pub message: String, 18 | } 19 | 20 | impl std::fmt::Display for AddresserError { 21 | fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { 22 | let AddresserError { message } = self; 23 | write!(f, "Addresser Error occurred: {}", message) 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /libtransact/src/contract/address/key_hash.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 Cargill Incorporated 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | use crate::contract::address::{hash, Addresser, AddresserError, ADDRESS_LENGTH}; 16 | 17 | pub struct KeyHashAddresser { 18 | prefix: String, 19 | } 20 | 21 | impl KeyHashAddresser { 22 | pub fn new(prefix: String) -> KeyHashAddresser { 23 | KeyHashAddresser { prefix } 24 | } 25 | } 26 | 27 | impl Addresser for KeyHashAddresser { 28 | fn compute(&self, key: &String) -> Result { 29 | let hash_length = ADDRESS_LENGTH - self.prefix.len(); 30 | 31 | Ok(String::from(&self.prefix) + &hash(hash_length, key)) 32 | } 33 | 34 | fn normalize(&self, key: &String) -> String { 35 | key.to_string() 36 | } 37 | } 38 | 39 | #[cfg(test)] 40 | mod tests { 41 | use super::*; 42 | 43 | #[test] 44 | /// The KeyHashAddresser is constructed by providing a 6 character `prefix.` The KeyHashAddresser 45 | /// represents keys as single strings. The `compute` method must combine the `prefix` and the 46 | /// provided natural key to create a valid radix address. This radix address is valid if: 47 | /// 48 | /// 1. The address is equal to the ADDRESS_LENGTH const 49 | /// 2. The prefix is present in the beginning of the address 50 | /// 3. The remaining characters match the same amount of characters from the hash of the provided 51 | /// natural key. 52 | /// 53 | /// This test also ensures that the instantiated KeyHashAddresser can transform the natural key 54 | /// into a single string, using the `normalize` method. 55 | fn test_key_hash_addresser() { 56 | // Instantiate a KeyHashAddresser, using a simple 6 character prefix 57 | let addresser = KeyHashAddresser::new("prefix".to_string()); 58 | // Calculate an address using `a` as the natural key 59 | let addr = addresser.compute(&"a".to_string()).unwrap(); 60 | 61 | // Verify the beginning characters match the provided prefix and the address length. 62 | assert_eq!(addr[..6], "prefix".to_string()); 63 | assert_eq!(addr.len(), ADDRESS_LENGTH); 64 | 65 | // Verify the remaining section of the calculated address matches the direct hash of the key. 66 | let key_hash = hash(64, "a"); 67 | let remaining = ADDRESS_LENGTH - 6; 68 | assert_eq!(addr[6..ADDRESS_LENGTH], key_hash[..remaining]); 69 | 70 | // Verify the instantiated KeyHashAddresser outputs the correctly normalized key. 71 | let normalized = addresser.normalize(&"b".to_string()); 72 | assert_eq!(normalized, "b".to_string()); 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /libtransact/src/contract/address/mod.rs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Cargill Incorporated 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * ----------------------------------------------------------------------------- 16 | */ 17 | 18 | #[cfg(feature = "contract-address-double-key-hash")] 19 | pub mod double_key_hash; 20 | mod error; 21 | #[cfg(feature = "contract-address-key-hash")] 22 | pub mod key_hash; 23 | #[cfg(feature = "contract-address-triple-key-hash")] 24 | pub mod triple_key_hash; 25 | 26 | pub use crate::contract::address::error::AddresserError; 27 | 28 | use sha2::{Digest, Sha512}; 29 | 30 | pub const ADDRESS_LENGTH: usize = 70; 31 | 32 | pub trait Addresser { 33 | /// Returns a radix address calculated from the given key 34 | /// 35 | /// # Arguments 36 | /// 37 | /// * `key` - A natural key, as defined by K, used to calculate an address 38 | /// 39 | fn compute(&self, key: &K) -> Result; 40 | 41 | /// Returns a human readable string of the given key 42 | /// 43 | /// # Arguments 44 | /// 45 | /// * `key` - A natural key, as defined by K 46 | /// 47 | fn normalize(&self, key: &K) -> String; 48 | } 49 | 50 | pub fn hash(hash_length: usize, key: &str) -> String { 51 | let mut sha = Sha512::new(); 52 | sha.update(key.as_bytes()); 53 | hex::encode(sha.finalize())[..hash_length].to_string() 54 | } 55 | -------------------------------------------------------------------------------- /libtransact/src/contract/archive/error.rs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Cargill Incorporated 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * ----------------------------------------------------------------------------- 16 | */ 17 | 18 | use glob::PatternError; 19 | use semver::Error as SemverError; 20 | 21 | #[derive(Debug)] 22 | pub struct Error { 23 | context: String, 24 | source: Option>, 25 | } 26 | 27 | impl Error { 28 | pub fn new(context: &str) -> Self { 29 | Self { 30 | context: context.into(), 31 | source: None, 32 | } 33 | } 34 | 35 | pub fn new_with_source(context: &str, err: Box) -> Self { 36 | Self { 37 | context: context.into(), 38 | source: Some(err), 39 | } 40 | } 41 | } 42 | 43 | impl std::error::Error for Error {} 44 | 45 | impl std::fmt::Display for Error { 46 | fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { 47 | if let Some(ref err) = self.source { 48 | write!(f, "{}: {}", self.context, err) 49 | } else { 50 | f.write_str(&self.context) 51 | } 52 | } 53 | } 54 | 55 | impl From for Error { 56 | fn from(err: PatternError) -> Self { 57 | Self::new_with_source("invalid file pattern", err.into()) 58 | } 59 | } 60 | 61 | impl From for Error { 62 | fn from(err: SemverError) -> Self { 63 | Self::new_with_source("invalid version", err.into()) 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /libtransact/src/contract/context/error.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 Cargill Incorporated 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | use std::error::Error as StdError; 16 | 17 | use crate::contract::address::AddresserError; 18 | use crate::handler::ContextError; 19 | use crate::protos::ProtoConversionError; 20 | 21 | #[derive(Debug)] 22 | pub enum ContractContextError { 23 | AddresserError(AddresserError), 24 | ProtoConversionError(ProtoConversionError), 25 | ProtocolBuildError(Box), 26 | TransactionContextError(ContextError), 27 | } 28 | 29 | impl StdError for ContractContextError { 30 | fn source(&self) -> Option<&(dyn StdError + 'static)> { 31 | match *self { 32 | ContractContextError::AddresserError(_) => None, 33 | ContractContextError::ProtoConversionError(ref err) => Some(err), 34 | ContractContextError::ProtocolBuildError(ref err) => Some(&**err), 35 | ContractContextError::TransactionContextError(ref err) => Some(err), 36 | } 37 | } 38 | } 39 | 40 | impl std::fmt::Display for ContractContextError { 41 | fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { 42 | match *self { 43 | ContractContextError::AddresserError(ref err) => { 44 | write!(f, "Error occurred while computing an address: {}", err) 45 | } 46 | ContractContextError::ProtoConversionError(ref err) => { 47 | write!(f, "Error occurred during protobuf conversion: {}", err) 48 | } 49 | ContractContextError::ProtocolBuildError(ref err) => write!( 50 | f, 51 | "Error occurred while building native protocol type: {}", 52 | err 53 | ), 54 | ContractContextError::TransactionContextError(ref err) => { 55 | write!(f, "Error occurred in TransactionContext method: {}", err) 56 | } 57 | } 58 | } 59 | } 60 | 61 | impl From for ContractContextError { 62 | fn from(e: ProtoConversionError) -> Self { 63 | ContractContextError::ProtoConversionError(e) 64 | } 65 | } 66 | 67 | impl From for ContractContextError { 68 | fn from(e: AddresserError) -> Self { 69 | ContractContextError::AddresserError(e) 70 | } 71 | } 72 | 73 | impl From for ContractContextError { 74 | fn from(e: ContextError) -> Self { 75 | ContractContextError::TransactionContextError(e) 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /libtransact/src/contract/context/mod.rs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Cargill Incorporated 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * ----------------------------------------------------------------------------- 16 | */ 17 | 18 | pub mod error; 19 | #[cfg(feature = "contract-context-key-value")] 20 | pub mod key_value; 21 | -------------------------------------------------------------------------------- /libtransact/src/contract/mod.rs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Cargill Incorporated 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * ----------------------------------------------------------------------------- 16 | */ 17 | 18 | #[cfg(feature = "contract-address")] 19 | pub mod address; 20 | #[cfg(feature = "contract-archive")] 21 | pub mod archive; 22 | #[cfg(feature = "contract-context")] 23 | pub mod context; 24 | -------------------------------------------------------------------------------- /libtransact/src/database/error.rs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 Intel Corporation 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * ------------------------------------------------------------------------------ 16 | */ 17 | 18 | //! A common set of errors that can occur on database operations. 19 | 20 | #[derive(Debug)] 21 | pub enum DatabaseError { 22 | InitError(String), 23 | ReaderError(String), 24 | WriterError(String), 25 | CorruptionError(String), 26 | NotFoundError(String), 27 | DuplicateEntry, 28 | } 29 | 30 | impl std::fmt::Display for DatabaseError { 31 | fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { 32 | match *self { 33 | DatabaseError::InitError(ref msg) => write!(f, "InitError: {}", msg), 34 | DatabaseError::ReaderError(ref msg) => write!(f, "ReaderError: {}", msg), 35 | DatabaseError::WriterError(ref msg) => write!(f, "WriterError: {}", msg), 36 | DatabaseError::CorruptionError(ref msg) => write!(f, "CorruptionError: {}", msg), 37 | DatabaseError::NotFoundError(ref msg) => write!(f, "NotFoundError: {}", msg), 38 | DatabaseError::DuplicateEntry => write!(f, "DuplicateEntry"), 39 | } 40 | } 41 | } 42 | 43 | impl std::error::Error for DatabaseError { 44 | fn description(&self) -> &str { 45 | match *self { 46 | DatabaseError::InitError(ref msg) => msg, 47 | DatabaseError::ReaderError(ref msg) => msg, 48 | DatabaseError::WriterError(ref msg) => msg, 49 | DatabaseError::CorruptionError(ref msg) => msg, 50 | DatabaseError::NotFoundError(ref msg) => msg, 51 | DatabaseError::DuplicateEntry => "DuplicateEntry", 52 | } 53 | } 54 | 55 | fn cause(&self) -> Option<&dyn std::error::Error> { 56 | match *self { 57 | DatabaseError::InitError(_) => None, 58 | DatabaseError::ReaderError(_) => None, 59 | DatabaseError::WriterError(_) => None, 60 | DatabaseError::CorruptionError(_) => None, 61 | DatabaseError::NotFoundError(_) => None, 62 | DatabaseError::DuplicateEntry => None, 63 | } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /libtransact/src/error/invalid_state.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2021 Cargill Incorporated 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | //! Module containing InvalidStateError implementation. 16 | 17 | use std::error; 18 | use std::fmt; 19 | 20 | /// An error returned when an operation cannot be completed because the state of the underlying 21 | /// struct is inconsistent. 22 | /// 23 | /// This can be caused by a caller when a sequence of functions is called in a way that results in 24 | /// a state which is inconsistent. 25 | /// 26 | /// This usually indicates a programming error on behalf of the caller. 27 | #[derive(Debug)] 28 | pub struct InvalidStateError { 29 | message: String, 30 | } 31 | 32 | impl InvalidStateError { 33 | /// Constructs a new `InvalidStateError` with a specified message string. 34 | /// 35 | /// The implementation of `std::fmt::Display` for this error will be the message string 36 | /// provided. 37 | /// 38 | /// # Examples 39 | /// 40 | /// ``` 41 | /// use transact::error::InvalidStateError; 42 | /// 43 | /// let invalid_state_error = InvalidStateError::with_message("oops".to_string()); 44 | /// assert_eq!(format!("{}", invalid_state_error), "oops"); 45 | /// ``` 46 | pub fn with_message(message: String) -> Self { 47 | Self { message } 48 | } 49 | } 50 | 51 | impl error::Error for InvalidStateError {} 52 | 53 | impl fmt::Display for InvalidStateError { 54 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 55 | write!(f, "{}", &self.message) 56 | } 57 | } 58 | 59 | #[cfg(test)] 60 | pub mod tests { 61 | use super::*; 62 | 63 | /// Tests that error constructed with `InvalidStateError::with_message` return message as the 64 | /// display string. 65 | #[test] 66 | fn test_display_with_message() { 67 | let msg = "test message"; 68 | let err = InvalidStateError::with_message(msg.to_string()); 69 | assert_eq!(format!("{}", err), msg); 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /libtransact/src/error/mod.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2021 Cargill Incorporated 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | //! Common set of basic errors used throughout the library. 16 | //! 17 | //! The errors in this module are intended to be used by themselves or as part of a more complex 18 | //! error `enum`. 19 | //! 20 | //! # Examples 21 | //! 22 | //! ## Returning an Error from a Function 23 | //! 24 | //! A function may return an error such as `InternalError` by itself. 25 | //! 26 | //! ``` 27 | //! use std::fs; 28 | //! 29 | //! use transact::error::InternalError; 30 | //! 31 | //! fn check_path(path: &str) -> Result { 32 | //! let metadata = fs::metadata(path).map_err(|e| InternalError::from_source(Box::new(e)))?; 33 | //! Ok(metadata.is_file()) 34 | //! } 35 | //! ``` 36 | //! 37 | //! ## Constructing Complex Errors 38 | //! 39 | //! Errors such as `InternalError` may be used to construct more complicated errors by defining 40 | //! an `enum`. 41 | //! 42 | //! ``` 43 | //! use std::error; 44 | //! use std::fmt; 45 | //! use std::fs; 46 | //! 47 | //! use transact::error::InternalError; 48 | //! 49 | //! #[derive(Debug)] 50 | //! enum MyError { 51 | //! InternalError(InternalError), 52 | //! MissingFilenameExtension, 53 | //! } 54 | //! 55 | //! impl error::Error for MyError {} 56 | //! 57 | //! impl fmt::Display for MyError { 58 | //! fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 59 | //! match self { 60 | //! MyError::InternalError(e) => write!(f, "{}", e), 61 | //! MyError::MissingFilenameExtension => write!(f, "Missing filename extension"), 62 | //! } 63 | //! } 64 | //! } 65 | //! 66 | //! fn check_path(path: &str) -> Result { 67 | //! match !path.ends_with(".md") { 68 | //! true => Err(MyError::MissingFilenameExtension), 69 | //! false => { 70 | //! let metadata = fs::metadata(path).map_err(|e| MyError::InternalError(InternalError::from_source(Box::new(e))))?; 71 | //! Ok(metadata.is_file()) 72 | //! } 73 | //! } 74 | //! } 75 | //! ``` 76 | 77 | mod internal; 78 | mod invalid_state; 79 | 80 | pub use internal::InternalError; 81 | pub use invalid_state::InvalidStateError; 82 | -------------------------------------------------------------------------------- /libtransact/src/execution/adapter/mod.rs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 Bitwise IO, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * ----------------------------------------------------------------------------- 16 | */ 17 | 18 | //! Contains execution adapter components and interfaces that proxy the `Transaction` 19 | //! and its associated state. 20 | 21 | mod error; 22 | pub mod static_adapter; 23 | #[cfg(test)] 24 | pub mod test_adapter; 25 | 26 | pub use crate::execution::adapter::error::{ExecutionAdapterError, ExecutionOperationError}; 27 | 28 | use crate::context::ContextId; 29 | use crate::execution::ExecutionRegistry; 30 | use crate::protocol::transaction::TransactionPair; 31 | use crate::scheduler::ExecutionTaskCompletionNotification; 32 | 33 | /// Implementers of this trait proxy the transaction to the correct component to execute 34 | /// the transaction. 35 | pub trait ExecutionAdapter: Send { 36 | fn start( 37 | &mut self, 38 | execution_registry: Box, 39 | ) -> Result<(), ExecutionOperationError>; 40 | 41 | /// Execute the transaction and provide an callback that handles the result. 42 | /// 43 | /// 44 | /// The `on_done` callback is fired when the transaction returns from processing or there 45 | /// is an error. 46 | fn execute( 47 | &self, 48 | transaction_pair: TransactionPair, 49 | context_id: ContextId, 50 | on_done: Box< 51 | dyn Fn(Result) + Send, 52 | >, 53 | ) -> Result<(), ExecutionOperationError>; 54 | 55 | /// Stop the internal threads and the Executor will no longer call execute. 56 | fn stop(self: Box) -> Result<(), ExecutionOperationError>; 57 | } 58 | -------------------------------------------------------------------------------- /libtransact/src/execution/executor/error.rs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Bitwise IO, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * ----------------------------------------------------------------------------- 16 | */ 17 | 18 | #[derive(Debug)] 19 | pub enum ExecutorError { 20 | // The Executor has not been started, and so calling `execute` will return an error. 21 | NotStarted, 22 | // The Executor has had start called more than once. 23 | AlreadyStarted(String), 24 | 25 | ResourcesUnavailable(String), 26 | } 27 | 28 | impl std::error::Error for ExecutorError {} 29 | 30 | impl std::fmt::Display for ExecutorError { 31 | fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { 32 | match self { 33 | ExecutorError::NotStarted => f.write_str("Executor not started"), 34 | ExecutorError::AlreadyStarted(ref msg) => { 35 | write!(f, "Executor already started: {}", msg) 36 | } 37 | ExecutorError::ResourcesUnavailable(ref msg) => { 38 | write!(f, "Resource Unavailable: {}", msg) 39 | } 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /libtransact/src/execution/mod.rs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 Bitwise IO, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * ----------------------------------------------------------------------------- 16 | */ 17 | 18 | //! Contains components that are used to directly execute a `Transaction` 19 | //! and return a `execution::adapter::ExecutionResult`. 20 | 21 | pub mod adapter; 22 | pub mod executor; 23 | 24 | use crate::protocol::transaction::TransactionPair; 25 | 26 | /// A Transaction Family Descriptor 27 | #[derive(Eq, PartialEq, Debug, Hash, Clone)] 28 | pub struct TransactionFamily { 29 | family_name: String, 30 | family_version: String, 31 | } 32 | 33 | impl TransactionFamily { 34 | /// Constructs a new Transaction Family Descriptor. 35 | pub fn new(family_name: String, family_version: String) -> Self { 36 | TransactionFamily { 37 | family_name, 38 | family_version, 39 | } 40 | } 41 | 42 | /// Creates a Transaction Family Descriptor using the information in a TransactionPair. 43 | pub fn from_pair(transaction_pair: &TransactionPair) -> Self { 44 | Self::new( 45 | transaction_pair.header().family_name().to_string(), 46 | transaction_pair.header().family_version().to_string(), 47 | ) 48 | } 49 | 50 | pub fn family_name(&self) -> &str { 51 | &self.family_name 52 | } 53 | 54 | pub fn family_version(&self) -> &str { 55 | &self.family_version 56 | } 57 | } 58 | 59 | /// The registry of transaction families 60 | pub trait ExecutionRegistry: Send { 61 | /// Register the given transaction family. 62 | /// 63 | /// Adding a family to the registry indicates that the family can be processed by an 64 | /// ExecutionAdapter. 65 | fn register_transaction_family(&mut self, family: TransactionFamily); 66 | 67 | /// Unregister the given transaction family. 68 | /// 69 | /// Signals that a transaction family can no longer be processed by an ExecutionAdapter. 70 | fn unregister_transaction_family(&mut self, family: &TransactionFamily); 71 | } 72 | -------------------------------------------------------------------------------- /libtransact/src/families/command/mod.rs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 Cargill Incorporated 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * ------------------------------------------------------------------------------ 16 | */ 17 | 18 | mod handler; 19 | #[cfg(feature = "family-command-transaction-builder")] 20 | mod transaction_builder; 21 | #[cfg(feature = "family-command-workload")] 22 | pub mod workload; 23 | 24 | pub use self::handler::CommandTransactionHandler; 25 | #[cfg(feature = "family-command-transaction-builder")] 26 | pub use self::transaction_builder::CommandTransactionBuilder; 27 | -------------------------------------------------------------------------------- /libtransact/src/families/mod.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2021 Cargill Incorporated 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #[cfg(feature = "family-command")] 16 | pub mod command; 17 | #[cfg(feature = "family-sabre")] 18 | pub mod sabre; 19 | #[cfg(feature = "family-smallbank")] 20 | pub mod smallbank; 21 | #[cfg(feature = "family-xo")] 22 | pub mod xo; 23 | -------------------------------------------------------------------------------- /libtransact/src/families/sabre/addressing.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Cargill Incorporated 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | use sha2::{Digest, Sha512}; 16 | 17 | use crate::handler::ApplyError; 18 | 19 | /// The namespace registry prefix for global state (00ec00) 20 | const NAMESPACE_REGISTRY_PREFIX: &str = "00ec00"; 21 | 22 | /// The contract registry prefix for global state (00ec01) 23 | const CONTRACT_REGISTRY_PREFIX: &str = "00ec01"; 24 | 25 | /// The contract prefix for global state (00ec02) 26 | const CONTRACT_PREFIX: &str = "00ec02"; 27 | 28 | pub fn hash(to_hash: &str, num: usize) -> Result { 29 | let temp = Sha512::digest(to_hash) 30 | .iter() 31 | .map(|b| format!("{:02x}", b)) 32 | .collect::(); 33 | let hash = match temp.get(..num) { 34 | Some(x) => x, 35 | None => { 36 | return Err(ApplyError::InvalidTransaction(format!( 37 | "Cannot hash {} to Sha512 and return String with len {}", 38 | to_hash, num 39 | ))); 40 | } 41 | }; 42 | Ok(hash.into()) 43 | } 44 | 45 | pub fn make_contract_address(name: &str, version: &str) -> Result { 46 | Ok(CONTRACT_PREFIX.to_string() + &hash(&(name.to_string() + "," + version), 64)?) 47 | } 48 | 49 | pub fn make_contract_registry_address(name: &str) -> Result { 50 | Ok(CONTRACT_REGISTRY_PREFIX.to_string() + &hash(name, 64)?) 51 | } 52 | 53 | pub fn make_namespace_registry_address(namespace: &str) -> Result { 54 | let prefix = match namespace.get(..6) { 55 | Some(x) => x, 56 | None => { 57 | return Err(ApplyError::InvalidTransaction(format!( 58 | "Namespace must be at least 6 characters long: {}", 59 | namespace 60 | ))); 61 | } 62 | }; 63 | Ok(NAMESPACE_REGISTRY_PREFIX.to_string() + &hash(prefix, 64)?) 64 | } 65 | -------------------------------------------------------------------------------- /libtransact/src/families/sabre/admin/allow_all.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2021 Cargill Incorporated 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | //! An implementations of `AdminPermission` that always returns true 16 | 17 | use crate::families::sabre::state::SabreState; 18 | use crate::handler::ApplyError; 19 | 20 | use super::AdminPermission; 21 | 22 | #[derive(Default)] 23 | pub struct AllowAllAdminPermission; 24 | 25 | impl AdminPermission for AllowAllAdminPermission { 26 | fn is_admin(&self, _signer: &str, _state: &mut SabreState) -> Result { 27 | Ok(true) 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /libtransact/src/families/sabre/admin/mod.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2021 Cargill Incorporated 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | //! A trait used by the Sabre transaction handle for verifying if a signer is an admin 16 | //! 17 | //! Includes two implementations, `AllowAllAdminPermission` and `SettingsAdminPermission`. 18 | //! `SettingsAdminPermission` checks Sawtooth Settings for admin keys. The 19 | //! `AllowAllAdminPermission` will always return true. 20 | 21 | mod allow_all; 22 | mod settings; 23 | 24 | pub use self::allow_all::AllowAllAdminPermission; 25 | pub use self::settings::SettingsAdminPermission; 26 | 27 | use crate::families::sabre::state::SabreState; 28 | use crate::handler::ApplyError; 29 | 30 | /// Used to verify if a signer is an admin 31 | pub trait AdminPermission: Send { 32 | /// Returns if the signer is an admin 33 | /// 34 | /// # Arguments 35 | /// 36 | /// * `signer` - The public key of the transaction signer 37 | /// * `state` - `SabreState` for fetching information about admins 38 | fn is_admin(&self, signer: &str, state: &mut SabreState) -> Result; 39 | } 40 | -------------------------------------------------------------------------------- /libtransact/src/families/sabre/admin/settings.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2021 Cargill Incorporated 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | //! An implementations of `AdminPermission` that checks Sawtooth Settings and returns true if the 16 | //! signer is listed as an admin. 17 | 18 | use crate::families::sabre::state::SabreState; 19 | use crate::handler::ApplyError; 20 | use crate::protocol::sabre::ADMINISTRATORS_SETTING_KEY; 21 | 22 | use super::AdminPermission; 23 | 24 | #[derive(Default)] 25 | pub struct SettingsAdminPermission; 26 | 27 | impl AdminPermission for SettingsAdminPermission { 28 | fn is_admin(&self, signer: &str, state: &mut SabreState) -> Result { 29 | let setting = match state.get_admin_setting() { 30 | Ok(Some(setting)) => setting, 31 | Ok(None) => { 32 | return Err(ApplyError::InvalidTransaction(format!( 33 | "Admins not set, cannot check signer permissions: {}", 34 | signer, 35 | ))); 36 | } 37 | Err(err) => { 38 | return Err(ApplyError::InvalidTransaction(format!( 39 | "Unable to check state: {}", 40 | err, 41 | ))); 42 | } 43 | }; 44 | 45 | for entry in setting.get_entries() { 46 | if entry.key == ADMINISTRATORS_SETTING_KEY { 47 | let mut values = entry.value.split(','); 48 | return Ok(values.any(|x| x == signer)); 49 | } 50 | } 51 | 52 | Ok(false) 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /libtransact/src/families/sabre/mod.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 Cargill Incorporated 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | mod addressing; 16 | pub mod admin; 17 | pub mod handler; 18 | mod payload; 19 | mod state; 20 | mod wasm_executor; 21 | 22 | pub use crate::protocol::sabre::{ADMINISTRATORS_SETTING_ADDRESS, ADMINISTRATORS_SETTING_KEY}; 23 | -------------------------------------------------------------------------------- /libtransact/src/families/sabre/wasm_executor/mod.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Cargill Incorporated 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | pub mod wasm_externals; 15 | pub mod wasm_module; 16 | -------------------------------------------------------------------------------- /libtransact/src/families/sabre/wasm_executor/wasm_module.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Cargill Incorporated 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | use crate::handler::TransactionContext; 16 | use wasmi::{ImportsBuilder, Module, ModuleInstance, RuntimeValue}; 17 | 18 | use super::wasm_externals::{ExternalsError, WasmExternals}; 19 | 20 | pub struct WasmModule<'a> { 21 | context: &'a mut dyn TransactionContext, 22 | module: Module, 23 | } 24 | 25 | impl<'a> WasmModule<'a> { 26 | pub fn new( 27 | wasm: &[u8], 28 | context: &'a mut dyn TransactionContext, 29 | ) -> Result, ExternalsError> { 30 | let module = Module::from_buffer(wasm)?; 31 | Ok(WasmModule { context, module }) 32 | } 33 | 34 | pub fn entrypoint( 35 | &mut self, 36 | payload: Vec, 37 | signer: String, 38 | signature: String, 39 | ) -> Result, ExternalsError> { 40 | let mut env = WasmExternals::new(None, self.context)?; 41 | 42 | let instance = ModuleInstance::new( 43 | &self.module, 44 | &ImportsBuilder::new().with_resolver("env", &env), 45 | )? 46 | .assert_no_start(); 47 | 48 | let payload_ptr = env.write_data(payload)? as i32; 49 | info!("Payload written to memory"); 50 | 51 | let signer_ptr = env.write_data(signer.into_bytes())? as i32; 52 | info!("Signer written to memory"); 53 | 54 | let signature_ptr = env.write_data(signature.into_bytes())? as i32; 55 | info!("Signature written to memory"); 56 | 57 | let result = instance.invoke_export( 58 | "entrypoint", 59 | &[ 60 | RuntimeValue::I32(payload_ptr), 61 | RuntimeValue::I32(signer_ptr), 62 | RuntimeValue::I32(signature_ptr), 63 | ], 64 | &mut env, 65 | )?; 66 | 67 | if let Some(RuntimeValue::I32(i)) = result { 68 | Ok(Some(i)) 69 | } else { 70 | Ok(None) 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /libtransact/src/families/smallbank/mod.rs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 Cargill Incorporated 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * ------------------------------------------------------------------------------ 16 | */ 17 | 18 | mod handler; 19 | #[cfg(feature = "family-smallbank-workload")] 20 | pub mod workload; 21 | 22 | pub use self::handler::SmallbankTransactionHandler; 23 | -------------------------------------------------------------------------------- /libtransact/src/families/smallbank/workload/error.rs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017 Intel Corporation 3 | * Copyright 2021 Cargill Incorporated 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * ------------------------------------------------------------------------------ 17 | */ 18 | use std::error::Error; 19 | use std::fmt; 20 | use std::io::Error as StdIoError; 21 | 22 | use cylinder::SigningError; 23 | use yaml_rust::EmitError; 24 | 25 | #[derive(Debug)] 26 | pub enum PlaylistError { 27 | IoError(StdIoError), 28 | YamlOutputError(EmitError), 29 | YamlInputError(yaml_rust::ScanError), 30 | MessageError(protobuf::ProtobufError), 31 | SigningError(SigningError), 32 | BuildError(String), 33 | } 34 | 35 | impl fmt::Display for PlaylistError { 36 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 37 | match *self { 38 | PlaylistError::IoError(ref err) => { 39 | write!(f, "Error occurred writing messages: {}", err) 40 | } 41 | PlaylistError::YamlOutputError(_) => write!(f, "Error occurred generating YAML output"), 42 | PlaylistError::YamlInputError(_) => write!(f, "Error occurred reading YAML input"), 43 | PlaylistError::MessageError(ref err) => { 44 | write!(f, "Error occurred creating protobuf: {}", err) 45 | } 46 | PlaylistError::SigningError(ref err) => { 47 | write!(f, "Error occurred signing transactions: {}", err) 48 | } 49 | PlaylistError::BuildError(ref err) => { 50 | write!(f, "Error occurred building transactions: {}", err) 51 | } 52 | } 53 | } 54 | } 55 | 56 | impl Error for PlaylistError { 57 | fn source(&self) -> Option<&(dyn Error + 'static)> { 58 | match *self { 59 | PlaylistError::IoError(ref err) => Some(err), 60 | PlaylistError::YamlOutputError(_) => None, 61 | PlaylistError::YamlInputError(_) => None, 62 | PlaylistError::MessageError(ref err) => Some(err), 63 | PlaylistError::SigningError(ref err) => Some(err), 64 | PlaylistError::BuildError(_) => None, 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /libtransact/src/protocol/mod.rs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019-2021 Cargill Incorporated 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * ----------------------------------------------------------------------------- 16 | */ 17 | 18 | //! Transact structs for batches, transactions and receipts. 19 | //! 20 | //! These structs cover the core protocols of the Transact system. Batches of transactions are 21 | //! scheduled and executed. The resuls of execution are stored in transaction receipts. 22 | 23 | #[cfg(feature = "protocol-batch")] 24 | pub mod batch; 25 | pub mod command; 26 | #[cfg(feature = "key-value-state")] 27 | pub mod key_value_state; 28 | pub mod receipt; 29 | #[cfg(any(feature = "protocol-sabre", feature = "family-sabre"))] 30 | pub mod sabre; 31 | #[cfg(feature = "protocol-transaction")] 32 | pub mod transaction; 33 | -------------------------------------------------------------------------------- /libtransact/src/scheduler/parallel/mod.rs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Cargill Incorporated 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * ----------------------------------------------------------------------------- 16 | */ 17 | 18 | pub mod tree; 19 | -------------------------------------------------------------------------------- /libtransact/src/scheduler/serial/shared.rs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2019 Cargill Incorporated 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * ----------------------------------------------------------------------------- 16 | */ 17 | 18 | //! Internal serial scheduler state shared across threads. 19 | 20 | use crate::protocol::batch::BatchPair; 21 | use crate::scheduler::BatchExecutionResult; 22 | use crate::scheduler::SchedulerError; 23 | use crate::scheduler::{default_error_callback, default_result_callback}; 24 | 25 | use std::collections::VecDeque; 26 | 27 | /// Stores all serial scheduler data which is shared between threads. 28 | pub struct Shared { 29 | finalized: bool, 30 | result_callback: Box) + Send>, 31 | error_callback: Box, 32 | unscheduled_batches: VecDeque, 33 | } 34 | 35 | impl Default for Shared { 36 | fn default() -> Self { 37 | Self::new() 38 | } 39 | } 40 | 41 | impl Shared { 42 | pub fn new() -> Self { 43 | Shared { 44 | finalized: false, 45 | result_callback: Box::new(default_result_callback), 46 | error_callback: Box::new(default_error_callback), 47 | unscheduled_batches: VecDeque::new(), 48 | } 49 | } 50 | 51 | pub fn finalized(&self) -> bool { 52 | self.finalized 53 | } 54 | 55 | pub fn result_callback(&self) -> &(dyn Fn(Option) + Send) { 56 | &*self.result_callback 57 | } 58 | 59 | pub fn error_callback(&self) -> &(dyn Fn(SchedulerError) + Send) { 60 | &*self.error_callback 61 | } 62 | 63 | pub fn set_finalized(&mut self, finalized: bool) { 64 | self.finalized = finalized; 65 | } 66 | 67 | pub fn set_result_callback( 68 | &mut self, 69 | callback: Box) + Send>, 70 | ) { 71 | self.result_callback = callback; 72 | } 73 | 74 | pub fn set_error_callback(&mut self, callback: Box) { 75 | self.error_callback = callback; 76 | } 77 | 78 | pub fn batch_already_queued(&self, batch: &BatchPair) -> bool { 79 | self.unscheduled_batches.contains(batch) 80 | } 81 | 82 | pub fn unscheduled_batches_is_empty(&self) -> bool { 83 | self.unscheduled_batches.is_empty() 84 | } 85 | 86 | pub fn add_unscheduled_batch(&mut self, batch: BatchPair) { 87 | self.unscheduled_batches.push_back(batch); 88 | } 89 | 90 | pub fn drain_unscheduled_batches(&mut self) -> Vec { 91 | self.unscheduled_batches.drain(0..).collect() 92 | } 93 | 94 | pub fn pop_unscheduled_batch(&mut self) -> Option { 95 | self.unscheduled_batches.pop_front() 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /libtransact/src/state/committer.rs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Cargill Incorporated 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * ----------------------------------------------------------------------------- 16 | */ 17 | 18 | use super::{State, StateError}; 19 | 20 | /// Provides a way to commit changes to a particular state storage system. 21 | /// 22 | /// A `StateId`, in the context of `Committer`, is used to indicate the starting state on which the 23 | /// changes will be applied. It can be thought of as the identifier of a checkpoint or snapshot. 24 | /// 25 | /// All operations are made using `StateChange` instances. These are the ordered set of changes to 26 | /// be applied onto the given `StateId`. 27 | pub trait Committer: State { 28 | /// Defines the type of change to apply 29 | type StateChange; 30 | 31 | /// Given a `StateId` and a slice of `StateChange` values, persist the state changes and return 32 | /// the resulting next `StateId` value. 33 | /// 34 | /// This function will persist the state values to the underlying storage mechanism. 35 | /// 36 | /// # Errors 37 | /// 38 | /// [`StateError`] is returned if any issues occur while trying to commit the changes. 39 | fn commit( 40 | &self, 41 | state_id: &Self::StateId, 42 | state_changes: &[Self::StateChange], 43 | ) -> Result; 44 | } 45 | -------------------------------------------------------------------------------- /libtransact/src/state/dry_run_committer.rs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Cargill Incorporated 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * ----------------------------------------------------------------------------- 16 | */ 17 | 18 | use super::{State, StateError}; 19 | 20 | /// Predicts future state checkpoints. 21 | pub trait DryRunCommitter: State { 22 | /// Defines the type of change to use for the prediction. 23 | type StateChange; 24 | 25 | /// Given a `StateId` and a slice of `StateChange` values, compute the next `StateId` value. 26 | /// 27 | /// This function will compute the value of the next `StateId` without actually persisting the 28 | /// state changes. Effectively, it is a dry-run. 29 | /// 30 | /// Returns the next `StateId` value; 31 | /// 32 | /// # Errors 33 | /// 34 | /// [`StateError`] is returned if any issues occur while trying to generate this next id. 35 | fn dry_run_commit( 36 | &self, 37 | state_id: &Self::StateId, 38 | state_changes: &[Self::StateChange], 39 | ) -> Result; 40 | } 41 | -------------------------------------------------------------------------------- /libtransact/src/state/merkle/error.rs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 Cargill Incorporated 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * ----------------------------------------------------------------------------- 16 | */ 17 | 18 | use std::error::Error; 19 | use std::fmt; 20 | 21 | use crate::error::{InternalError, InvalidStateError}; 22 | 23 | /// Error variants that may occur while reading Merkle Radix tree leaves. 24 | #[derive(Debug)] 25 | pub enum MerkleRadixLeafReadError { 26 | /// An internal error occurred. 27 | /// 28 | /// This error may be caused by an issue outside of the control of the application, such as 29 | /// invalid storage. 30 | InternalError(InternalError), 31 | /// An invalid state error occurred. 32 | /// 33 | /// This error may occur in cases where the reader has been provided invalid state, such as a 34 | /// non-existent state root hash. 35 | InvalidStateError(InvalidStateError), 36 | } 37 | 38 | impl fmt::Display for MerkleRadixLeafReadError { 39 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 40 | match self { 41 | MerkleRadixLeafReadError::InternalError(err) => f.write_str(&err.to_string()), 42 | MerkleRadixLeafReadError::InvalidStateError(err) => f.write_str(&err.to_string()), 43 | } 44 | } 45 | } 46 | 47 | impl Error for MerkleRadixLeafReadError { 48 | fn source(&self) -> Option<&(dyn Error + 'static)> { 49 | match self { 50 | MerkleRadixLeafReadError::InternalError(ref err) => Some(err), 51 | MerkleRadixLeafReadError::InvalidStateError(ref err) => Some(err), 52 | } 53 | } 54 | } 55 | 56 | impl From for MerkleRadixLeafReadError { 57 | fn from(err: InternalError) -> Self { 58 | MerkleRadixLeafReadError::InternalError(err) 59 | } 60 | } 61 | 62 | impl From for MerkleRadixLeafReadError { 63 | fn from(err: InvalidStateError) -> Self { 64 | MerkleRadixLeafReadError::InvalidStateError(err) 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /libtransact/src/state/merkle/kv/state_trait_impls/committer.rs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Cargill Incorporated 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * ----------------------------------------------------------------------------- 16 | */ 17 | 18 | use crate::error::{InternalError, InvalidStateError}; 19 | use crate::state::{Committer, StateChange, StateError}; 20 | 21 | use crate::state::merkle::kv::{error::StateDatabaseError, MerkleRadixTree, MerkleState}; 22 | 23 | impl Committer for MerkleState { 24 | type StateChange = StateChange; 25 | 26 | fn commit( 27 | &self, 28 | state_id: &Self::StateId, 29 | state_changes: &[Self::StateChange], 30 | ) -> Result { 31 | let merkle_tree = 32 | MerkleRadixTree::new(self.db.clone(), Some(state_id)).map_err(|err| match err { 33 | StateDatabaseError::NotFound(msg) => { 34 | StateError::from(InvalidStateError::with_message(msg)) 35 | } 36 | _ => StateError::from(InternalError::from_source(Box::new(err))), 37 | })?; 38 | 39 | merkle_tree 40 | .update(state_changes, false) 41 | .map_err(|err| StateError::from(InternalError::from_source(Box::new(err)))) 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /libtransact/src/state/merkle/kv/state_trait_impls/dry_run_committer.rs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Cargill Incorporated 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * ----------------------------------------------------------------------------- 16 | */ 17 | 18 | use crate::error::{InternalError, InvalidStateError}; 19 | use crate::state::{DryRunCommitter, StateChange, StateError}; 20 | 21 | use crate::state::merkle::kv::{error::StateDatabaseError, MerkleRadixTree, MerkleState}; 22 | 23 | impl DryRunCommitter for MerkleState { 24 | type StateChange = StateChange; 25 | 26 | fn dry_run_commit( 27 | &self, 28 | state_id: &Self::StateId, 29 | state_changes: &[Self::StateChange], 30 | ) -> Result { 31 | let merkle_tree = 32 | MerkleRadixTree::new(self.db.clone(), Some(state_id)).map_err(|err| match err { 33 | StateDatabaseError::NotFound(msg) => { 34 | StateError::from(InvalidStateError::with_message(msg)) 35 | } 36 | _ => StateError::from(InternalError::from_source(Box::new(err))), 37 | })?; 38 | 39 | merkle_tree 40 | .update(state_changes, true) 41 | .map_err(|err| StateError::from(InternalError::from_source(Box::new(err)))) 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /libtransact/src/state/merkle/kv/state_trait_impls/mod.rs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Cargill Incorporated 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * ----------------------------------------------------------------------------- 16 | */ 17 | 18 | mod committer; 19 | mod dry_run_committer; 20 | mod pruner; 21 | mod reader; 22 | 23 | use super::MerkleState; 24 | 25 | impl crate::state::State for MerkleState { 26 | type StateId = String; 27 | type Key = String; 28 | type Value = Vec; 29 | } 30 | -------------------------------------------------------------------------------- /libtransact/src/state/merkle/kv/state_trait_impls/pruner.rs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Cargill Incorporated 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * ----------------------------------------------------------------------------- 16 | */ 17 | 18 | use crate::error::{InternalError, InvalidStateError}; 19 | use crate::state::{Pruner, StateError}; 20 | 21 | use crate::state::merkle::kv::{error::StateDatabaseError, MerkleRadixTree, MerkleState}; 22 | 23 | impl Pruner for MerkleState { 24 | fn prune(&self, state_ids: Vec) -> Result, StateError> { 25 | state_ids 26 | .iter() 27 | .try_fold(Vec::new(), |mut result, state_id| { 28 | result.extend(MerkleRadixTree::prune(&*self.db, state_id).map_err( 29 | |err| match err { 30 | StateDatabaseError::NotFound(msg) => { 31 | StateError::from(InvalidStateError::with_message(msg)) 32 | } 33 | _ => StateError::from(InternalError::from_source(Box::new(err))), 34 | }, 35 | )?); 36 | Ok(result) 37 | }) 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /libtransact/src/state/merkle/sql/error.rs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 Cargill Incorporated 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * ----------------------------------------------------------------------------- 16 | */ 17 | 18 | //! Errors related to SQL-backed merkle-radix state representation. 19 | 20 | use std::error::Error; 21 | use std::fmt; 22 | 23 | use crate::error::{InternalError, InvalidStateError}; 24 | 25 | /// This error may occur during the construction of a SqlMerkeState instance. 26 | #[derive(Debug)] 27 | pub enum SqlMerkleStateBuildError { 28 | InternalError(InternalError), 29 | InvalidStateError(InvalidStateError), 30 | } 31 | 32 | impl fmt::Display for SqlMerkleStateBuildError { 33 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 34 | match self { 35 | SqlMerkleStateBuildError::InternalError(e) => f.write_str(&e.to_string()), 36 | SqlMerkleStateBuildError::InvalidStateError(e) => f.write_str(&e.to_string()), 37 | } 38 | } 39 | } 40 | 41 | impl Error for SqlMerkleStateBuildError { 42 | fn source(&self) -> Option<&(dyn Error + 'static)> { 43 | match *self { 44 | SqlMerkleStateBuildError::InternalError(ref e) => Some(e), 45 | SqlMerkleStateBuildError::InvalidStateError(ref e) => Some(e), 46 | } 47 | } 48 | } 49 | 50 | impl From for SqlMerkleStateBuildError { 51 | fn from(err: InternalError) -> Self { 52 | SqlMerkleStateBuildError::InternalError(err) 53 | } 54 | } 55 | 56 | impl From for SqlMerkleStateBuildError { 57 | fn from(err: InvalidStateError) -> Self { 58 | SqlMerkleStateBuildError::InvalidStateError(err) 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /libtransact/src/state/merkle/sql/migration/mod.rs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 Cargill Incorporated 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * ----------------------------------------------------------------------------- 16 | */ 17 | 18 | //! Provides the MigrationManager trait. 19 | 20 | #[cfg(feature = "postgres")] 21 | pub(crate) mod postgres; 22 | #[cfg(feature = "sqlite")] 23 | pub(crate) mod sqlite; 24 | 25 | use crate::error::InternalError; 26 | 27 | use super::backend::Backend; 28 | 29 | #[cfg(feature = "postgres")] 30 | pub use postgres::run_migrations as run_postgres_migrations; 31 | #[cfg(feature = "sqlite")] 32 | pub use sqlite::run_migrations as run_sqlite_migrations; 33 | 34 | /// Provides backend migration execution. 35 | /// 36 | /// Backend's that implement this trait can expose a migration operation on their underlying 37 | /// database system. 38 | pub trait MigrationManager: Backend { 39 | fn run_migrations(&self) -> Result<(), InternalError>; 40 | } 41 | -------------------------------------------------------------------------------- /libtransact/src/state/merkle/sql/migration/postgres/migrations/2021-09-09-121000-initialize-tables/down.sql: -------------------------------------------------------------------------------- 1 | -- Copyright 2021 Cargill Incorporated 2 | -- 3 | -- Licensed under the Apache License, Version 2.0 (the "License"); 4 | -- you may not use this file except in compliance with the License. 5 | -- You may obtain a copy of the License at 6 | -- 7 | -- http://www.apache.org/licenses/LICENSE-2.0 8 | -- 9 | -- Unless required by applicable law or agreed to in writing, software 10 | -- distributed under the License is distributed on an "AS IS" BASIS, 11 | -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | -- See the License for the specific language governing permissions and 13 | -- limitations under the License. 14 | -- ----------------------------------------------------------------------------- 15 | 16 | DROP TABLE IF EXISTS merkle_radix_change_log_addition; 17 | DROP TABLE IF EXISTS merkle_radix_change_log_deletion; 18 | DROP TABLE IF EXISTS merkle_radix_tree_node; 19 | DROP TABLE IF EXISTS merkle_radix_leaf; 20 | DROP TABLE IF EXISTS merkle_radix_tree; 21 | -------------------------------------------------------------------------------- /libtransact/src/state/merkle/sql/migration/postgres/migrations/2021-09-09-121000-initialize-tables/up.sql: -------------------------------------------------------------------------------- 1 | -- Copyright 2021 Cargill Incorporated 2 | -- 3 | -- Licensed under the Apache License, Version 2.0 (the "License"); 4 | -- you may not use this file except in compliance with the License. 5 | -- You may obtain a copy of the License at 6 | -- 7 | -- http://www.apache.org/licenses/LICENSE-2.0 8 | -- 9 | -- Unless required by applicable law or agreed to in writing, software 10 | -- distributed under the License is distributed on an "AS IS" BASIS, 11 | -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | -- See the License for the specific language governing permissions and 13 | -- limitations under the License. 14 | -- ----------------------------------------------------------------------------- 15 | 16 | CREATE TABLE IF NOT EXISTS merkle_radix_tree ( 17 | id BIGSERIAL PRIMARY KEY, 18 | name VARCHAR(512), 19 | UNIQUE(name) 20 | ); 21 | 22 | INSERT INTO merkle_radix_tree (name) VALUES ('default'); 23 | 24 | CREATE TABLE IF NOT EXISTS merkle_radix_leaf ( 25 | id BIGSERIAL PRIMARY KEY, 26 | tree_id BIGINT NOT NULL, 27 | address VARCHAR(70) NOT NULL, 28 | data BYTEA, 29 | FOREIGN KEY(tree_id) REFERENCES merkle_radix_tree (id) 30 | ); 31 | 32 | CREATE TABLE IF NOT EXISTS merkle_radix_tree_node ( 33 | hash VARCHAR(64) NOT NULL, 34 | tree_id BIGINT NOT NULL, 35 | leaf_id BIGINT, 36 | children VARCHAR(64)[], 37 | PRIMARY KEY (hash, tree_id), 38 | FOREIGN KEY(tree_id) REFERENCES merkle_radix_tree(id), 39 | FOREIGN KEY(leaf_id) REFERENCES merkle_radix_leaf(id) 40 | ); 41 | 42 | create TABLE IF NOT EXISTS merkle_radix_change_log_addition ( 43 | id BIGSERIAL PRIMARY KEY, 44 | tree_id BIGINT NOT NULL, 45 | state_root VARCHAR(64) NOT NULL, 46 | parent_state_root VARCHAR(64), 47 | addition VARCHAR(64), 48 | FOREIGN KEY(state_root, tree_id) REFERENCES merkle_radix_tree_node(hash, tree_id), 49 | FOREIGN KEY(parent_state_root, tree_id) REFERENCES merkle_radix_tree_node(hash, tree_id), 50 | FOREIGN KEY(addition, tree_id) REFERENCES merkle_radix_tree_node(hash, tree_id) 51 | ); 52 | 53 | create TABLE IF NOT EXISTS merkle_radix_change_log_deletion ( 54 | id BIGSERIAL PRIMARY KEY, 55 | tree_id BIGINT NOT NULL, 56 | successor_state_root VARCHAR(64) NOT NULL, 57 | state_root VARCHAR(64) NOT NULL, 58 | deletion VARCHAR(64), 59 | FOREIGN KEY(successor_state_root, tree_id) REFERENCES merkle_radix_tree_node(hash, tree_id), 60 | FOREIGN KEY(state_root, tree_id) REFERENCES merkle_radix_tree_node(hash, tree_id), 61 | FOREIGN KEY(deletion, tree_id) REFERENCES merkle_radix_tree_node(hash, tree_id) 62 | ); 63 | -------------------------------------------------------------------------------- /libtransact/src/state/merkle/sql/migration/postgres/migrations/2022-03-06-add-pruned-column/down.sql: -------------------------------------------------------------------------------- 1 | -- Copyright 2021 Cargill Incorporated 2 | -- 3 | -- Licensed under the Apache License, Version 2.0 (the "License"); 4 | -- you may not use this file except in compliance with the License. 5 | -- You may obtain a copy of the License at 6 | -- 7 | -- http://www.apache.org/licenses/LICENSE-2.0 8 | -- 9 | -- Unless required by applicable law or agreed to in writing, software 10 | -- distributed under the License is distributed on an "AS IS" BASIS, 11 | -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | -- See the License for the specific language governing permissions and 13 | -- limitations under the License. 14 | -- ----------------------------------------------------------------------------- 15 | 16 | ALTER TABLE merkle_radix_tree_node DROP COLUMN reference; 17 | 18 | ALTER TABLE merkle_radix_leaf DROP COLUMN pruned_at; 19 | 20 | ALTER TABLE merkle_radix_change_log_addition DROP COLUMN pruned_at; 21 | DROP INDEX idx_merkle_change_log_add_tree_id_state_root; 22 | DROP INDEX idx_merkle_change_log_add_tree_id_parent_state_root; 23 | 24 | ALTER TABLE merkle_radix_change_log_deletion DROP COLUMN pruned_at; 25 | DROP INDEX idx_merkle_change_log_delete_tree_id_state_root; 26 | DROP INDEX idx_merkle_change_log_delete_tree_id_successor_state_root; 27 | -------------------------------------------------------------------------------- /libtransact/src/state/merkle/sql/migration/postgres/migrations/2022-03-06-add-pruned-column/up.sql: -------------------------------------------------------------------------------- 1 | -- Copyright 2021 Cargill Incorporated 2 | -- 3 | -- Licensed under the Apache License, Version 2.0 (the "License"); 4 | -- you may not use this file except in compliance with the License. 5 | -- You may obtain a copy of the License at 6 | -- 7 | -- http://www.apache.org/licenses/LICENSE-2.0 8 | -- 9 | -- Unless required by applicable law or agreed to in writing, software 10 | -- distributed under the License is distributed on an "AS IS" BASIS, 11 | -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | -- See the License for the specific language governing permissions and 13 | -- limitations under the License. 14 | -- ----------------------------------------------------------------------------- 15 | 16 | ALTER TABLE merkle_radix_tree_node 17 | ADD COLUMN IF NOT EXISTS reference BIGINT NOT NULL DEFAULT 0; 18 | 19 | -- Count the references via the additions 20 | UPDATE merkle_radix_tree_node 21 | SET reference = ref_counts.reference 22 | FROM (SELECT addition, tree_id, COUNT(*) AS reference 23 | FROM merkle_radix_change_log_addition 24 | GROUP BY addition, tree_id) AS ref_counts 25 | WHERE merkle_radix_tree_node.hash = ref_counts.addition 26 | AND merkle_radix_tree_node.tree_id = ref_counts.tree_id; 27 | 28 | ALTER TABLE merkle_radix_leaf 29 | ADD COLUMN IF NOT EXISTS pruned_at BIGINT; 30 | 31 | ALTER TABLE merkle_radix_change_log_addition 32 | ADD COLUMN IF NOT EXISTS pruned_at BIGINT; 33 | 34 | CREATE INDEX IF NOT EXISTS 35 | idx_merkle_change_log_add_tree_id_state_root 36 | ON merkle_radix_change_log_addition(tree_id, state_root); 37 | 38 | CREATE INDEX IF NOT EXISTS 39 | idx_merkle_change_log_add_tree_id_parent_state_root 40 | ON merkle_radix_change_log_addition(tree_id, parent_state_root); 41 | 42 | ALTER TABLE merkle_radix_change_log_deletion 43 | ADD COLUMN IF NOT EXISTS pruned_at BIGINT; 44 | 45 | CREATE INDEX IF NOT EXISTS 46 | idx_merkle_change_log_delete_tree_id_state_root 47 | ON merkle_radix_change_log_deletion(tree_id, state_root); 48 | 49 | CREATE INDEX IF NOT EXISTS 50 | idx_merkle_change_log_delete_tree_id_successor_state_root 51 | ON merkle_radix_change_log_deletion(tree_id, successor_state_root); 52 | -------------------------------------------------------------------------------- /libtransact/src/state/merkle/sql/migration/postgres/mod.rs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 Cargill Incorporated 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * ----------------------------------------------------------------------------- 16 | */ 17 | 18 | //! Defines methods and utilities to interact with merkle radix tables in a PostgreSQL database. 19 | 20 | embed_migrations!("./src/state/merkle/sql/migration/postgres/migrations"); 21 | 22 | use crate::error::InternalError; 23 | use crate::state::merkle::sql::backend::{Connection, Execute, PostgresBackend}; 24 | 25 | use super::MigrationManager; 26 | 27 | /// Run database migrations to create tables defined for the SqlMerkleState. 28 | /// 29 | /// # Arguments 30 | /// 31 | /// * `conn` - Connection to Postgres database 32 | /// 33 | #[allow(dead_code)] 34 | pub fn run_migrations(conn: &diesel::pg::PgConnection) -> Result<(), InternalError> { 35 | embedded_migrations::run(conn).map_err(|err| InternalError::from_source(Box::new(err)))?; 36 | 37 | debug!("Successfully applied Transact PostgreSQL migrations"); 38 | 39 | Ok(()) 40 | } 41 | 42 | impl MigrationManager for PostgresBackend { 43 | fn run_migrations(&self) -> Result<(), InternalError> { 44 | self.execute(|conn| run_migrations(conn.as_inner())) 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /libtransact/src/state/merkle/sql/migration/sqlite/migrations/2021-09-09-121000-initialize-tables/down.sql: -------------------------------------------------------------------------------- 1 | -- Copyright 2021 Cargill Incorporated 2 | -- 3 | -- Licensed under the Apache License, Version 2.0 (the "License"); 4 | -- you may not use this file except in compliance with the License. 5 | -- You may obtain a copy of the License at 6 | -- 7 | -- http://www.apache.org/licenses/LICENSE-2.0 8 | -- 9 | -- Unless required by applicable law or agreed to in writing, software 10 | -- distributed under the License is distributed on an "AS IS" BASIS, 11 | -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | -- See the License for the specific language governing permissions and 13 | -- limitations under the License. 14 | -- ----------------------------------------------------------------------------- 15 | 16 | DROP TABLE IF EXISTS merkle_radix_change_log_addition; 17 | DROP TABLE IF EXISTS merkle_radix_change_log_deletion; 18 | DROP TABLE IF EXISTS merkle_radix_tree_node; 19 | DROP TABLE IF EXISTS merkle_radix_leaf; 20 | DROP TABLE IF EXISTS merkle_radix_tree; 21 | -------------------------------------------------------------------------------- /libtransact/src/state/merkle/sql/migration/sqlite/migrations/2021-09-09-121000-initialize-tables/up.sql: -------------------------------------------------------------------------------- 1 | -- Copyright 2021 Cargill Incorporated 2 | -- 3 | -- Licensed under the Apache License, Version 2.0 (the "License"); 4 | -- you may not use this file except in compliance with the License. 5 | -- You may obtain a copy of the License at 6 | -- 7 | -- http://www.apache.org/licenses/LICENSE-2.0 8 | -- 9 | -- Unless required by applicable law or agreed to in writing, software 10 | -- distributed under the License is distributed on an "AS IS" BASIS, 11 | -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | -- See the License for the specific language governing permissions and 13 | -- limitations under the License. 14 | -- ----------------------------------------------------------------------------- 15 | 16 | CREATE TABLE IF NOT EXISTS merkle_radix_tree ( 17 | id INTEGER PRIMARY KEY, 18 | name TEXT, 19 | UNIQUE(name) 20 | ); 21 | 22 | INSERT INTO merkle_radix_tree (name) VALUES ('default'); 23 | 24 | CREATE TABLE IF NOT EXISTS merkle_radix_leaf ( 25 | id INTEGER PRIMARY KEY, 26 | tree_id INTEGER NOT NULL, 27 | address STRING NOT NULL, 28 | data BLOB, 29 | FOREIGN KEY(tree_id) REFERENCES merkle_radix_tree (id) 30 | ); 31 | 32 | CREATE TABLE IF NOT EXISTS merkle_radix_tree_node ( 33 | hash STRING NOT NULL, 34 | tree_id INTEGER NOT NULL, 35 | leaf_id INTEGER, 36 | children TEXT, 37 | PRIMARY KEY (hash, tree_id), 38 | FOREIGN KEY(tree_id) REFERENCES merkle_radix_tree (id), 39 | FOREIGN KEY(leaf_id) REFERENCES merkle_radix_leaf(id) 40 | ); 41 | 42 | create TABLE IF NOT EXISTS merkle_radix_change_log_addition ( 43 | id INTEGER PRIMARY KEY, 44 | tree_id BIGINT NOT NULL, 45 | state_root VARCHAR(64) NOT NULL, 46 | parent_state_root VARCHAR(64), 47 | addition VARCHAR(64), 48 | FOREIGN KEY(state_root, tree_id) REFERENCES merkle_radix_tree_node(hash, tree_id), 49 | FOREIGN KEY(parent_state_root, tree_id) REFERENCES merkle_radix_tree_node(hash, tree_id), 50 | FOREIGN KEY(addition, tree_id) REFERENCES merkle_radix_tree_node(hash, tree_id) 51 | ); 52 | 53 | create TABLE IF NOT EXISTS merkle_radix_change_log_deletion ( 54 | id INTEGER PRIMARY KEY, 55 | tree_id BIGINT NOT NULL, 56 | successor_state_root VARCHAR(64) NOT NULL, 57 | state_root VARCHAR(64) NOT NULL, 58 | deletion VARCHAR(64), 59 | FOREIGN KEY(successor_state_root, tree_id) REFERENCES merkle_radix_tree_node(hash, tree_id), 60 | FOREIGN KEY(state_root, tree_id) REFERENCES merkle_radix_tree_node(hash, tree_id), 61 | FOREIGN KEY(deletion, tree_id) REFERENCES merkle_radix_tree_node(hash, tree_id) 62 | ); 63 | -------------------------------------------------------------------------------- /libtransact/src/state/merkle/sql/migration/sqlite/migrations/2022-01-06-101500-correct-column-type/down.sql: -------------------------------------------------------------------------------- 1 | -- Copyright 2022 Cargill Incorporated 2 | -- 3 | -- Licensed under the Apache License, Version 2.0 (the "License"); 4 | -- you may not use this file except in compliance with the License. 5 | -- You may obtain a copy of the License at 6 | -- 7 | -- http://www.apache.org/licenses/LICENSE-2.0 8 | -- 9 | -- Unless required by applicable law or agreed to in writing, software 10 | -- distributed under the License is distributed on an "AS IS" BASIS, 11 | -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | -- See the License for the specific language governing permissions and 13 | -- limitations under the License. 14 | -- ----------------------------------------------------------------------------- 15 | 16 | PRAGMA foreign_keys=OFF; 17 | 18 | CREATE TABLE new_merkle_radix_leaf ( 19 | id INTEGER PRIMARY KEY, 20 | tree_id INTEGER NOT NULL, 21 | address STRING NOT NULL, 22 | data BLOB, 23 | FOREIGN KEY(tree_id) REFERENCES merkle_radix_tree (id) 24 | ); 25 | 26 | INSERT INTO new_merkle_radix_leaf 27 | (id, tree_id, address, data) 28 | SELECT id, tree_id, address, data 29 | FROM merkle_radix_leaf; 30 | 31 | DROP TABLE merkle_radix_leaf; 32 | 33 | ALTER TABLE new_merkle_radix_leaf RENAME TO merkle_radix_leaf; 34 | 35 | PRAGMA foreign_keys=ON; 36 | -------------------------------------------------------------------------------- /libtransact/src/state/merkle/sql/migration/sqlite/migrations/2022-01-06-101500-correct-column-type/up.sql: -------------------------------------------------------------------------------- 1 | -- Copyright 2022 Cargill Incorporated 2 | -- 3 | -- Licensed under the Apache License, Version 2.0 (the "License"); 4 | -- you may not use this file except in compliance with the License. 5 | -- You may obtain a copy of the License at 6 | -- 7 | -- http://www.apache.org/licenses/LICENSE-2.0 8 | -- 9 | -- Unless required by applicable law or agreed to in writing, software 10 | -- distributed under the License is distributed on an "AS IS" BASIS, 11 | -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | -- See the License for the specific language governing permissions and 13 | -- limitations under the License. 14 | -- ----------------------------------------------------------------------------- 15 | 16 | PRAGMA foreign_keys=OFF; 17 | 18 | CREATE TABLE new_merkle_radix_leaf ( 19 | id INTEGER PRIMARY KEY, 20 | tree_id INTEGER NOT NULL, 21 | address TEXT NOT NULL, 22 | data BLOB, 23 | FOREIGN KEY(tree_id) REFERENCES merkle_radix_tree (id) 24 | ); 25 | 26 | INSERT INTO new_merkle_radix_leaf 27 | (id, tree_id, address, data) 28 | SELECT id, tree_id, address, data 29 | FROM merkle_radix_leaf; 30 | 31 | UPDATE new_merkle_radix_leaf 32 | SET address = '0' || address 33 | WHERE length(address) % 2 = 1; 34 | 35 | DROP TABLE merkle_radix_leaf; 36 | 37 | ALTER TABLE new_merkle_radix_leaf RENAME TO merkle_radix_leaf; 38 | 39 | PRAGMA foreign_keys=ON; 40 | -------------------------------------------------------------------------------- /libtransact/src/state/merkle/sql/migration/sqlite/migrations/2022-03-06-add-pruned-column/down.sql: -------------------------------------------------------------------------------- 1 | -- Copyright 2021 Cargill Incorporated 2 | -- 3 | -- Licensed under the Apache License, Version 2.0 (the "License"); 4 | -- you may not use this file except in compliance with the License. 5 | -- You may obtain a copy of the License at 6 | -- 7 | -- http://www.apache.org/licenses/LICENSE-2.0 8 | -- 9 | -- Unless required by applicable law or agreed to in writing, software 10 | -- distributed under the License is distributed on an "AS IS" BASIS, 11 | -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | -- See the License for the specific language governing permissions and 13 | -- limitations under the License. 14 | -- ----------------------------------------------------------------------------- 15 | -------------------------------------------------------------------------------- /libtransact/src/state/merkle/sql/migration/sqlite/migrations/2022-03-06-add-pruned-column/up.sql: -------------------------------------------------------------------------------- 1 | -- Copyright 2021 Cargill Incorporated 2 | -- 3 | -- Licensed under the Apache License, Version 2.0 (the "License"); 4 | -- you may not use this file except in compliance with the License. 5 | -- You may obtain a copy of the License at 6 | -- 7 | -- http://www.apache.org/licenses/LICENSE-2.0 8 | -- 9 | -- Unless required by applicable law or agreed to in writing, software 10 | -- distributed under the License is distributed on an "AS IS" BASIS, 11 | -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | -- See the License for the specific language governing permissions and 13 | -- limitations under the License. 14 | -- ----------------------------------------------------------------------------- 15 | 16 | PRAGMA foreign_keys=OFF; 17 | 18 | ALTER TABLE merkle_radix_tree_node 19 | ADD COLUMN reference INTEGER NOT NULL DEFAULT 0; 20 | 21 | -- Count the references via the additions. In Sqlite, this is accomplished by 22 | -- copying the data to a temporary table, and reinserting it using a join with 23 | -- the counts from the additions. 24 | CREATE TABLE IF NOT EXISTS temp_merkle_radix_tree_node ( 25 | hash STRING NOT NULL, 26 | tree_id INTEGER NOT NULL, 27 | leaf_id INTEGER, 28 | children TEXT, 29 | refernce INTEGER, 30 | PRIMARY KEY (hash, tree_id) 31 | ); 32 | 33 | INSERT INTO temp_merkle_radix_tree_node select * from merkle_radix_tree_node; 34 | 35 | DELETE from merkle_radix_tree_node; 36 | 37 | INSERT into merkle_radix_tree_node 38 | SELECT n.hash, n.tree_id, n.leaf_id, n.children, ref_counts.reference 39 | FROM temp_merkle_radix_tree_node n, 40 | (SELECT addition, tree_id, COUNT(*) AS reference 41 | FROM merkle_radix_change_log_addition 42 | GROUP BY addition, tree_id) AS ref_counts 43 | WHERE n.hash = ref_counts.addition 44 | AND n.tree_id = ref_counts.tree_id; 45 | 46 | DROP TABLE temp_merkle_radix_tree_node; 47 | 48 | ALTER TABLE merkle_radix_leaf ADD COLUMN pruned_at INTEGER; 49 | 50 | ALTER TABLE merkle_radix_change_log_addition ADD COLUMN pruned_at INTEGER; 51 | 52 | CREATE INDEX IF NOT EXISTS 53 | idx_merkle_change_log_add_tree_id_state_root 54 | ON merkle_radix_change_log_addition(tree_id, state_root); 55 | 56 | CREATE INDEX IF NOT EXISTS 57 | idx_merkle_change_log_add_tree_id_parent_state_root 58 | ON merkle_radix_change_log_addition(tree_id, parent_state_root); 59 | 60 | ALTER TABLE merkle_radix_change_log_deletion ADD COLUMN pruned_at INTEGER; 61 | 62 | CREATE INDEX IF NOT EXISTS 63 | idx_merkle_change_log_delete_tree_id_state_root 64 | ON merkle_radix_change_log_deletion(tree_id, state_root); 65 | 66 | CREATE INDEX IF NOT EXISTS 67 | idx_merkle_change_log_delete_tree_id_successor_state_root 68 | ON merkle_radix_change_log_deletion(tree_id, successor_state_root); 69 | 70 | PRAGMA foreign_keys=ON; 71 | -------------------------------------------------------------------------------- /libtransact/src/state/merkle/sql/migration/sqlite/mod.rs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 Cargill Incorporated 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * ----------------------------------------------------------------------------- 16 | */ 17 | 18 | //! Defines methods and utilities to interact with merkle-radix tables in a SQLite database. 19 | 20 | embed_migrations!("./src/state/merkle/sql/migration/sqlite/migrations"); 21 | 22 | use crate::error::InternalError; 23 | use crate::state::merkle::sql::backend::{Connection, SqliteBackend, WriteExclusiveExecute}; 24 | 25 | use super::MigrationManager; 26 | 27 | /// Run database migrations to create tables defined for the SqlMerkleState. 28 | /// 29 | /// # Arguments 30 | /// 31 | /// * `conn` - Connection to SQLite database 32 | /// 33 | pub fn run_migrations(conn: &diesel::sqlite::SqliteConnection) -> Result<(), InternalError> { 34 | embedded_migrations::run(conn).map_err(|err| InternalError::from_source(Box::new(err)))?; 35 | 36 | debug!("Successfully applied Transact SQLite migrations"); 37 | 38 | Ok(()) 39 | } 40 | 41 | impl MigrationManager for SqliteBackend { 42 | fn run_migrations(&self) -> Result<(), InternalError> { 43 | self.execute_write(|conn| run_migrations(conn.as_inner())) 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /libtransact/src/state/merkle/sql/store/models/postgres.rs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 Cargill Incorporated 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * ----------------------------------------------------------------------------- 16 | */ 17 | 18 | use crate::state::merkle::sql::store::schema::postgres_merkle_radix_tree_node; 19 | 20 | #[derive(Hash, PartialEq, Eq, Insertable, Queryable, QueryableByName, Identifiable)] 21 | #[cfg_attr(test, derive(Debug))] 22 | #[table_name = "postgres_merkle_radix_tree_node"] 23 | #[primary_key(hash, tree_id)] 24 | pub struct MerkleRadixTreeNode { 25 | pub hash: String, 26 | pub tree_id: i64, 27 | pub leaf_id: Option, 28 | pub children: Vec>, 29 | pub reference: i64, 30 | } 31 | 32 | impl MerkleRadixTreeNode { 33 | pub fn new>(hash: S, tree_id: i64) -> Self { 34 | Self::inner_new(hash.into(), tree_id) 35 | } 36 | 37 | fn inner_new(hash: String, tree_id: i64) -> Self { 38 | Self { 39 | hash, 40 | tree_id, 41 | leaf_id: None, 42 | children: vec![None; 256], 43 | reference: 1, 44 | } 45 | } 46 | 47 | pub fn with_children(mut self, children: Vec>) -> Self { 48 | self.children = children; 49 | self 50 | } 51 | 52 | pub fn with_leaf_id(mut self, leaf_id: Option) -> Self { 53 | self.leaf_id = leaf_id; 54 | self 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /libtransact/src/state/merkle/sql/store/models/sqlite.rs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 Cargill Incorporated 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * ----------------------------------------------------------------------------- 16 | */ 17 | 18 | use std::io::Write; 19 | 20 | use diesel::{ 21 | backend::Backend, 22 | deserialize::{self, FromSql}, 23 | serialize::{self, Output, ToSql}, 24 | sql_types::Text, 25 | sqlite::Sqlite, 26 | }; 27 | 28 | use crate::state::merkle::sql::store::schema::sqlite_merkle_radix_tree_node; 29 | 30 | #[derive(Insertable, Queryable, QueryableByName, Identifiable)] 31 | #[cfg_attr(test, derive(Debug, PartialEq))] 32 | #[table_name = "sqlite_merkle_radix_tree_node"] 33 | #[primary_key(hash, tree_id)] 34 | pub struct MerkleRadixTreeNode { 35 | pub hash: String, 36 | pub tree_id: i64, 37 | pub leaf_id: Option, 38 | pub children: Children, 39 | pub reference: i64, 40 | } 41 | 42 | impl MerkleRadixTreeNode { 43 | pub fn new>(hash: S, tree_id: i64) -> Self { 44 | Self::inner_new(hash.into(), tree_id) 45 | } 46 | 47 | fn inner_new(hash: String, tree_id: i64) -> Self { 48 | Self { 49 | hash, 50 | tree_id, 51 | leaf_id: None, 52 | children: Children(vec![None; 256]), 53 | reference: 1, 54 | } 55 | } 56 | 57 | pub fn with_children(mut self, children: Vec>) -> Self { 58 | self.children = Children(children); 59 | self 60 | } 61 | 62 | pub fn with_leaf_id(mut self, leaf_id: Option) -> Self { 63 | self.leaf_id = leaf_id; 64 | self 65 | } 66 | } 67 | 68 | #[derive(AsExpression, Debug, FromSqlRow, Deserialize, Serialize)] 69 | #[cfg_attr(test, derive(PartialEq))] 70 | #[sql_type = "diesel::sql_types::Text"] 71 | pub struct Children(pub Vec>); 72 | 73 | impl FromSql for Children { 74 | fn from_sql(bytes: Option<&::RawValue>) -> deserialize::Result { 75 | let t = >::from_sql(bytes)?; 76 | Ok(serde_json::from_str(&t)?) 77 | } 78 | } 79 | 80 | impl ToSql for Children { 81 | fn to_sql(&self, out: &mut Output) -> serialize::Result { 82 | let s = serde_json::to_string(&self.0)?; 83 | >::to_sql(&s, out) 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /libtransact/src/state/merkle/sql/store/operations/mod.rs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 Cargill Incorporated 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * ----------------------------------------------------------------------------- 16 | */ 17 | 18 | pub(super) mod delete_tree; 19 | pub(super) mod get_leaves; 20 | pub(super) mod get_or_create_tree; 21 | pub(super) mod get_path; 22 | pub(super) mod get_tree_by_name; 23 | pub(super) mod has_root; 24 | pub(super) mod list_leaves; 25 | pub(super) mod list_trees; 26 | pub(super) mod prune_entries; 27 | pub(super) mod remove_pruned_entries; 28 | pub(super) mod write_changes; 29 | 30 | mod prepared_stmt; 31 | 32 | #[cfg(feature = "sqlite")] 33 | no_arg_sql_function!( 34 | last_insert_rowid, 35 | diesel::sql_types::BigInt, 36 | "Represents the SQLite last_insert_rowid() function" 37 | ); 38 | 39 | pub struct MerkleRadixOperations<'a, C> 40 | where 41 | C: diesel::Connection, 42 | { 43 | conn: &'a C, 44 | } 45 | 46 | impl<'a, C> MerkleRadixOperations<'a, C> 47 | where 48 | C: diesel::Connection, 49 | { 50 | pub fn new(conn: &'a C) -> Self { 51 | MerkleRadixOperations { conn } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /libtransact/src/state/merkle/sql/store/schema.rs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 Cargill Incorporated 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * ----------------------------------------------------------------------------- 16 | */ 17 | 18 | table! { 19 | merkle_radix_tree (id) { 20 | id -> Int8, 21 | name -> VarChar, 22 | } 23 | } 24 | 25 | table! { 26 | merkle_radix_leaf (id) { 27 | id -> Int8, 28 | tree_id -> Int8, 29 | address -> VarChar, 30 | data -> Blob, 31 | pruned_at -> Nullable, 32 | } 33 | } 34 | 35 | #[cfg(feature = "sqlite")] 36 | table! { 37 | #[sql_name = "merkle_radix_tree_node"] 38 | sqlite_merkle_radix_tree_node (hash, tree_id) { 39 | hash -> VarChar, 40 | tree_id -> Int8, 41 | leaf_id -> Nullable, 42 | // JSON children 43 | children -> Text, 44 | reference -> Int8, 45 | } 46 | } 47 | 48 | #[cfg(feature = "postgres")] 49 | table! { 50 | #[sql_name = "merkle_radix_tree_node"] 51 | postgres_merkle_radix_tree_node (hash, tree_id) { 52 | hash -> VarChar, 53 | tree_id -> Int8, 54 | leaf_id -> Nullable, 55 | children -> Array>, 56 | reference -> Int8, 57 | } 58 | } 59 | 60 | table! { 61 | merkle_radix_change_log_addition (id) { 62 | id -> Int8, 63 | tree_id -> Int8, 64 | state_root -> VarChar, 65 | parent_state_root -> Nullable, 66 | addition -> VarChar, 67 | pruned_at -> Nullable, 68 | } 69 | } 70 | 71 | table! { 72 | merkle_radix_change_log_deletion (id) { 73 | id -> Int8, 74 | tree_id -> Int8, 75 | successor_state_root -> VarChar, 76 | state_root -> VarChar, 77 | deletion -> VarChar, 78 | pruned_at -> Nullable, 79 | } 80 | } 81 | 82 | #[cfg(all(feature = "sqlite", feature = "postgres"))] 83 | allow_tables_to_appear_in_same_query!( 84 | merkle_radix_tree, 85 | merkle_radix_leaf, 86 | sqlite_merkle_radix_tree_node, 87 | postgres_merkle_radix_tree_node, 88 | ); 89 | 90 | #[cfg(all(feature = "sqlite", not(feature = "postgres")))] 91 | allow_tables_to_appear_in_same_query!( 92 | merkle_radix_tree, 93 | merkle_radix_leaf, 94 | sqlite_merkle_radix_tree_node, 95 | ); 96 | 97 | #[cfg(all(not(feature = "sqlite"), feature = "postgres"))] 98 | allow_tables_to_appear_in_same_query!( 99 | merkle_radix_tree, 100 | merkle_radix_leaf, 101 | postgres_merkle_radix_tree_node, 102 | ); 103 | -------------------------------------------------------------------------------- /libtransact/src/state/pruner.rs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Cargill Incorporated 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * ----------------------------------------------------------------------------- 16 | */ 17 | 18 | use super::{State, StateError}; 19 | 20 | /// Provides a way to remove no-longer needed state data from a particular state storage system. 21 | /// 22 | /// Removing `StateIds` and the associated state makes it so the state storage system does not grow 23 | /// unbounded. 24 | pub trait Pruner: State { 25 | /// Prune keys from state for a given set of state IDs. 26 | /// 27 | /// In storage mechanisms that have a concept of `StateId` ordering, this function should 28 | /// provide the functionality to prune older state values. 29 | /// 30 | /// It can be considered a clean-up or space-saving mechanism. 31 | /// 32 | /// It returns the keys that have been removed from state, if any. 33 | /// 34 | /// # Errors 35 | /// 36 | /// [`StateError`] is returned if any issues occur while trying to prune past results. 37 | fn prune(&self, state_ids: Vec) -> Result, StateError>; 38 | } 39 | -------------------------------------------------------------------------------- /libtransact/src/state/reader.rs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Cargill Incorporated 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * ----------------------------------------------------------------------------- 16 | */ 17 | 18 | use std::collections::HashMap; 19 | 20 | use super::{State, StateError}; 21 | 22 | pub type ValueIterResult = Result; 23 | pub type ValueIter = Box>>; 24 | 25 | /// Provides a way to retrieve state values from a particular storage system. 26 | /// 27 | /// This trait provides similar behaviour to the [`Read`](super::Read) trait, without the 28 | /// explicit requirements about thread safety. 29 | pub trait Reader: State { 30 | /// The filter used for the iterating over state values. 31 | type Filter: ?Sized; 32 | 33 | /// At a given `StateId`, attempt to retrieve the given slice of keys. 34 | /// 35 | /// The results of the get will be returned in a `HashMap`. Only keys that were found will be 36 | /// in this map. Keys missing from the map can be assumed to be missing from the underlying 37 | /// storage system as well. 38 | /// 39 | /// # Errors 40 | /// 41 | /// [`StateError`] is returned if any issues occur while trying to fetch the values. 42 | fn get( 43 | &self, 44 | state_id: &Self::StateId, 45 | keys: &[Self::Key], 46 | ) -> Result, StateError>; 47 | 48 | /// Returns an iterator over the values of state. 49 | /// 50 | /// By providing an optional filter, the caller can limit the iteration over a subset of the 51 | /// values. 52 | /// 53 | /// The values are returned in their natural order. 54 | /// 55 | /// # Errors 56 | /// 57 | /// [`StateError`] is returned if any issues occur while trying to query the values. 58 | /// Additionally, a [`StateError`] may be returned on each call to `next` on the resulting 59 | /// iteration. 60 | fn filter_iter( 61 | &self, 62 | state_id: &Self::StateId, 63 | filter: Option<&Self::Filter>, 64 | ) -> ValueIterResult>; 65 | } 66 | -------------------------------------------------------------------------------- /libtransact/src/state/state_trait.rs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Cargill Incorporated 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * ----------------------------------------------------------------------------- 16 | */ 17 | 18 | /// Defines the characteristics of a given state system. 19 | /// 20 | /// A State system stores keys and values. The keys and values may be made available via state 21 | /// IDs, which define a checkpoint in the state. Keys that exist under one state ID are not 22 | /// required to be available under another. How this is handled is left up to the implementation. 23 | /// 24 | /// For example, a `State` defined over a merkle database would prove the root merkle hash as its 25 | /// state ID. 26 | pub trait State { 27 | /// A reference to a checkpoint in state. It could be a merkle hash for a merkle database. 28 | type StateId; 29 | 30 | /// The Key that is being stored in state. 31 | type Key; 32 | 33 | /// The Value that is being stored in state. 34 | type Value; 35 | } 36 | -------------------------------------------------------------------------------- /libtransact/src/workload/batch_reader/mod.rs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 Cargill Incorporated 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * ----------------------------------------------------------------------------- 16 | */ 17 | 18 | //! Trait for reading batches from a source 19 | 20 | pub mod protobuf; 21 | 22 | use crate::error::InternalError; 23 | use crate::protocol::batch::BatchPair; 24 | 25 | /// `BatchReader` provides an API for reading batches from a source 26 | pub trait BatchReader { 27 | /// Returns a vec with at least max_batches `Batches` in it 28 | fn next(&mut self, max_batches: usize) -> Result, InternalError>; 29 | } 30 | -------------------------------------------------------------------------------- /libtransact/src/workload/batch_reader/protobuf.rs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 Cargill Incorporated 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * ------------------------------------------------------------------------------ 16 | */ 17 | 18 | //! Tools for reading length-delimited protobuf batches from a file 19 | 20 | use std::io::Read; 21 | 22 | use protobuf::Message; 23 | 24 | use crate::error::InternalError; 25 | use crate::protocol::batch::BatchPair; 26 | use crate::protos::FromProto; 27 | 28 | use super::BatchReader; 29 | 30 | /// Decodes Protocol Buffer `Batches` from a length-delimited input reader. 31 | pub struct ProtobufBatchReader<'a> { 32 | source: protobuf::CodedInputStream<'a>, 33 | } 34 | 35 | impl<'a> ProtobufBatchReader<'a> { 36 | pub fn new(source: &'a mut dyn Read) -> Self { 37 | let source = protobuf::CodedInputStream::new(source); 38 | ProtobufBatchReader { source } 39 | } 40 | } 41 | 42 | impl BatchReader for ProtobufBatchReader<'_> { 43 | /// Returns the next set of `Batches`. 44 | /// The vector of `Batches` will contain up to `max_batches` number of 45 | /// `Batches`. An empty vector indicates that the source has been consumed. 46 | fn next(&mut self, max_batches: usize) -> Result, InternalError> { 47 | let mut results = Vec::with_capacity(max_batches); 48 | for _ in 0..max_batches { 49 | let eof = self 50 | .source 51 | .eof() 52 | .map_err(|err| InternalError::from_source(Box::new(err)))?; 53 | if eof { 54 | break; 55 | } 56 | 57 | // read the delimited length 58 | let next_len = self 59 | .source 60 | .read_raw_varint32() 61 | .map_err(|err| InternalError::from_source(Box::new(err)))?; 62 | let buf = self 63 | .source 64 | .read_raw_bytes(next_len) 65 | .map_err(|err| InternalError::from_source(Box::new(err)))?; 66 | 67 | let msg = Message::parse_from_bytes(&buf) 68 | .map_err(|err| InternalError::from_source(Box::new(err)))?; 69 | let batch = BatchPair::from_proto(msg) 70 | .map_err(|err| InternalError::from_source(Box::new(err)))?; 71 | results.push(batch); 72 | } 73 | Ok(results) 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /libtransact/src/workload/error.rs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 Bitwise IO, Inc. 3 | * Copyright 2019-2021 Cargill Incorporated 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * ----------------------------------------------------------------------------- 17 | */ 18 | 19 | #[cfg(feature = "workload-batch-gen")] 20 | use crate::error::{InternalError, InvalidStateError}; 21 | 22 | #[cfg(feature = "workload-runner")] 23 | #[derive(Debug, PartialEq, Eq)] 24 | pub enum WorkloadRunnerError { 25 | /// Error raised when failing to submit the batch 26 | SubmitError(String), 27 | TooManyRequests, 28 | /// Error raised when adding workload to the runner 29 | WorkloadAddError(String), 30 | /// Error raised when removing workload from the runner 31 | WorkloadRemoveError(String), 32 | /// Error raised when retrieving a batch status 33 | BatchStatusError(String), 34 | } 35 | 36 | #[cfg(feature = "workload-runner")] 37 | impl std::error::Error for WorkloadRunnerError {} 38 | 39 | #[cfg(feature = "workload-runner")] 40 | impl std::fmt::Display for WorkloadRunnerError { 41 | fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { 42 | match *self { 43 | WorkloadRunnerError::SubmitError(ref err) => { 44 | write!(f, "Unable to submit batch: {}", err) 45 | } 46 | WorkloadRunnerError::TooManyRequests => { 47 | write!(f, "Unable to submit batch because of TooManyRequests") 48 | } 49 | WorkloadRunnerError::WorkloadAddError(ref err) => { 50 | write!(f, "Unable to add workload: {}", err) 51 | } 52 | WorkloadRunnerError::WorkloadRemoveError(ref err) => { 53 | write!(f, "Unable to remove workload: {}", err) 54 | } 55 | WorkloadRunnerError::BatchStatusError(ref err) => { 56 | write!(f, "Error occurred while retrieving batch status: {}", err) 57 | } 58 | } 59 | } 60 | } 61 | 62 | // Errors that may occur during the generation of batches from a source. 63 | #[cfg(feature = "workload-batch-gen")] 64 | #[derive(Debug)] 65 | pub enum BatchingError { 66 | InternalError(InternalError), 67 | InvalidStateError(InvalidStateError), 68 | } 69 | 70 | #[cfg(feature = "workload-batch-gen")] 71 | impl std::fmt::Display for BatchingError { 72 | fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { 73 | match self { 74 | BatchingError::InternalError(err) => f.write_str(&err.to_string()), 75 | BatchingError::InvalidStateError(err) => f.write_str(&err.to_string()), 76 | } 77 | } 78 | } 79 | 80 | #[cfg(feature = "workload-batch-gen")] 81 | impl std::error::Error for BatchingError { 82 | fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { 83 | match self { 84 | BatchingError::InternalError(ref err) => Some(err), 85 | BatchingError::InvalidStateError(ref err) => Some(err), 86 | } 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /libtransact/src/workload/mod.rs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 Bitwise IO, Inc. 3 | * Copyright 2019-2021 Cargill Incorporated 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * ----------------------------------------------------------------------------- 17 | */ 18 | 19 | //! Traits for generating transactions and batches. 20 | 21 | #[cfg(feature = "workload-batch-gen")] 22 | pub mod batch_gen; 23 | #[cfg(feature = "workload-batch-gen")] 24 | mod batch_reader; 25 | mod error; 26 | #[cfg(feature = "workload-runner")] 27 | mod runner; 28 | #[cfg(feature = "workload-batch-gen")] 29 | mod transaction_reader; 30 | 31 | use crate::error::InvalidStateError; 32 | use crate::protocol::batch::BatchPair; 33 | use crate::protocol::transaction::TransactionPair; 34 | #[cfg(feature = "workload-runner")] 35 | pub use crate::workload::runner::{HttpRequestCounter, WorkloadRunner}; 36 | 37 | /// `TransactionWorkload` provides an API for generating transactions 38 | pub trait TransactionWorkload: Send { 39 | /// Get a `TransactionPair` and the result that is expected when that transaction is executed 40 | fn next_transaction( 41 | &mut self, 42 | ) -> Result<(TransactionPair, Option), InvalidStateError>; 43 | } 44 | 45 | /// `BatchWorkload` provides an API for generating batches 46 | pub trait BatchWorkload: Send { 47 | /// Get a `BatchPair` and the result that is expected when that batch is processed and its 48 | /// transactions are executed 49 | fn next_batch(&mut self) 50 | -> Result<(BatchPair, Option), InvalidStateError>; 51 | } 52 | 53 | #[derive(Clone)] 54 | pub enum ExpectedBatchResult { 55 | Invalid, 56 | Valid, 57 | } 58 | 59 | #[cfg(test)] 60 | pub mod tests { 61 | use super::*; 62 | 63 | pub fn test_transaction_workload(workload: &mut dyn TransactionWorkload) { 64 | workload.next_transaction().unwrap(); 65 | workload.next_transaction().unwrap(); 66 | } 67 | 68 | pub fn test_batch_workload(workload: &mut dyn BatchWorkload) { 69 | workload.next_batch().unwrap(); 70 | workload.next_batch().unwrap(); 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /libtransact/src/workload/transaction_reader/mod.rs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 Cargill Incorporated 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * ----------------------------------------------------------------------------- 16 | */ 17 | 18 | //! Trait for reading transactions from a source 19 | 20 | pub mod protobuf; 21 | 22 | use crate::error::InternalError; 23 | use crate::protocol::transaction::Transaction; 24 | 25 | /// `TransactionReader` provides an API for reading transactions from a source 26 | pub trait TransactionReader { 27 | /// Returns a vec with at least max_txns `Transactions` in it 28 | fn next(&mut self, max_txns: usize) -> Result, InternalError>; 29 | } 30 | -------------------------------------------------------------------------------- /libtransact/src/workload/transaction_reader/protobuf.rs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 Cargill Incorporated 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * ------------------------------------------------------------------------------ 16 | */ 17 | 18 | //! Tools for reading length-delimited protobuf transactions from a file 19 | 20 | use std::io::Read; 21 | 22 | use protobuf::Message; 23 | 24 | use crate::error::InternalError; 25 | use crate::protocol::transaction::Transaction; 26 | use crate::protos::FromProto; 27 | 28 | use super::TransactionReader; 29 | 30 | /// Decodes Protocol Buffer `Transactions` from a length-delimited input reader. 31 | pub struct ProtobufTransactionReader<'a> { 32 | source: protobuf::CodedInputStream<'a>, 33 | } 34 | 35 | impl<'a> ProtobufTransactionReader<'a> { 36 | pub fn new(source: &'a mut dyn Read) -> Self { 37 | let source = protobuf::CodedInputStream::new(source); 38 | ProtobufTransactionReader { source } 39 | } 40 | } 41 | 42 | impl TransactionReader for ProtobufTransactionReader<'_> { 43 | /// Returns the next set of `Transactions`. 44 | /// The vector of `Transactions` will contain up to `max_txns` number of 45 | /// `Transactions`. An empty vector indicates that the source has been consumed. 46 | fn next(&mut self, max_txns: usize) -> Result, InternalError> { 47 | let mut results = Vec::with_capacity(max_txns); 48 | for _ in 0..max_txns { 49 | let eof = self 50 | .source 51 | .eof() 52 | .map_err(|err| InternalError::from_source(Box::new(err)))?; 53 | if eof { 54 | break; 55 | } 56 | 57 | // read the delimited length 58 | let next_len = self 59 | .source 60 | .read_raw_varint32() 61 | .map_err(|err| InternalError::from_source(Box::new(err)))?; 62 | let buf = self 63 | .source 64 | .read_raw_bytes(next_len) 65 | .map_err(|err| InternalError::from_source(Box::new(err)))?; 66 | 67 | let msg = Message::parse_from_bytes(&buf) 68 | .map_err(|err| InternalError::from_source(Box::new(err)))?; 69 | let txn = Transaction::from_proto(msg) 70 | .map_err(|err| InternalError::from_source(Box::new(err)))?; 71 | results.push(txn); 72 | } 73 | Ok(results) 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /libtransact/tests/mod.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Cargill Incorporated 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | mod state; 16 | -------------------------------------------------------------------------------- /libtransact/tests/state/mod.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Cargill Incorporated 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #[cfg(feature = "state-merkle")] 16 | mod merkle; 17 | --------------------------------------------------------------------------------