├── .clang-format ├── .cmake_format.yaml ├── .github ├── CODEOWNERS ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── ISSUE_TEMPLATE │ ├── bug_report.md │ ├── config.yml │ └── feature_request.md ├── SECURITY.md ├── SUPPORT.md ├── pull_request_template.md └── workflows │ ├── format.yml │ ├── simple_test.yml │ ├── test-modules.yml │ └── test.yml ├── .gitignore ├── .mbedignore ├── .readthedocs.yml ├── .vscode ├── README.md ├── extensions.json ├── launch.json └── settings.json ├── CHANGELOG.md ├── CMakeLists.txt ├── LICENSE ├── README.md ├── benchmark ├── CMakeLists.txt ├── README.md ├── benchmark_config.h ├── client │ ├── send_tagged_data.c │ └── send_tagged_data_max.c ├── core │ ├── create_transaction_basic_output.c │ ├── create_transaction_basic_output_full.c │ └── create_transaction_basic_output_max.c ├── measure_heap_consumers.py └── run_benchmark.sh ├── cmake ├── blake2.cmake ├── cjson.cmake ├── ed25519_donna.cmake ├── jemalloc.cmake ├── mbedtls.cmake ├── mosquitto.cmake ├── sodium.cmake ├── unity.cmake └── uthash.cmake ├── docs ├── Doxyfile ├── Makefile ├── _static │ └── .gitkeep ├── _templates │ └── .gitkeep ├── api │ ├── core.md │ ├── crypto.md │ ├── events.md │ ├── restful.md │ └── wallet.md ├── arduino_esp32.md ├── conf.py ├── examples.md ├── img │ ├── arduino_examples.png │ ├── arduino_include_zip.png │ ├── arduino_preferences_sketchbook_location.png │ ├── client_application_architecture.jpg │ ├── client_block_diagram.jpg │ └── github_download_zip.png ├── index.md ├── introduction.md ├── make.bat └── requirements.txt ├── examples ├── CMakeLists.txt ├── README.md ├── arduino_esp32_info │ └── arduino_esp32_info.ino ├── arduino_esp32_token_transfer │ └── arduino_esp32_token_transfer.ino ├── client │ ├── encrypted_tagged_data_block.c │ ├── get_block.c │ ├── get_event_blocks.c │ ├── node_info.c │ └── tagged_data_block.c └── wallet │ ├── create_alias_output.c │ ├── mint_native_tokens.c │ ├── send_basic_output.c │ └── send_native_tokens.c ├── functional-tests ├── CMakeLists.txt ├── README.md ├── config.json ├── functional_app.c ├── functional_cases.c └── functional_cases.h ├── iota-c.png ├── library.json ├── library.properties ├── src ├── CMakeLists.txt ├── client │ ├── CMakeLists.txt │ ├── api │ │ ├── events │ │ │ ├── node_event.c │ │ │ ├── node_event.h │ │ │ ├── sub_blocks_metadata.c │ │ │ ├── sub_blocks_metadata.h │ │ │ ├── sub_milestone_payload.c │ │ │ ├── sub_milestone_payload.h │ │ │ ├── sub_outputs_payload.c │ │ │ ├── sub_outputs_payload.h │ │ │ ├── sub_serialized_output.c │ │ │ └── sub_serialized_output.h │ │ ├── json_parser │ │ │ ├── block.c │ │ │ ├── block.h │ │ │ ├── common.c │ │ │ ├── common.h │ │ │ ├── inputs │ │ │ │ ├── inputs.c │ │ │ │ └── inputs.h │ │ │ ├── json_keys.h │ │ │ ├── json_utils.c │ │ │ ├── json_utils.h │ │ │ ├── outputs │ │ │ │ ├── features.c │ │ │ │ ├── features.h │ │ │ │ ├── native_tokens.c │ │ │ │ ├── native_tokens.h │ │ │ │ ├── output_alias.c │ │ │ │ ├── output_alias.h │ │ │ │ ├── output_basic.c │ │ │ │ ├── output_basic.h │ │ │ │ ├── output_foundry.c │ │ │ │ ├── output_foundry.h │ │ │ │ ├── output_nft.c │ │ │ │ ├── output_nft.h │ │ │ │ ├── outputs.c │ │ │ │ ├── outputs.h │ │ │ │ ├── unlock_conditions.c │ │ │ │ └── unlock_conditions.h │ │ │ ├── payloads │ │ │ │ ├── payloads.c │ │ │ │ └── payloads.h │ │ │ ├── unlocks.c │ │ │ └── unlocks.h │ │ └── restful │ │ │ ├── faucet_enqueue.c │ │ │ ├── faucet_enqueue.h │ │ │ ├── get_block.c │ │ │ ├── get_block.h │ │ │ ├── get_block_metadata.c │ │ │ ├── get_block_metadata.h │ │ │ ├── get_health.c │ │ │ ├── get_health.h │ │ │ ├── get_milestone.c │ │ │ ├── get_milestone.h │ │ │ ├── get_node_info.c │ │ │ ├── get_node_info.h │ │ │ ├── get_output.c │ │ │ ├── get_output.h │ │ │ ├── get_outputs_id.c │ │ │ ├── get_outputs_id.h │ │ │ ├── get_tips.c │ │ │ ├── get_tips.h │ │ │ ├── get_transaction_included_block.c │ │ │ ├── get_transaction_included_block.h │ │ │ ├── response_error.c │ │ │ ├── response_error.h │ │ │ ├── send_block.c │ │ │ ├── send_block.h │ │ │ ├── send_tagged_data.c │ │ │ └── send_tagged_data.h │ ├── client_service.h │ ├── constants.h │ └── network │ │ ├── http.h │ │ ├── http_curl.c │ │ ├── http_esp32.c │ │ ├── http_zephyr.c │ │ └── mqtt │ │ ├── mqtt.h │ │ ├── mqtt_esp32.c │ │ └── mqtt_mosquitto.c ├── core │ ├── CMakeLists.txt │ ├── address.c │ ├── address.h │ ├── constants.h │ ├── models │ │ ├── block.c │ │ ├── block.h │ │ ├── inputs │ │ │ ├── utxo_input.c │ │ │ └── utxo_input.h │ │ ├── outputs │ │ │ ├── byte_cost_config.c │ │ │ ├── byte_cost_config.h │ │ │ ├── features.c │ │ │ ├── features.h │ │ │ ├── native_tokens.c │ │ │ ├── native_tokens.h │ │ │ ├── output_alias.c │ │ │ ├── output_alias.h │ │ │ ├── output_basic.c │ │ │ ├── output_basic.h │ │ │ ├── output_foundry.c │ │ │ ├── output_foundry.h │ │ │ ├── output_nft.c │ │ │ ├── output_nft.h │ │ │ ├── outputs.c │ │ │ ├── outputs.h │ │ │ ├── storage_deposit.c │ │ │ ├── storage_deposit.h │ │ │ ├── unlock_conditions.c │ │ │ └── unlock_conditions.h │ │ ├── payloads │ │ │ ├── milestone.c │ │ │ ├── milestone.h │ │ │ ├── tagged_data.c │ │ │ ├── tagged_data.h │ │ │ ├── transaction.c │ │ │ └── transaction.h │ │ ├── signing.c │ │ ├── signing.h │ │ ├── unlocks.c │ │ └── unlocks.h │ └── utils │ │ ├── allocator.h │ │ ├── bech32.c │ │ ├── bech32.h │ │ ├── byte_buffer.c │ │ ├── byte_buffer.h │ │ ├── iota_str.c │ │ ├── iota_str.h │ │ ├── macros.h │ │ ├── slip10.c │ │ ├── slip10.h │ │ ├── uint256.c │ │ └── uint256.h ├── crypto │ ├── CMakeLists.txt │ ├── constants.h │ ├── iota_crypto.c │ └── iota_crypto.h ├── iota_client.h └── wallet │ ├── CMakeLists.txt │ ├── bip39.c │ ├── bip39.h │ ├── output_alias.c │ ├── output_alias.h │ ├── output_basic.c │ ├── output_basic.h │ ├── output_foundry.c │ ├── output_foundry.h │ ├── wallet.c │ ├── wallet.h │ └── wordlists │ ├── README.md │ ├── chinese_simplified.h │ ├── chinese_simplified.txt │ ├── chinese_traditional.h │ ├── chinese_traditional.txt │ ├── czech.h │ ├── czech.txt │ ├── english.h │ ├── english.txt │ ├── french.h │ ├── french.txt │ ├── italian.h │ ├── italian.txt │ ├── japanese.h │ ├── japanese.txt │ ├── korean.h │ ├── korean.txt │ ├── portuguese.h │ ├── portuguese.txt │ ├── spanish.h │ ├── spanish.txt │ ├── word.h │ └── wordlist_header.py ├── tests ├── CMakeLists.txt ├── client │ ├── api_events │ │ ├── test_blocks_events.c │ │ ├── test_milestones_events.c │ │ ├── test_outputs_payloads.c │ │ └── test_serialized_blocks_events.c │ ├── api_json_parser │ │ ├── test_common.c │ │ ├── test_features.c │ │ ├── test_inputs.c │ │ ├── test_native_tokens.c │ │ ├── test_output_alias.c │ │ ├── test_output_basic.c │ │ ├── test_output_foundry.c │ │ ├── test_output_nft.c │ │ ├── test_outputs.c │ │ ├── test_unlock_conditions.c │ │ └── test_unlocks.c │ ├── api_restful │ │ ├── test_block_meta.c │ │ ├── test_faucet_enqueue.c │ │ ├── test_get_block.c │ │ ├── test_get_health.c │ │ ├── test_get_info.c │ │ ├── test_get_milestone.c │ │ ├── test_get_output.c │ │ ├── test_get_tips.c │ │ ├── test_get_transaction_included_block.c │ │ ├── test_outputs_id.c │ │ ├── test_response_error.c │ │ ├── test_send_block.c │ │ └── test_send_tagged_data.c │ ├── test_http.c │ └── test_json.c ├── core │ ├── slip10_vector.h │ ├── test_address.c │ ├── test_allocator.c │ ├── test_block.c │ ├── test_byte_buffer.c │ ├── test_byte_cost_config.c │ ├── test_condition_blocks.c │ ├── test_features.c │ ├── test_inputs.c │ ├── test_iota_str.c │ ├── test_native_tokens.c │ ├── test_output_alias.c │ ├── test_output_basic.c │ ├── test_output_foundry.c │ ├── test_output_nft.c │ ├── test_outputs.c │ ├── test_slip10.c │ ├── test_storage_deposit.c │ ├── test_tagged_data.c │ ├── test_transaction.c │ ├── test_transaction_alias.c │ ├── test_transaction_nft.c │ ├── test_uint256.c │ ├── test_unlocks.c │ └── test_utils_bech32.c ├── crypto │ ├── blake2b_data.h │ ├── ed25519_sign.input │ ├── ed25519_signature_edges.h │ ├── pbkdf2_vectors.h │ ├── pbkdf2_vectors.py │ └── test_crypto.c ├── test_config.h └── wallet │ ├── mnemonic_vectors.h │ ├── test_bip39.c │ └── test_wallet.c └── tools ├── ci_format_check ├── formatter └── hooks ├── autohook.sh ├── pre-commit └── 01-format-check └── scripts └── format_check /.clang-format: -------------------------------------------------------------------------------- 1 | --- 2 | Language: Cpp 3 | # BasedOnStyle: Google 4 | AccessModifierOffset: -1 5 | AlignAfterOpenBracket: Align 6 | AlignConsecutiveAssignments: false 7 | AlignConsecutiveDeclarations: false 8 | AlignEscapedNewlines: Left 9 | AlignOperands: true 10 | AlignTrailingComments: true 11 | AllowAllParametersOfDeclarationOnNextLine: true 12 | AllowShortBlocksOnASingleLine: false 13 | AllowShortCaseLabelsOnASingleLine: false 14 | AllowShortFunctionsOnASingleLine: All 15 | AllowShortIfStatementsOnASingleLine: true 16 | AllowShortLoopsOnASingleLine: true 17 | AlwaysBreakAfterDefinitionReturnType: None 18 | AlwaysBreakAfterReturnType: None 19 | AlwaysBreakBeforeMultilineStrings: true 20 | AlwaysBreakTemplateDeclarations: true 21 | BinPackArguments: true 22 | BinPackParameters: true 23 | BraceWrapping: 24 | AfterClass: false 25 | AfterControlStatement: false 26 | AfterEnum: false 27 | AfterFunction: false 28 | AfterNamespace: false 29 | AfterObjCDeclaration: false 30 | AfterStruct: false 31 | AfterUnion: false 32 | BeforeCatch: false 33 | BeforeElse: false 34 | IndentBraces: false 35 | SplitEmptyFunction: true 36 | SplitEmptyRecord: true 37 | SplitEmptyNamespace: true 38 | BreakBeforeBinaryOperators: None 39 | BreakBeforeBraces: Attach 40 | BreakBeforeInheritanceComma: false 41 | BreakBeforeTernaryOperators: true 42 | BreakConstructorInitializersBeforeComma: false 43 | BreakConstructorInitializers: BeforeColon 44 | BreakAfterJavaFieldAnnotations: false 45 | BreakStringLiterals: true 46 | ColumnLimit: 120 47 | CommentPragmas: '^ IWYU pragma:' 48 | CompactNamespaces: false 49 | ConstructorInitializerAllOnOneLineOrOnePerLine: true 50 | ConstructorInitializerIndentWidth: 4 51 | ContinuationIndentWidth: 4 52 | Cpp11BracedListStyle: true 53 | DerivePointerAlignment: true 54 | DisableFormat: false 55 | ExperimentalAutoDetectBinPacking: false 56 | FixNamespaceComments: true 57 | ForEachMacros: 58 | - foreach 59 | - Q_FOREACH 60 | - BOOST_FOREACH 61 | IncludeCategories: 62 | - Regex: '^<.*\.h>' 63 | Priority: 1 64 | - Regex: '^<.*' 65 | Priority: 2 66 | - Regex: '.*' 67 | Priority: 3 68 | IncludeIsMainRegex: '([-_](test|unittest))?$' 69 | IndentCaseLabels: true 70 | IndentWidth: 2 71 | IndentWrappedFunctionNames: false 72 | JavaScriptQuotes: Leave 73 | JavaScriptWrapImports: true 74 | KeepEmptyLinesAtTheStartOfBlocks: false 75 | MacroBlockBegin: '' 76 | MacroBlockEnd: '' 77 | MaxEmptyLinesToKeep: 1 78 | NamespaceIndentation: None 79 | ObjCBlockIndentWidth: 2 80 | ObjCSpaceAfterProperty: false 81 | ObjCSpaceBeforeProtocolList: false 82 | PenaltyBreakAssignment: 2 83 | PenaltyBreakBeforeFirstCallParameter: 1 84 | PenaltyBreakComment: 300 85 | PenaltyBreakFirstLessLess: 120 86 | PenaltyBreakString: 1000 87 | PenaltyExcessCharacter: 1000000 88 | PenaltyReturnTypeOnItsOwnLine: 200 89 | PointerAlignment: Left 90 | ReflowComments: true 91 | SortIncludes: true 92 | SortUsingDeclarations: true 93 | SpaceAfterCStyleCast: false 94 | SpaceAfterTemplateKeyword: true 95 | SpaceBeforeAssignmentOperators: true 96 | SpaceBeforeParens: ControlStatements 97 | SpaceInEmptyParentheses: false 98 | SpacesBeforeTrailingComments: 2 99 | SpacesInAngles: false 100 | SpacesInContainerLiterals: true 101 | SpacesInCStyleCastParentheses: false 102 | SpacesInParentheses: false 103 | SpacesInSquareBrackets: false 104 | Standard: Auto 105 | TabWidth: 8 106 | UseTab: Never 107 | --- 108 | -------------------------------------------------------------------------------- /.cmake_format.yaml: -------------------------------------------------------------------------------- 1 | _help_format: Options affecting formatting. 2 | format: 3 | _help_line_width: 4 | - How wide to allow formatted cmake files 5 | line_width: 120 6 | _help_tab_size: 7 | - How many spaces to tab for indent 8 | tab_size: 2 9 | _help_max_pargs_hwrap: 10 | - If a positional argument group contains more than this many 11 | - arguments, then force it to a vertical layout. 12 | max_pargs_hwrap: 4 -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/about-codeowners/ 2 | # for more details about CODEOWNERS file 3 | 4 | * @iotaledger/client-c 5 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Report a bug in the C client library 3 | about: Report a bug 4 | labels: bug 5 | --- 6 | 7 | ## Bug description 8 | 9 | Briefly describe the bug. 10 | 11 | ## Version 12 | 13 | Which version of the library are you running? 14 | 15 | - Version: 16 | 17 | ## IOTA network 18 | 19 | Which node are you connected to and which IOTA network is it in? 20 | 21 | - Node URL: 22 | - Network: 23 | 24 | ## Hardware specification 25 | 26 | What hardware are you using? 27 | 28 | - Operating system: 29 | - RAM: 30 | - Number of cores: 31 | - Device type: 32 | ## Compiler and build tool specification 33 | 34 | What compiler are you using? 35 | 36 | What build tool are you using? 37 | Bazel/Bazelisk/CMake 38 | 39 | ## Steps To reproduce the bug 40 | 41 | Explain how the maintainer can reproduce the bug. 42 | 43 | 1. 44 | 2. 45 | 3. 46 | 47 | ## Expected behaviour 48 | 49 | Describe what you expect to happen. 50 | 51 | ## Actual behaviour 52 | 53 | Describe what actually happens. 54 | 55 | ## Errors 56 | 57 | Paste any errors that you see. 58 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: false 2 | contact_links: 3 | - name: Discord 4 | url: https://discord.iota.org/ 5 | about: Please ask and answer questions here. 6 | - name: Security vulnerabilities 7 | url: security@iota.org 8 | about: Please report security vulnerabilities here. -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Request a feature for the C client library 3 | about: Request a feature 4 | --- 5 | 6 | ## Description 7 | 8 | Briefly describe the feature that you are requesting. 9 | 10 | ## Motivation 11 | 12 | Explain why this feature is needed. 13 | 14 | ## Requirements 15 | 16 | Write a list of what you want this feature to do. 17 | 18 | 1. 19 | 2. 20 | 3. 21 | 22 | ## Open questions (optional) 23 | 24 | Use this section to ask any questions that are related to the feature. 25 | 26 | ## Are you planning to do it yourself in a pull request? 27 | 28 | Yes/No. 29 | -------------------------------------------------------------------------------- /.github/SECURITY.md: -------------------------------------------------------------------------------- 1 |

Responsible disclosure policy

2 | 3 | At the IOTA Foundation, we consider the security of our systems a top priority. But no matter how much effort we put into system security, there can still be vulnerabilities present. If you've discovered a vulnerability, please follow the guidelines below to report it to our security team: 4 | 7 | Please follow these rules when testing/reporting vulnerabilities: 8 | 15 | What we promise: 16 | 22 | We sincerely appreciate the efforts of security researchers in keeping our community safe. 23 | 24 | -------------------------------------------------------------------------------- /.github/SUPPORT.md: -------------------------------------------------------------------------------- 1 | # Community resources 2 | 3 | If you have a general or technical question, you can use one of the following resources instead of submitting an issue: 4 | 5 | - [**Developer documentation:**](https://docs.iota.org/) For official information about developing with IOTA technology 6 | - [**Discord:**](https://discord.iota.org/) For real-time chats with the developers and community members 7 | - [**IOTA cafe:**](https://iota.cafe/) For technical discussions with the Research and Development Department at the IOTA Foundation 8 | - [**StackExchange:**](https://iota.stackexchange.com/) For technical and troubleshooting questions -------------------------------------------------------------------------------- /.github/pull_request_template.md: -------------------------------------------------------------------------------- 1 | # Description of change 2 | 3 | Please write a summary of your changes and why you made them. Be sure to reference any related issues by adding `fixes # (issue)`. 4 | 5 | ## Type of change 6 | 7 | Choose a type of change, and delete any options that are not relevant. 8 | 9 | - Bugfix (a non-breaking change which fixes an issue) 10 | - Enhancement (a non-breaking change which adds functionality) 11 | - Breaking change (fix or feature that would cause existing functionality to not work as expected) 12 | - Documentation fix 13 | 14 | ## How the change has been tested 15 | 16 | Describe the tests that you ran to verify your changes. 17 | 18 | Make sure to provide instructions for the maintainer as well as any relevant configurations. 19 | 20 | ## Change checklist 21 | 22 | Add an `x` to the boxes that are relevant to your changes, and delete any items that are not. 23 | 24 | - [ ] My code follows the contribution guidelines for this project 25 | - [ ] I have performed a self-review of my own code 26 | - [ ] I have commented my code, particularly in hard-to-understand areas 27 | - [ ] I have made corresponding changes to the documentation 28 | - [ ] I have added tests using CTest that prove my fix is effective or that my feature works 29 | - [ ] New and existing unit tests pass locally with my changes 30 | -------------------------------------------------------------------------------- /.github/workflows/format.yml: -------------------------------------------------------------------------------- 1 | # coding style and static checks 2 | 3 | name: coding-style 4 | 5 | on: [push, pull_request] 6 | 7 | jobs: 8 | coding_style: 9 | runs-on: ubuntu-20.04 10 | 11 | steps: 12 | - uses: actions/checkout@v2 13 | 14 | - name: install requirements 15 | run: | 16 | sudo apt update 17 | sudo apt install -y cppcheck clang-format-12 18 | sudo pip3 install cmakelang 19 | 20 | - name: Coding style check 21 | run: ./tools/ci_format_check src tests examples 22 | 23 | - name: Static analysis check 24 | run: | 25 | cppcheck --version 26 | cppcheck --force --error-exitcode=1 -q src tests examples 27 | -------------------------------------------------------------------------------- /.github/workflows/simple_test.yml: -------------------------------------------------------------------------------- 1 | # a simple check 2 | name: simple_test 3 | 4 | on: 5 | push: 6 | branches: 7 | - tokenization-sc 8 | pull_request: 9 | branches: 10 | - tokenization-sc 11 | env: 12 | CTEST_OUTPUT_ON_FAILURE: TRUE 13 | 14 | jobs: 15 | simple_make_gcc_openssl: 16 | runs-on: ubuntu-20.04 17 | 18 | steps: 19 | - uses: actions/checkout@v2 20 | 21 | - name: install requirements 22 | run: | 23 | sudo apt update 24 | sudo apt install -y libcurl4-openssl-dev clang-format build-essential 25 | 26 | - name: Debug build 27 | run: | 28 | cmake --version 29 | gcc --version 30 | mkdir build && cd build 31 | cmake -DCMAKE_INSTALL_PREFIX=$PWD -DIOTA_TESTS=ON -DIOTA_ASAN_ENABLED=ON -DCryptoUse=openssl .. 32 | make -j8 && make test 33 | 34 | - name: Release build 35 | run: | 36 | rm -rf build && sync 37 | mkdir build && cd build 38 | cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=$PWD -DIOTA_TESTS=ON -DCryptoUse=openssl .. 39 | make -j8 && make test 40 | -------------------------------------------------------------------------------- /.github/workflows/test-modules.yml: -------------------------------------------------------------------------------- 1 | # Build and test by modules 2 | 3 | name: test-modules 4 | on: 5 | push: 6 | branches: 7 | - production 8 | - staging 9 | - dev* 10 | pull_request: 11 | branches: 12 | - production 13 | - staging 14 | - dev* 15 | env: 16 | CTEST_OUTPUT_ON_FAILURE: TRUE 17 | 18 | jobs: 19 | ninja_clang_check_modules: 20 | runs-on: ubuntu-20.04 21 | steps: 22 | - uses: actions/checkout@v2 23 | 24 | - name: install requirements 25 | run: | 26 | sudo apt update 27 | sudo apt install -y ninja-build libcurl4-openssl-dev build-essential 28 | 29 | - name: Build Crypto 30 | run: | 31 | cmake --version 32 | clang --version 33 | mkdir build && cd build 34 | cmake -G Ninja -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_INSTALL_PREFIX=$PWD -DCryptoUse=openssl -DIOTA_ASAN_ENABLED=ON -DIOTA_WALLET_ENABLE=OFF -DWITH_IOTA_CLIENT=OFF -DWITH_IOTA_CORE=OFF .. 35 | ninja -v && ninja test 36 | 37 | - name: Build Core 38 | run: | 39 | rm -rf build && sync 40 | mkdir build && cd build 41 | cmake -G Ninja -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_INSTALL_PREFIX=$PWD -DCryptoUse=openssl -DIOTA_ASAN_ENABLED=ON -DIOTA_WALLET_ENABLE=OFF -DWITH_IOTA_CLIENT=OFF -DWITH_IOTA_CORE=ON .. 42 | ninja && ninja test 43 | 44 | - name: Build Client 45 | run: | 46 | rm -rf build && sync 47 | mkdir build && cd build 48 | cmake -G Ninja -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_INSTALL_PREFIX=$PWD -DCryptoUse=openssl -DIOTA_ASAN_ENABLED=ON -DIOTA_WALLET_ENABLE=OFF -DWITH_IOTA_CLIENT=ON -DWITH_IOTA_CORE=OFF .. 49 | ninja && ninja test 50 | 51 | - name: Build Wallet 52 | run: | 53 | rm -rf build && sync 54 | mkdir build && cd build 55 | cmake -G Ninja -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_INSTALL_PREFIX=$PWD -DCryptoUse=openssl -DIOTA_ASAN_ENABLED=ON -DIOTA_WALLET_ENABLE=ON -DWITH_IOTA_CLIENT=OFF -DWITH_IOTA_CORE=OFF .. 56 | ninja && ninja test 57 | 58 | - name: Build Examples 59 | run: | 60 | rm -rf build && sync 61 | mkdir build && cd build 62 | cmake -G Ninja -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_INSTALL_PREFIX=$PWD -DCryptoUse=openssl -DIOTA_ASAN_ENABLED=ON -DIOTA_WALLET_ENABLE=ON -DWITH_IOTA_CLIENT=OFF -DWITH_IOTA_CORE=OFF -DIOTA_EXAMPLES=ON .. 63 | ninja && ninja test 64 | -------------------------------------------------------------------------------- /.github/workflows/test.yml: -------------------------------------------------------------------------------- 1 | # Build and Test with different crypto libs and compilers 2 | 3 | name: tests 4 | on: 5 | push: 6 | branches: 7 | - production 8 | - staging 9 | - dev* 10 | pull_request: 11 | branches: 12 | - production 13 | - staging 14 | - dev* 15 | env: 16 | CTEST_OUTPUT_ON_FAILURE: TRUE 17 | 18 | jobs: 19 | ninja_clang_sodium: 20 | runs-on: ubuntu-20.04 21 | steps: 22 | - uses: actions/checkout@v2 23 | 24 | - name: install requirements 25 | run: | 26 | sudo apt update 27 | sudo apt install -y ninja-build libcurl4-openssl-dev build-essential 28 | 29 | - name: Debug build 30 | run: | 31 | cmake --version 32 | clang --version 33 | mkdir build && cd build 34 | cmake -G Ninja -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_INSTALL_PREFIX=$PWD -DCryptoUse=libsodium -DIOTA_ASAN_ENABLED=ON -DIOTA_WALLET_ENABLE=ON .. 35 | ninja -v && ninja test 36 | 37 | - name: Release build 38 | run: | 39 | rm -rf build && sync 40 | mkdir build && cd build 41 | cmake -G Ninja -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_INSTALL_PREFIX=$PWD -DCryptoUse=libsodium -DIOTA_WALLET_ENABLE=ON .. 42 | ninja && ninja test 43 | 44 | make_gcc_openssl: 45 | runs-on: ubuntu-20.04 46 | steps: 47 | - uses: actions/checkout@v2 48 | 49 | - name: install requirements 50 | run: | 51 | sudo apt update 52 | sudo apt install -y libcurl4-openssl-dev clang-format build-essential 53 | 54 | - name: Debug build 55 | run: | 56 | cmake --version 57 | gcc --version 58 | mkdir build && cd build 59 | cmake -DCMAKE_INSTALL_PREFIX=$PWD -DIOTA_TESTS=ON -DIOTA_ASAN_ENABLED=ON -DCryptoUse=openssl .. 60 | make -j8 && make test 61 | 62 | - name: Release build 63 | run: | 64 | rm -rf build && sync 65 | mkdir build && cd build 66 | cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=$PWD -DIOTA_TESTS=ON -DCryptoUse=openssl .. 67 | make -j8 && make test 68 | 69 | make_gcc_mbedtls: 70 | runs-on: ubuntu-20.04 71 | steps: 72 | - uses: actions/checkout@v2 73 | 74 | - name: install requirements 75 | run: | 76 | sudo apt update 77 | sudo apt install -y libcurl4-openssl-dev clang-format build-essential 78 | 79 | - name: Debug build 80 | run: | 81 | cmake --version 82 | gcc --version 83 | mkdir build && cd build 84 | cmake -DCMAKE_INSTALL_PREFIX=$PWD -DIOTA_TESTS=ON -DIOTA_ASAN_ENABLED=ON -DCryptoUse=mbedtls .. 85 | make -j8 && make test 86 | 87 | - name: Release build 88 | run: | 89 | rm -rf build && sync 90 | mkdir build && cd build 91 | cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=$PWD -DIOTA_TESTS=ON -DCryptoUse=mbedtls .. 92 | make -j8 && make test 93 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Bazel 2 | bazel-* 3 | user.bazelrc 4 | 5 | # CMake 6 | build 7 | 8 | # VS Code 9 | .vscode 10 | 11 | # CLion 12 | .idea 13 | 14 | # Sphinx build dir 15 | docs/_build 16 | docs/doxygen_build 17 | -------------------------------------------------------------------------------- /.mbedignore: -------------------------------------------------------------------------------- 1 | cmake/* 2 | docs/* 3 | examples/* 4 | tests/* 5 | tools/* 6 | src/client/* 7 | src/wallet/* 8 | library.json 9 | -------------------------------------------------------------------------------- /.readthedocs.yml: -------------------------------------------------------------------------------- 1 | # .readthedocs.yml 2 | # Read the Docs configuration file 3 | # See https://docs.readthedocs.io/en/stable/config-file/v2.html for details 4 | 5 | # Required 6 | version: 2 7 | 8 | # Build documentation in the docs/ directory with Sphinx 9 | sphinx: 10 | configuration: docs/conf.py 11 | 12 | # Optionally build your docs in additional formats such as PDF 13 | formats: 14 | - pdf 15 | 16 | # Optionally set the version of Python and requirements required to build your docs 17 | python: 18 | version: 3.7 19 | install: 20 | - requirements: docs/requirements.txt 21 | -------------------------------------------------------------------------------- /.vscode/README.md: -------------------------------------------------------------------------------- 1 | # VS Code Integration 2 | 3 | ## Extension Requirements 4 | 5 | * [CMake Tools](https://marketplace.visualstudio.com/items?itemName=ms-vscode.cmake-tools) 6 | * [C/C++ for Visual Studio Code](https://marketplace.visualstudio.com/items?itemName=ms-vscode.cpptools) 7 | * [Clang-Format](https://marketplace.visualstudio.com/items?itemName=xaver.clang-format) 8 | * [cmake-format](https://marketplace.visualstudio.com/items?itemName=cheshirekow.cmake-format) 9 | 10 | see `.vscode/extensions.json` 11 | -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": [ 3 | "ms-vscode.cmake-tools", 4 | "ms-vscode.cpptools", 5 | "xaver.clang-format", 6 | "cheshirekow.cmake-format" 7 | ] 8 | } -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "name": "(gdb)launch", 9 | "type": "cppdbg", 10 | "request": "launch", 11 | "program": "${command:cmake.launchTargetPath}", 12 | "args": [], 13 | "stopAtEntry": true, 14 | "cwd": "${workspaceFolder}", 15 | "environment": [ 16 | { 17 | "name": "PATH", 18 | "value": "$PATH:${command:cmake.launchTargetDirectory}" 19 | } 20 | ], 21 | "externalConsole": false, 22 | "MIMode": "gdb", 23 | "setupCommands": [ 24 | { 25 | "description": "Enable pretty-printing for gdb", 26 | "text": "-enable-pretty-printing", 27 | "ignoreFailures": true 28 | } 29 | ] 30 | } 31 | ] 32 | } -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "editor.tabSize": 2, 3 | "cmake.installPrefix": "${workspaceFolder}/build", 4 | "cmake.buildDirectory": "${workspaceFolder}/build", 5 | "cmake.configureArgs": [ 6 | "-DCryptoUse:STRING=openssl", 7 | "-DIOTA_TESTS:BOOL=TRUE", 8 | "-DIOTA_ASAN_ENABLED:BOOL=TRUE", 9 | "-DIOTA_WALLET_ENABLE:BOOL=TRUE" 10 | ], 11 | "cmakeFormat.args": [ 12 | "--config-file", 13 | "${workspaceFolder}/.cmake_format.yaml" 14 | ] 15 | } 16 | -------------------------------------------------------------------------------- /benchmark/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | #[[ 2 | // Copyright 2022 IOTA Stiftung 3 | // SPDX-License-Identifier: Apache-2.0 4 | ]] 5 | 6 | # function for benchmark cases 7 | function(add_iota_benchmark benchmark_name benchmark_src) 8 | add_executable(${benchmark_name} "${benchmark_src}") 9 | set_target_properties(${benchmark_name} PROPERTIES C_STANDARD_REQUIRED NO C_STANDARD 99) 10 | target_include_directories(${benchmark_name} PRIVATE ${PROJECT_SOURCE_DIR}/src ${PROJECT_SOURCE_DIR}/benchmark 11 | ${CMAKE_INSTALL_PREFIX}/include) 12 | target_compile_options(${benchmark_name} PRIVATE -Wall -Wextra) 13 | if(ENABLE_MTRACE) 14 | target_compile_definitions(${benchmark_name} PRIVATE MTRACE_ENABLED) 15 | endif() 16 | if(${benchmark_src} MATCHES "^core") 17 | add_dependencies(${benchmark_name} iota_core) 18 | target_link_libraries(${benchmark_name} PRIVATE iota_core) 19 | elseif(${benchmark_src} MATCHES "^client") 20 | add_dependencies(${benchmark_name} iota_client) 21 | target_link_libraries(${benchmark_name} PRIVATE iota_client) 22 | elseif(${benchmark_src} MATCHES "^wallet") 23 | add_dependencies(${benchmark_name} iota_wallet) 24 | target_link_libraries(${benchmark_name} PRIVATE iota_wallet) 25 | endif() 26 | # install directory for benchmark application 27 | install(TARGETS ${benchmark_name} RUNTIME DESTINATION "${PROJECT_SOURCE_DIR}/benchmark") 28 | endfunction(add_iota_benchmark) 29 | 30 | add_iota_benchmark(benchmark_create_transaction_basic_output "core/create_transaction_basic_output.c") 31 | add_iota_benchmark(benchmark_create_transaction_basic_output_full "core/create_transaction_basic_output_full.c") 32 | add_iota_benchmark(benchmark_create_transaction_basic_output_max "core/create_transaction_basic_output_max.c") 33 | 34 | if(WITH_IOTA_CLIENT) 35 | add_iota_benchmark(benchmark_send_tagged_data "client/send_tagged_data.c") 36 | add_iota_benchmark(benchmark_send_tagged_data_max "client/send_tagged_data_max.c") 37 | endif() 38 | -------------------------------------------------------------------------------- /benchmark/benchmark_config.h: -------------------------------------------------------------------------------- 1 | // Copyright 2022 IOTA Stiftung 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | #ifndef __BENCHMARK_BENCHMARK_CONFIG_H__ 5 | #define __BENCHMARK_BENCHMARK_CONFIG_H__ 6 | 7 | // Node endpoint 8 | #define NODE_HOST "localhost" 9 | #define NODE_PORT 14265 10 | 11 | #endif 12 | -------------------------------------------------------------------------------- /benchmark/client/send_tagged_data.c: -------------------------------------------------------------------------------- 1 | // Copyright 2022 IOTA Stiftung 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | #ifdef MTRACE_ENABLED 5 | #include 6 | #endif 7 | #include 8 | 9 | #include "benchmark_config.h" 10 | #include "client/api/restful/get_node_info.h" 11 | #include "client/api/restful/send_tagged_data.h" 12 | #include "client/constants.h" 13 | 14 | int main() { 15 | #ifdef MTRACE_ENABLED 16 | // enable memory tracing 17 | mtrace(); 18 | #endif 19 | 20 | iota_client_conf_t ctx = {.host = NODE_HOST, .port = NODE_PORT, .use_tls = false}; 21 | 22 | res_node_info_t* info = res_node_info_new(); 23 | if (!info) { 24 | printf("[%s:%d]: Can not create node info object!\n", __func__, __LINE__); 25 | return -1; 26 | } 27 | 28 | int result = get_node_info(&ctx, info); 29 | if (result != 0 || info->is_error || info->u.info == NULL) { 30 | printf("[%s:%d]: Can not received node info data!\n", __func__, __LINE__); 31 | res_node_info_free(info); 32 | return -1; 33 | } 34 | 35 | byte_t tag[] = "Test tag from a benchmark application."; 36 | byte_t tag_data[] = "Test tagged data from a benchmark application"; 37 | res_send_block_t res = {0}; 38 | 39 | result = send_tagged_data_block(&ctx, info->u.info->protocol_params.version, tag, sizeof(tag), tag_data, 40 | sizeof(tag_data), &res); 41 | if (result != 0 || res.is_error) { 42 | printf("[%s:%d]: Can not send tagged data block!\n", __func__, __LINE__); 43 | res_node_info_free(info); 44 | return -1; 45 | } 46 | res_node_info_free(info); 47 | 48 | printf("[%s:%d]: Tagged Data successfully send! URL: http://%s:%d%s/blocks/0x%s\n", __func__, __LINE__, NODE_HOST, 49 | NODE_PORT, CORE_API_ROUTE, res.u.blk_id); 50 | 51 | return 0; 52 | } 53 | -------------------------------------------------------------------------------- /benchmark/client/send_tagged_data_max.c: -------------------------------------------------------------------------------- 1 | // Copyright 2022 IOTA Stiftung 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | #ifdef MTRACE_ENABLED 5 | #include 6 | #endif 7 | #include 8 | 9 | #include "benchmark_config.h" 10 | #include "client/api/restful/get_node_info.h" 11 | #include "client/api/restful/send_tagged_data.h" 12 | #include "client/constants.h" 13 | #include "core/models/outputs/features.h" 14 | 15 | int main() { 16 | #ifdef MTRACE_ENABLED 17 | // enable memory tracing 18 | mtrace(); 19 | #endif 20 | 21 | iota_client_conf_t ctx = {.host = NODE_HOST, .port = NODE_PORT, .use_tls = false}; 22 | 23 | res_node_info_t* info = res_node_info_new(); 24 | if (!info) { 25 | printf("[%s:%d]: Can not create node info object!\n", __func__, __LINE__); 26 | return -1; 27 | } 28 | 29 | int result = get_node_info(&ctx, info); 30 | if (result != 0 || info->is_error || info->u.info == NULL) { 31 | printf("[%s:%d]: Can not received node info data!\n", __func__, __LINE__); 32 | res_node_info_free(info); 33 | return -1; 34 | } 35 | 36 | byte_t tag[MAX_INDEX_TAG_BYTES] = "Test tagged data from a benchmark application. Test tagged dat"; 37 | byte_t* tag_data = malloc(MAX_METADATA_LENGTH_BYTES); 38 | if (!tag_data) { 39 | printf("[%s:%d]: Can not create tag data object!\n", __func__, __LINE__); 40 | res_node_info_free(info); 41 | return -1; 42 | } 43 | res_send_block_t res = {0}; 44 | 45 | result = send_tagged_data_block(&ctx, info->u.info->protocol_params.version, tag, sizeof(tag), tag_data, 46 | MAX_METADATA_LENGTH_BYTES, &res); 47 | if (result != 0 || res.is_error) { 48 | printf("[%s:%d]: Can not send tagged data block!\n", __func__, __LINE__); 49 | free(tag_data); 50 | res_node_info_free(info); 51 | return -1; 52 | } 53 | free(tag_data); 54 | res_node_info_free(info); 55 | 56 | printf("[%s:%d]: Tagged Data successfully send! URL: http://%s:%d%s/blocks/0x%s\n", __func__, __LINE__, NODE_HOST, 57 | NODE_PORT, CORE_API_ROUTE, res.u.blk_id); 58 | 59 | return 0; 60 | } 61 | -------------------------------------------------------------------------------- /benchmark/measure_heap_consumers.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env python3 2 | import subprocess 3 | import fileinput 4 | import sys 5 | import re 6 | import os 7 | 8 | if len(sys.argv) < 2: 9 | print("Executable file is missing") 10 | print("Usage: python measure_heap_consumers.py executable_file") 11 | quit() 12 | 13 | demo_application = sys.argv[1] 14 | heap_consumers_file_path = os.getcwd() + "/heap_consumers.txt" 15 | 16 | print("Executing " + os.path.basename(demo_application) + " application...") 17 | process = subprocess.Popen("export MALLOC_TRACE=" + heap_consumers_file_path + ";" + demo_application, 18 | shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) 19 | process.wait() 20 | 21 | if process.returncode == 0: 22 | print("Application executed successfully.") 23 | else: 24 | print("Failed to successfully execute application.") 25 | quit() 26 | 27 | print("Collecting results...") 28 | 29 | heap_memory_allocations = {} 30 | 31 | for line in fileinput.input(heap_consumers_file_path, inplace=True): 32 | # find address in memory map 33 | start = line.find('[') 34 | end = line.find(']') 35 | 36 | if start != -1 and end != -1 and line.find(demo_application) != -1 and line.find('+') != -1: 37 | address = line[start + 1:end] 38 | # get line in source code for address in memory map 39 | process = subprocess.Popen("addr2line -e " + demo_application + " " + address, 40 | shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) 41 | process.wait() 42 | # replace address with line number 43 | addr2line = process.stdout.readline().decode("utf-8").rstrip() 44 | line = line.replace(address, addr2line).rstrip() 45 | # update line in a file with line number instead of an address 46 | print(line) 47 | # get size of memory allocation 48 | size_of_allocation = int(line[[m.start() for m in re.finditer(r"0x", line)][1] + 2: len(line)], 16) 49 | # update dictionary 50 | heap_memory_allocations[size_of_allocation] = heap_memory_allocations.get(size_of_allocation, 0) + 1 51 | 52 | print("Results for heap memory allocation are collected.\n") 53 | 54 | # print all heap memory allocations 55 | print("All heap memory allocation:") 56 | all_heap_memory_allocations = sorted(heap_memory_allocations.items(), key=lambda x: x[1], reverse=True) 57 | print("{:<12} {:<10}".format('Alloc.size', 'Occurrence')) 58 | for allocation in all_heap_memory_allocations: 59 | (size, occurrence) = allocation 60 | print("{:<12} {:<10}".format(str(size) + ' B', str(occurrence) + 'x')) 61 | 62 | # print TOP 5 heap memory allocations 63 | print("\nTOP 5 heap memory allocation:") 64 | top_5_heap_memory_allocations = sorted(heap_memory_allocations.items(), key=lambda x: x[0] * x[1], reverse=True) 65 | print("{:<12} {:<10}".format('Alloc.size', 'Occurrence')) 66 | for allocation in top_5_heap_memory_allocations[:5]: 67 | (size, occurrence) = allocation 68 | print("{:<12} {:<10}".format(str(size) + ' B', str(occurrence) + 'x')) 69 | -------------------------------------------------------------------------------- /benchmark/run_benchmark.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | helpFunction() 4 | { 5 | echo "" 6 | echo "Usage: $0 executable_file" 7 | exit 1 # Exit script after printing help 8 | } 9 | 10 | # Print helpFunction in case a parameter is missing 11 | if [ -z "$1" ] 12 | then 13 | echo "Executable file is missing"; 14 | helpFunction 15 | fi 16 | 17 | # Begin script in case executable file is present 18 | executable_file=$1 19 | 20 | echo "Executing memory benchmark for: $executable_file\n" 21 | 22 | echo "Memory benchmark with Valgrind and Massif heap profiler:" 23 | if valgrind --tool=massif --time-unit=B --threshold=0.1 --massif-out-file=massif.out $executable_file; then 24 | ms_print massif.out | head -33 25 | rm massif.out 26 | fi 27 | -------------------------------------------------------------------------------- /cmake/blake2.cmake: -------------------------------------------------------------------------------- 1 | #[[ 2 | // Copyright 2021 IOTA Stiftung 3 | // SPDX-License-Identifier: Apache-2.0 4 | ]] 5 | 6 | if (NOT __BLAKE2_INCLUDE) 7 | set(__BLAKE2_INCLUDE TRUE) 8 | 9 | ExternalProject_Add( 10 | blake2_download 11 | PREFIX ${PROJECT_BINARY_DIR}/blake2 12 | DOWNLOAD_DIR ${PROJECT_BINARY_DIR}/download 13 | DOWNLOAD_NAME 54f4faa4c16ea34bcd59d16e8da46a64b259fc07.tar.gz 14 | URL https://github.com/BLAKE2/BLAKE2/archive/54f4faa4c16ea34bcd59d16e8da46a64b259fc07.tar.gz 15 | URL_HASH SHA256=710753a61f3f67eff11bc1a4e3374651a266493e6c1691c70197e72c3c6379d9 16 | CONFIGURE_COMMAND "" 17 | INSTALL_COMMAND "" 18 | BUILD_COMMAND "" 19 | # for debug 20 | # LOG_DOWNLOAD 1 21 | ) 22 | 23 | set(blake2_cmake_dir ${PROJECT_BINARY_DIR}/blake2/src/ext_blake2) 24 | set(blake2_src_dir ../blake2_download) 25 | set(blake2_install_include ${CMAKE_INSTALL_PREFIX}/include/) 26 | set(blake2_install_lib ${CMAKE_INSTALL_PREFIX}/lib) 27 | 28 | file(WRITE ${blake2_cmake_dir}/CMakeLists.txt 29 | "cmake_minimum_required(VERSION 3.15)\n" 30 | "project(blake2 C)\n" 31 | "add_library(blake2 STATIC)\n" 32 | "target_sources(\n" 33 | "blake2\n" 34 | "PRIVATE \"${blake2_src_dir}/ref/blake2-impl.h\"\n" 35 | " \"${blake2_src_dir}/ref/blake2b-ref.c\"\n" 36 | " \"${blake2_src_dir}/ref/blake2bp-ref.c\"\n" 37 | " \"${blake2_src_dir}/ref/blake2s-ref.c\"\n" 38 | " \"${blake2_src_dir}/ref/blake2sp-ref.c\"\n" 39 | " \"${blake2_src_dir}/ref/blake2xb-ref.c\"\n" 40 | " \"${blake2_src_dir}/ref/blake2xs-ref.c\"\n" 41 | "PUBLIC \"${blake2_src_dir}/ref/blake2.h\")\n" 42 | "target_include_directories(blake2 PUBLIC ${base58_src_dir})\n" 43 | "install(TARGETS blake2 DESTINATION ${blake2_install_lib})\n" 44 | "install(FILES ${blake2_src_dir}/ref/blake2.h DESTINATION ${blake2_install_include})\n" 45 | ) 46 | 47 | ExternalProject_Add( 48 | ext_blake2 49 | PREFIX ${PROJECT_BINARY_DIR}/blake2 50 | DOWNLOAD_COMMAND "" 51 | BUILD_IN_SOURCE TRUE 52 | CMAKE_ARGS 53 | -DCMAKE_BUILD_TYPE:STRING=${CMAKE_BUILD_TYPE} 54 | -DCMAKE_INSTALL_PREFIX:STRING=${CMAKE_INSTALL_PREFIX} 55 | -DCMAKE_C_COMPILER:FILEPATH=${CMAKE_C_COMPILER} 56 | # for debug 57 | # LOG_CONFIGURE 1 58 | # LOG_INSTALL 1 59 | ) 60 | add_dependencies(ext_blake2 blake2_download) 61 | 62 | endif() 63 | -------------------------------------------------------------------------------- /cmake/cjson.cmake: -------------------------------------------------------------------------------- 1 | #[[ 2 | // Copyright 2020 IOTA Stiftung 3 | // SPDX-License-Identifier: Apache-2.0 4 | ]] 5 | 6 | if (NOT __CJSON_INCLUDED) 7 | set(__CJSON_INCLUDED TRUE) 8 | 9 | ExternalProject_Add( 10 | ext_cjson 11 | PREFIX ${PROJECT_BINARY_DIR}/cjson 12 | DOWNLOAD_DIR ${PROJECT_BINARY_DIR}/download 13 | DOWNLOAD_NAME cjson_v1.7.15.tar.gz 14 | URL https://github.com/DaveGamble/cJSON/archive/v1.7.15.tar.gz 15 | URL_HASH SHA256=5308fd4bd90cef7aa060558514de6a1a4a0819974a26e6ed13973c5f624c24b2 16 | BUILD_IN_SOURCE TRUE 17 | CMAKE_ARGS 18 | -DENABLE_CJSON_TEST:STRING=Off 19 | -DENABLE_CJSON_UTILS:STRING=Off 20 | -DBUILD_SHARED_LIBS:STRING=Off 21 | -DCMAKE_INSTALL_PREFIX:STRING=${CMAKE_INSTALL_PREFIX} 22 | -DCMAKE_C_COMPILER:FILEPATH=${CMAKE_C_COMPILER} 23 | -DCMAKE_BUILD_TYPE:STRING=${CMAKE_BUILD_TYPE} 24 | # -DCMAKE_TOOLCHAIN_FILE:STRING=${CMAKE_TOOLCHAIN_FILE} 25 | # for debug 26 | # LOG_DOWNLOAD 1 27 | # LOG_CONFIGURE 1 28 | # LOG_INSTALL 1 29 | ) 30 | endif() 31 | -------------------------------------------------------------------------------- /cmake/jemalloc.cmake: -------------------------------------------------------------------------------- 1 | #[[ 2 | // Copyright 2020 IOTA Stiftung 3 | // SPDX-License-Identifier: Apache-2.0 4 | ]] 5 | 6 | if (NOT __JEMALLOC_INCLUDED) 7 | set(__JEMALLOC_INCLUDED TRUE) 8 | 9 | set(jemalloc_src_dir ${PROJECT_BINARY_DIR}/jemalloc/src/jemalloc) 10 | 11 | if(${CMAKE_BUILD_TYPE} MATCHES Debug) 12 | ExternalProject_Add( 13 | jemalloc 14 | PREFIX ${PROJECT_BINARY_DIR}/jemalloc 15 | DOWNLOAD_DIR ${PROJECT_BINARY_DIR}/download 16 | DOWNLOAD_NAME jemalloc-5.2.1.tar.bz2 17 | URL https://github.com/jemalloc/jemalloc/releases/download/5.2.1/jemalloc-5.2.1.tar.bz2 18 | URL_HASH SHA256=34330e5ce276099e2e8950d9335db5a875689a4c6a56751ef3b1d8c537f887f6 19 | BUILD_IN_SOURCE TRUE 20 | CONFIGURE_COMMAND ${jemalloc_src_dir}/configure --enable-debug --enable-log --prefix=${CMAKE_INSTALL_PREFIX} CC=${CMAKE_C_COMPILER} CXX=${CMAKE_CXX_COMPILER} 21 | BUILD_COMMAND make build_lib install_lib install_include -j10 22 | # INSTALL_COMMAND "" 23 | # for debug 24 | # LOG_DOWNLOAD 1 25 | ) 26 | else() 27 | ExternalProject_Add( 28 | jemalloc 29 | PREFIX ${PROJECT_BINARY_DIR}/jemalloc 30 | DOWNLOAD_DIR ${PROJECT_BINARY_DIR}/download 31 | DOWNLOAD_NAME jemalloc-5.2.1.tar.bz2 32 | URL https://github.com/jemalloc/jemalloc/releases/download/5.2.1/jemalloc-5.2.1.tar.bz2 33 | URL_HASH SHA256=34330e5ce276099e2e8950d9335db5a875689a4c6a56751ef3b1d8c537f887f6 34 | BUILD_IN_SOURCE TRUE 35 | CONFIGURE_COMMAND ${jemalloc_src_dir}/configure --prefix=${CMAKE_INSTALL_PREFIX} CC=${CMAKE_C_COMPILER} CXX=${CMAKE_CXX_COMPILER} 36 | BUILD_COMMAND make build_lib install_lib install_include -j10 37 | # INSTALL_COMMAND "" 38 | # for debug 39 | # LOG_DOWNLOAD 1 40 | ) 41 | endif() 42 | 43 | # add_library(malloc::jemalloc ALIAS jemalloc) 44 | 45 | set(THREADS_PREFER_PTHREAD_FLAG ON) 46 | find_package(Threads REQUIRED) 47 | endif() 48 | -------------------------------------------------------------------------------- /cmake/mbedtls.cmake: -------------------------------------------------------------------------------- 1 | #[[ 2 | // Copyright 2021 IOTA Stiftung 3 | // SPDX-License-Identifier: Apache-2.0 4 | ]] 5 | 6 | if (NOT __MBEDTLS_INCLUDED) 7 | set(__MBEDTLS_INCLUDED TRUE) 8 | 9 | set(MBEDTLS_VERSION "v2.28.0") 10 | 11 | ExternalProject_Add( 12 | mbedtls_download 13 | PREFIX ${PROJECT_BINARY_DIR}/mbedtls 14 | SOURCE_DIR ${PROJECT_BINARY_DIR}/mbedtls/src/ext_mbedtls 15 | DOWNLOAD_DIR ${PROJECT_BINARY_DIR}/download 16 | DOWNLOAD_NAME mbedtls_${MBEDTLS_VERSION}.tar.gz 17 | URL https://github.com/ARMmbed/mbedtls/archive/refs/tags/${MBEDTLS_VERSION}.tar.gz 18 | URL_HASH SHA256=6519579b836ed78cc549375c7c18b111df5717e86ca0eeff4cb64b2674f424cc 19 | CONFIGURE_COMMAND "" 20 | INSTALL_COMMAND "" 21 | BUILD_COMMAND "" 22 | # for debug 23 | # LOG_DOWNLOAD 1 24 | ) 25 | 26 | ExternalProject_Add( 27 | ext_mbedtls 28 | PREFIX ${PROJECT_BINARY_DIR}/mbedtls 29 | DOWNLOAD_COMMAND "" 30 | CMAKE_ARGS 31 | -DENABLE_TESTING=Off 32 | -DENABLE_PROGRAMS=Off 33 | -DCMAKE_INSTALL_PREFIX:STRING=${CMAKE_INSTALL_PREFIX} 34 | # -DCMAKE_TOOLCHAIN_FILE:STRING=${CMAKE_TOOLCHAIN_FILE} 35 | # for debug 36 | # LOG_CONFIGURE 1 37 | # LOG_INSTALL 1 38 | ) 39 | 40 | add_dependencies(ext_mbedtls mbedtls_download) 41 | 42 | endif() 43 | -------------------------------------------------------------------------------- /cmake/mosquitto.cmake: -------------------------------------------------------------------------------- 1 | #[[ 2 | // Copyright 2021 IOTA Stiftung 3 | // SPDX-License-Identifier: Apache-2.0 4 | ]] 5 | 6 | if (NOT __MOSQUITTO_INCLUDED) 7 | set(__MOSQUITTO_INCLUDED TRUE) 8 | 9 | ExternalProject_Add( 10 | ext_mosquitto 11 | PREFIX ${PROJECT_BINARY_DIR}/mosquitto 12 | DOWNLOAD_DIR ${PROJECT_BINARY_DIR}/download 13 | DOWNLOAD_NAME mosquitto_v2.0.14.tar.gz 14 | URL https://github.com/eclipse/mosquitto/archive/v2.0.14.tar.gz 15 | URL_HASH SHA256=c0ce97b1911d1769ccfd65da237e919fd7eaa60209fd190c113d63fbd0c40347 16 | BUILD_IN_SOURCE TRUE 17 | CMAKE_ARGS 18 | -DWITH_CJSON:STRING=OFF 19 | -DWITH_TLS:STRING=OFF 20 | -DWITH_STATIC_LIBRARIES:STRING=ON 21 | -DWITH_THREADING:STRING=ON 22 | -DWITH_CLIENTS:STRING=OFF 23 | -DWITH_BROKER:STRING=OFF 24 | -DWITH_APPS:STRING=OFF 25 | -DWITH_PLUGINS:STRING=OFF 26 | -DDOCUMENTATION:STRING=OFF 27 | -DCMAKE_INSTALL_PREFIX:STRING=${CMAKE_INSTALL_PREFIX} 28 | -DCMAKE_C_COMPILER:FILEPATH=${CMAKE_C_COMPILER} 29 | -DCMAKE_BUILD_TYPE:STRING=${CMAKE_BUILD_TYPE} 30 | # for debug 31 | # LOG_DOWNLOAD 1 32 | # LOG_CONFIGURE 1 33 | # LOG_INSTALL 1 34 | ) 35 | 36 | endif() 37 | -------------------------------------------------------------------------------- /cmake/sodium.cmake: -------------------------------------------------------------------------------- 1 | #[[ 2 | // Copyright 2020 IOTA Stiftung 3 | // SPDX-License-Identifier: Apache-2.0 4 | ]] 5 | 6 | if (NOT __SODIUM_INCLUDED) 7 | set(__SODIUM_INCLUDED TRUE) 8 | 9 | set(sodium_src_dir ${PROJECT_BINARY_DIR}/libsodium/src/sodium) 10 | 11 | ExternalProject_Add( 12 | sodium 13 | PREFIX ${PROJECT_BINARY_DIR}/libsodium 14 | DOWNLOAD_DIR ${PROJECT_BINARY_DIR}/download 15 | DOWNLOAD_NAME libsodium-1.0.18-stable.tar.gz 16 | URL https://download.libsodium.org/libsodium/releases/libsodium-1.0.18-stable.tar.gz 17 | # URL_HASH SHA256=2ef4304dd844e274d78dfcf0201e1ba1a312eaba135bdc8affc56a3d80b58593 18 | BUILD_IN_SOURCE TRUE 19 | CONFIGURE_COMMAND ${sodium_src_dir}/configure --prefix=${CMAKE_INSTALL_PREFIX} --disable-shared CC=${CMAKE_C_COMPILER} CXX=${CMAKE_CXX_COMPILER} 20 | # BUILD_COMMAND make 21 | # INSTALL_COMMAND "" 22 | # for debug 23 | # LOG_DOWNLOAD 1 24 | ) 25 | 26 | endif() 27 | -------------------------------------------------------------------------------- /cmake/unity.cmake: -------------------------------------------------------------------------------- 1 | #[[ 2 | // Copyright 2020 IOTA Stiftung 3 | // SPDX-License-Identifier: Apache-2.0 4 | ]] 5 | 6 | if (NOT __UNITY_INCLUDED) 7 | set(__UNITY_INCLUDED TRUE) 8 | 9 | ExternalProject_Add( 10 | ext_unity 11 | PREFIX ${PROJECT_BINARY_DIR}/unity 12 | DOWNLOAD_DIR ${PROJECT_BINARY_DIR}/download 13 | DOWNLOAD_NAME unity_v2.5.2.tar.gz 14 | URL https://github.com/ThrowTheSwitch/Unity/archive/v2.5.2.tar.gz 15 | URL_HASH SHA256=3786de6c8f389be3894feae4f7d8680a02e70ed4dbcce36109c8f8646da2671a 16 | BUILD_IN_SOURCE TRUE 17 | CMAKE_ARGS 18 | -DCMAKE_BUILD_TYPE:STRING=${CMAKE_BUILD_TYPE} 19 | -DCMAKE_INSTALL_PREFIX:STRING=${CMAKE_INSTALL_PREFIX} 20 | -DCMAKE_C_COMPILER:FILEPATH=${CMAKE_C_COMPILER} 21 | # for debug 22 | # LOG_CONFIGURE 1 23 | # LOG_INSTALL 1 24 | ) 25 | 26 | endif() 27 | -------------------------------------------------------------------------------- /cmake/uthash.cmake: -------------------------------------------------------------------------------- 1 | #[[ 2 | // Copyright 2020 IOTA Stiftung 3 | // SPDX-License-Identifier: Apache-2.0 4 | ]] 5 | 6 | if (NOT __UTHASH_INCLUDED) 7 | set(__UTHASH_INCLUDED TRUE) 8 | 9 | ExternalProject_Add( 10 | ext_uthash 11 | PREFIX ${PROJECT_BINARY_DIR}/uthash 12 | DOWNLOAD_DIR ${PROJECT_BINARY_DIR}/download 13 | URL https://github.com/troydhanson/uthash/archive/v2.3.0.tar.gz 14 | URL_HASH SHA256=e10382ab75518bad8319eb922ad04f907cb20cccb451a3aa980c9d005e661acc 15 | CONFIGURE_COMMAND "" 16 | BUILD_COMMAND "" 17 | INSTALL_COMMAND ${CMAKE_COMMAND} -E copy_directory 18 | /src ${CMAKE_INSTALL_PREFIX}/include 19 | ) 20 | 21 | endif() 22 | -------------------------------------------------------------------------------- /docs/Makefile: -------------------------------------------------------------------------------- 1 | # Minimal makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line, and also 5 | # from the environment for the first two. 6 | SPHINXOPTS ?= 7 | SPHINXBUILD ?= sphinx-build 8 | SOURCEDIR = . 9 | BUILDDIR = _build 10 | 11 | # Put it first so that "make" without argument is like "make help". 12 | help: 13 | @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 14 | 15 | .PHONY: help Makefile 16 | 17 | # Catch-all target: route all unknown targets to Sphinx using the new 18 | # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). 19 | %: Makefile 20 | @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 21 | -------------------------------------------------------------------------------- /docs/_static/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iotaledger-archive/iota.c/bdcaf8e4e704fe32d0e8ed6ab7b75a90126eb390/docs/_static/.gitkeep -------------------------------------------------------------------------------- /docs/_templates/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iotaledger-archive/iota.c/bdcaf8e4e704fe32d0e8ed6ab7b75a90126eb390/docs/_templates/.gitkeep -------------------------------------------------------------------------------- /docs/api/crypto.md: -------------------------------------------------------------------------------- 1 | # Crypto API Reference 2 | 3 | The Crypto APIs provide an abstraction layer of cryptography functions. 4 | 5 | ## ED25519 Keypair 6 | 7 | ```{eval-rst} 8 | .. doxygenstruct:: ed25519_keypair_t 9 | :members: 10 | ``` 11 | 12 | ## Random Bytes 13 | 14 | ```{eval-rst} 15 | .. doxygenfunction:: iota_crypto_randombytes 16 | ``` 17 | 18 | ## ED25519 keypair 19 | 20 | ```{eval-rst} 21 | .. doxygenfunction:: iota_crypto_keypair 22 | ``` 23 | 24 | ## ED25519 Signature 25 | 26 | ```{eval-rst} 27 | .. doxygenfunction:: iota_crypto_sign 28 | ``` 29 | 30 | ```{eval-rst} 31 | .. doxygenfunction:: iota_crypto_sign_open 32 | ``` 33 | 34 | ## HMAC-SHA-256 35 | 36 | ```{eval-rst} 37 | .. doxygenfunction:: iota_crypto_hmacsha256 38 | ``` 39 | 40 | ## HMAC-SHA-512 41 | 42 | ```{eval-rst} 43 | .. doxygenfunction:: iota_crypto_hmacsha512 44 | ``` 45 | 46 | ## SHA-256 47 | 48 | ```{eval-rst} 49 | .. doxygenfunction:: iota_crypto_sha256 50 | ``` 51 | 52 | ## SHA-512 53 | 54 | ```{eval-rst} 55 | .. doxygenfunction:: iota_crypto_sha512 56 | ``` 57 | 58 | ## Blake2b 59 | 60 | ```{eval-rst} 61 | .. doxygenfunction:: iota_blake2b_sum 62 | ``` 63 | 64 | ```{eval-rst} 65 | .. doxygenfunction:: iota_blake2b_new_state 66 | ``` 67 | 68 | ```{eval-rst} 69 | .. doxygenfunction:: iota_blake2b_free_state 70 | ``` 71 | 72 | ```{eval-rst} 73 | .. doxygenfunction:: iota_blake2b_init 74 | ``` 75 | 76 | ```{eval-rst} 77 | .. doxygenfunction:: iota_blake2b_update 78 | ``` 79 | 80 | ```{eval-rst} 81 | .. doxygenfunction:: iota_blake2b_final 82 | ``` 83 | 84 | ## PBKDF2 HMAC 85 | 86 | ```{eval-rst} 87 | .. doxygenfunction:: iota_crypto_pbkdf2_hmac_sha512 88 | ``` 89 | -------------------------------------------------------------------------------- /docs/api/events.md: -------------------------------------------------------------------------------- 1 | # Event API Reference 2 | 3 | The Event API is event subscribers based on [TIP-28 Node Event API](https://github.com/iotaledger/tips/pull/66), it provides an easy way to subscribe node events via MQTT protocol. 4 | 5 | ## Event Client Configuration 6 | 7 | ```{eval-rst} 8 | .. doxygenstruct:: event_client_config_t 9 | :members: 10 | ``` 11 | 12 | ## Event IDs 13 | 14 | ```{eval-rst} 15 | .. doxygenenum:: event_client_event_id_t 16 | ``` 17 | 18 | ## Initialize Event Service 19 | 20 | ```{eval-rst} 21 | .. doxygenfunction:: event_init 22 | ``` 23 | 24 | ## Register Event Callback Handler 25 | 26 | ```{eval-rst} 27 | .. doxygenfunction:: event_register_cb 28 | ``` 29 | 30 | ## Subscribe To A Topic 31 | 32 | ```{eval-rst} 33 | .. doxygenfunction:: event_subscribe 34 | ``` 35 | 36 | ## Unsubscribe To A Topic 37 | 38 | ```{eval-rst} 39 | .. doxygenfunction:: event_unsubscribe 40 | ``` 41 | 42 | ## Start Event Service 43 | 44 | ```{eval-rst} 45 | .. doxygenfunction:: event_start 46 | ``` 47 | 48 | ## Stop Event Service 49 | 50 | ```{eval-rst} 51 | .. doxygenfunction:: event_stop 52 | ``` 53 | 54 | ## Destroy Event Service 55 | 56 | ```{eval-rst} 57 | .. doxygenfunction:: event_destroy 58 | ``` 59 | 60 | ## IOTA Event Topics 61 | 62 | ### milestone-info/latest 63 | 64 | Use `TOPIC_MILESTONE_LATEST` 65 | 66 | ``` 67 | event_subscribe(event_client_handle_t client, int *mid, TOPIC_MS_LATEST, int qos); 68 | ``` 69 | 70 | ### milestone-info/confirmed 71 | 72 | ``` 73 | event_subscribe(event->client, NULL, TOPIC_MILESTONE_CONGIRMED, 1); 74 | ``` 75 | 76 | ### milestones 77 | 78 | TODO 79 | 80 | ### blocks 81 | 82 | ``` 83 | event_subscribe(event->client, NULL, TOPIC_BLOCKS, 1); 84 | ``` 85 | 86 | ### blocks/transaction 87 | 88 | ``` 89 | event_subscribe(event->client, NULL, TOPIC_BLK_TRANSACTION, 1); 90 | ``` 91 | 92 | ### blocks/transaction/tagged-data 93 | 94 | TODO 95 | 96 | ### blocks/transaction/tagged-data/{tag} 97 | 98 | TODO 99 | 100 | ### blocks/tagged-data 101 | 102 | ``` 103 | event_subscribe(event->client, NULL, TOPIC_BLK_TAGGED_DATA, 1); 104 | ``` 105 | 106 | ### blocks/tagged-data/{tag} 107 | 108 | TODO 109 | 110 | ### transactions/{transaction ID}/included-block 111 | 112 | TODO 113 | 114 | ### block-metadata/{block ID} 115 | 116 | TODO 117 | 118 | ### block-metadata/referenced 119 | 120 | TODO 121 | 122 | ### outputs/{Output ID} 123 | 124 | ```{eval-rst} 125 | .. doxygenfunction:: event_sub_outputs_id 126 | ``` 127 | 128 | ### outputs/nft/{NFT ID} 129 | 130 | ```{eval-rst} 131 | .. doxygenfunction:: event_sub_outputs_nft_id 132 | ``` 133 | 134 | ### outputs/aliases/{Alias ID} 135 | 136 | ```{eval-rst} 137 | .. doxygenfunction:: event_sub_outputs_alias_id 138 | ``` 139 | 140 | ### outputs/foundries/{Foundry ID} 141 | 142 | ```{eval-rst} 143 | .. doxygenfunction:: event_sub_outputs_foundry_id 144 | ``` 145 | 146 | ### outputs/unlock/{condition}/{address} 147 | 148 | ```{eval-rst} 149 | .. doxygenfunction:: event_sub_outputs_unlock_address 150 | ``` 151 | 152 | ### outputs/unlock/{condition}/{address}/spent 153 | 154 | ```{eval-rst} 155 | .. doxygenfunction:: event_sub_outputs_unlock_address_spent 156 | ``` 157 | 158 | -------------------------------------------------------------------------------- /docs/api/wallet.md: -------------------------------------------------------------------------------- 1 | # Wallet API Reference 2 | 3 | The Wallet API provides some helper methods for developers to create wallet alllications. 4 | 5 | ## Wallet Configuration 6 | 7 | ```{eval-rst} 8 | .. doxygenstruct:: iota_wallet_t 9 | :members: 10 | ``` 11 | 12 | ## Create and Destory Methods 13 | 14 | ```{eval-rst} 15 | .. doxygenfunction:: wallet_create 16 | ``` 17 | 18 | ```{eval-rst} 19 | .. doxygenfunction:: wallet_destroy 20 | ``` 21 | 22 | ```{eval-rst} 23 | .. doxygenfunction:: wallet_set_endpoint 24 | ``` 25 | 26 | ```{eval-rst} 27 | .. doxygenfunction:: wallet_update_node_config 28 | ``` 29 | 30 | ## Address Methods 31 | 32 | ```{eval-rst} 33 | .. doxygenfunction:: wallet_ed25519_address_from_index 34 | ``` 35 | 36 | ```{eval-rst} 37 | .. doxygenfunction:: wallet_get_address_and_keypair_from_index 38 | ``` 39 | 40 | ## UTXO Methods 41 | 42 | ```{eval-rst} 43 | .. doxygenfunction:: wallet_is_collected_balance_sufficient 44 | ``` 45 | 46 | ```{eval-rst} 47 | .. doxygenfunction:: wallet_calculate_remainder_amount 48 | ``` 49 | 50 | ```{eval-rst} 51 | .. doxygenfunction:: wallet_send 52 | ``` 53 | 54 | ```{eval-rst} 55 | .. doxygenfunction:: wallet_create_core_block 56 | ``` 57 | 58 | ```{eval-rst} 59 | .. doxygenfunction:: wallet_send_block 60 | ``` 61 | 62 | ```{eval-rst} 63 | .. doxygenfunction:: wallet_alias_output_create 64 | ``` 65 | 66 | ```{eval-rst} 67 | .. doxygenfunction:: wallet_alias_output_state_transition 68 | ``` 69 | 70 | ```{eval-rst} 71 | .. doxygenfunction:: wallet_alias_output_destroy 72 | ``` 73 | 74 | ```{eval-rst} 75 | .. doxygenfunction:: wallet_basic_output_create 76 | ``` 77 | 78 | ```{eval-rst} 79 | .. doxygenfunction:: wallet_get_unspent_basic_output_ids 80 | ``` 81 | 82 | ```{eval-rst} 83 | .. doxygenfunction:: wallet_basic_output_send 84 | ``` 85 | 86 | ```{eval-rst} 87 | .. doxygenfunction:: wallet_foundry_output_mint_native_tokens 88 | ``` 89 | 90 | ## Mnemonic Sentence 91 | 92 | ```{eval-rst} 93 | .. doxygenenum:: ms_lan_t 94 | ``` 95 | 96 | ```{eval-rst} 97 | .. doxygenenum:: ms_entropy_t 98 | ``` 99 | 100 | ```{eval-rst} 101 | .. doxygenfunction:: mnemonic_to_seed 102 | ``` 103 | 104 | ```{eval-rst} 105 | .. doxygenfunction:: mnemonic_generator 106 | ``` 107 | 108 | ```{eval-rst} 109 | .. doxygenfunction:: mnemonic_encode 110 | ``` 111 | 112 | ```{eval-rst} 113 | .. doxygenfunction:: mnemonic_decode 114 | ``` 115 | 116 | ```{eval-rst} 117 | .. doxygenfunction:: mnemonic_convertor 118 | ``` 119 | 120 | ```{eval-rst} 121 | .. doxygenfunction:: mnemonic_validation 122 | ``` 123 | -------------------------------------------------------------------------------- /docs/arduino_esp32.md: -------------------------------------------------------------------------------- 1 | # Arduino-ESP32 Integration 2 | 3 | Developers are able to write IOTA client and wallet applications with [arduino-esp32](https://github.com/espressif/arduino-esp32) framework via the [Arduino Desktop IDE](https://www.arduino.cc/en/software) 4 | 5 | Please follow the installation document to setup the IDE on your system 6 | 7 | - [Install Arduino Desktop IDE](https://www.arduino.cc/en/Guide) 8 | - [Install Arduino-ESP32 Support](https://docs.espressif.com/projects/arduino-esp32/en/latest/installing.html) 9 | 10 | 11 | Once the desktop IDE and arduino-esp32 support are installed, you are ready to add IOTA Client library into the Arduino Libraries. 12 | 13 | There are two packages are required: 14 | 15 | - [iota.c](https://github.com/iotaledger/iota.c) 16 | - [uthash](https://github.com/oopsmonk/uthash) 17 | 18 | ## Import IOTA Client packages 19 | 20 | Choose one way which your preferred to import packages into the Arduino IDE. 21 | 22 | ### Download Packages From GitHub 23 | 24 | Download ZIP files from the website and save to a folder. 25 | 26 | ![](img/github_download_zip.png) 27 | 28 | Add packages into Arduino Libraries 29 | 30 | ![](img/arduino_include_zip.png) 31 | 32 | ### Clone Packages From GitHub 33 | 34 | Clone repositories into the Arduino Libraries folder, the folder is under the Sketchbook location can be found in the preferences settings. 35 | 36 | ![](img/arduino_preferences_sketchbook_location.png) 37 | 38 | In my case, it is `/home/sam/Arduino/libraries`. 39 | 40 | ```bash 41 | cd /home/same/Arduino/libraries 42 | git clone https://github.com/iotaledger/iota.c.git 43 | git clone https://github.com/oopsmonk/uthash.git 44 | ``` 45 | 46 | ### Import IOTA Client Library From Arduino Package Manager 47 | 48 | TODO 49 | 50 | ## Open Examples from IDE 51 | 52 | Once IOTA Client packages are imported to the Libraries folder, please restart Arduino IDE and you can find the examples in the IDE. 53 | 54 | ![](img/arduino_examples.png) 55 | 56 | -------------------------------------------------------------------------------- /docs/conf.py: -------------------------------------------------------------------------------- 1 | # Configuration file for the Sphinx documentation builder. 2 | # 3 | # This file only contains a selection of the most common options. For a full 4 | # list see the documentation: 5 | # https://www.sphinx-doc.org/en/master/usage/configuration.html 6 | 7 | # -- Path setup -------------------------------------------------------------- 8 | 9 | # If extensions (or modules to document with autodoc) are in another directory, 10 | # add these directories to sys.path here. If the directory is relative to the 11 | # documentation root, use os.path.abspath to make it absolute, like shown here. 12 | # 13 | import os, sys, subprocess 14 | sys.path.insert(0, os.path.abspath('.')) 15 | 16 | if os.environ.get('READTHEDOCS', None) == 'True': 17 | subprocess.call('doxygen') 18 | 19 | 20 | # -- Project information ----------------------------------------------------- 21 | 22 | project = 'IOTA C Client' 23 | copyright = '2022, IOTA Stiftung' 24 | author = 'Sam Chen' 25 | 26 | master_doc = "index" 27 | highlight_language = 'c' 28 | primary_domain = 'c' 29 | language = "en" 30 | 31 | # -- General configuration --------------------------------------------------- 32 | 33 | # Add any Sphinx extension module names here, as strings. They can be 34 | # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom 35 | # ones. 36 | extensions = ['myst_parser', 'breathe'] 37 | 38 | # Auto-generated header anchors 39 | myst_heading_anchors = 2 40 | 41 | # Add any paths that contain templates here, relative to this directory. 42 | templates_path = ['_templates'] 43 | 44 | # List of patterns, relative to source directory, that match files and 45 | # directories to ignore when looking for source files. 46 | # This pattern also affects html_static_path and html_extra_path. 47 | exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store'] 48 | 49 | 50 | # -- Options for HTML output ------------------------------------------------- 51 | 52 | # The theme to use for HTML and HTML Help pages. See the documentation for 53 | # a list of builtin themes. 54 | # 55 | html_theme = 'sphinx_book_theme' 56 | 57 | # Add any paths that contain custom static files (such as style sheets) here, 58 | # relative to this directory. They are copied after the builtin static files, 59 | # so a file named "default.css" will overwrite the builtin "default.css". 60 | html_static_path = ['_static'] 61 | 62 | ## myst-parser settings 63 | 64 | ## breathe settings 65 | 66 | breathe_default_project = 'iota.c' 67 | breathe_domain_by_extension = {'h' : 'c'} 68 | breathe_projects = { 'iota.c': './doxygen_build/xml/' } 69 | -------------------------------------------------------------------------------- /docs/examples.md: -------------------------------------------------------------------------------- 1 | # Examples 2 | 3 | See [iota.c/examples](https://github.com/iotaledger/iota.c/tree/develop/examples) 4 | -------------------------------------------------------------------------------- /docs/img/arduino_examples.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iotaledger-archive/iota.c/bdcaf8e4e704fe32d0e8ed6ab7b75a90126eb390/docs/img/arduino_examples.png -------------------------------------------------------------------------------- /docs/img/arduino_include_zip.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iotaledger-archive/iota.c/bdcaf8e4e704fe32d0e8ed6ab7b75a90126eb390/docs/img/arduino_include_zip.png -------------------------------------------------------------------------------- /docs/img/arduino_preferences_sketchbook_location.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iotaledger-archive/iota.c/bdcaf8e4e704fe32d0e8ed6ab7b75a90126eb390/docs/img/arduino_preferences_sketchbook_location.png -------------------------------------------------------------------------------- /docs/img/client_application_architecture.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iotaledger-archive/iota.c/bdcaf8e4e704fe32d0e8ed6ab7b75a90126eb390/docs/img/client_application_architecture.jpg -------------------------------------------------------------------------------- /docs/img/client_block_diagram.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iotaledger-archive/iota.c/bdcaf8e4e704fe32d0e8ed6ab7b75a90126eb390/docs/img/client_block_diagram.jpg -------------------------------------------------------------------------------- /docs/img/github_download_zip.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iotaledger-archive/iota.c/bdcaf8e4e704fe32d0e8ed6ab7b75a90126eb390/docs/img/github_download_zip.png -------------------------------------------------------------------------------- /docs/index.md: -------------------------------------------------------------------------------- 1 | # IOTA C Client API Reference 2 | 3 | ## Welcome 4 | 5 | This is an IOTA Client library for IOTA Shimmer network. 6 | Learn more about IOTA, please visit [IOTA WiKi](https://wiki.iota.org/). 7 | This C Client is still a highly development project for POSIX systems and embedded development, such as STM32, Nordic, Arduino, and ESP32 MCUs, the repository can be found in [iotaledger/iota.c](https://github.com/iotaledger/iota.c). 8 | 9 | 10 | ```{toctree} 11 | --- 12 | maxdepth: 2 13 | caption: IOTA C Client 14 | --- 15 | introduction.md 16 | examples.md 17 | arduino_esp32.md 18 | ``` 19 | 20 | ```{toctree} 21 | --- 22 | maxdepth: 1 23 | caption: API Reference 24 | --- 25 | api/wallet.md 26 | api/events.md 27 | api/restful.md 28 | api/core.md 29 | api/crypto.md 30 | ``` 31 | -------------------------------------------------------------------------------- /docs/introduction.md: -------------------------------------------------------------------------------- 1 | # Introduction 2 | 3 | The C Client library is built for embedded development and can be integrated to POSIX operating systems easily. 4 | 5 | It has integrated with Software Development Kits(SDK) and a STM32Cube expansion: 6 | * [esp32-client-sdk](https://github.com/iotaledger/esp32-client-sdk) - based on ESP-IDF for ESP32 series 7 | * [zephyr-client-sdk](https://github.com/iotaledger/zephyr-client-sdk) - based on ZephyrOS, supports hundreds of MCU out of the box, it works with nRF Connect SDK for Nordic microcontrollers as well. 8 | * [iota-mbed-studio](https://github.com/iotaledger/iota-mbed-studio) - based on ARM Mbed OS and [Mbed Studio IDE](https://os.mbed.com/studio/). 9 | * [X-CUBE-IOTA1](https://www.st.com/en/embedded-software/x-cube-iota1.html) - IOTA Distributed Ledger Technology software expansion for STM32Cube 10 | 11 | ## C Client Library Diagram 12 | 13 | The C Client library consists 4 abstraction layers: 14 | * Crypto - provides cryptographic functions 15 | * Core - implements components include address/block/UTXO... 16 | * Client - implements node REST APIs and Event APIs. (optional) 17 | * Wallet - implements simple wallet functions. (optional) 18 | 19 | As a client application, Client and Wallet modules could be an option as needed. For instance, the application can implement its own wallet logic or it uses the Core module to compose blocks then send blocks through another interface without the Client module. 20 | 21 | ![](img/client_block_diagram.jpg) 22 | 23 | The C Client library relies on some functionalities from the operating system API or external library: 24 | * HTTP/HTTPS Client 25 | * JSON parser 26 | * Crypto library 27 | * MQTT Client 28 | 29 | ## IOTA Application Architecture 30 | 31 | The real world application could be vary, here shows an example of an IOTA client application. 32 | 33 | ![](img/client_application_architecture.jpg) 34 | 35 | With this design, the application can interact with IOTA Tangle in order to: 36 | * Create data and transaction blocks 37 | * Send data and transaction blocks 38 | * Query blocks 39 | * Query the node status 40 | * Generate addresses 41 | * Subscribe to node events 42 | 43 | -------------------------------------------------------------------------------- /docs/make.bat: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | 3 | pushd %~dp0 4 | 5 | REM Command file for Sphinx documentation 6 | 7 | if "%SPHINXBUILD%" == "" ( 8 | set SPHINXBUILD=sphinx-build 9 | ) 10 | set SOURCEDIR=. 11 | set BUILDDIR=_build 12 | 13 | if "%1" == "" goto help 14 | 15 | %SPHINXBUILD% >NUL 2>NUL 16 | if errorlevel 9009 ( 17 | echo. 18 | echo.The 'sphinx-build' command was not found. Make sure you have Sphinx 19 | echo.installed, then set the SPHINXBUILD environment variable to point 20 | echo.to the full path of the 'sphinx-build' executable. Alternatively you 21 | echo.may add the Sphinx directory to PATH. 22 | echo. 23 | echo.If you don't have Sphinx installed, grab it from 24 | echo.http://sphinx-doc.org/ 25 | exit /b 1 26 | ) 27 | 28 | %SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% 29 | goto end 30 | 31 | :help 32 | %SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% 33 | 34 | :end 35 | popd 36 | -------------------------------------------------------------------------------- /docs/requirements.txt: -------------------------------------------------------------------------------- 1 | sphinx_book_theme 2 | breathe 3 | myst-parser 4 | -------------------------------------------------------------------------------- /examples/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | #[[ 2 | // Copyright 2020 IOTA Stiftung 3 | // SPDX-License-Identifier: Apache-2.0 4 | ]] 5 | 6 | # function for example cases 7 | function(add_iota_example example_name example_src) 8 | add_executable(${example_name} "${example_src}") 9 | set_target_properties(${example_name} PROPERTIES C_STANDARD_REQUIRED NO C_STANDARD 99) 10 | target_include_directories(${example_name} PRIVATE ${PROJECT_SOURCE_DIR}/src ${CMAKE_INSTALL_PREFIX}/include) 11 | target_compile_options(${example_name} PRIVATE -Wall -Wextra) 12 | if(IOTA_WALLET_ENABLE) 13 | add_dependencies(${example_name} iota_wallet) 14 | target_link_libraries(${example_name} PRIVATE iota_wallet) 15 | else() 16 | add_dependencies(${example_name} iota_client) 17 | target_link_libraries(${example_name} PRIVATE iota_client) 18 | endif() 19 | endfunction(add_iota_example) 20 | 21 | add_iota_example(encrypted_tagged_data_block "client/encrypted_tagged_data_block.c") 22 | add_iota_example(tagged_data_block "client/tagged_data_block.c") 23 | add_iota_example(get_block "client/get_block.c") 24 | add_iota_example(node_info "client/node_info.c") 25 | 26 | if(IOTA_WALLET_ENABLE) 27 | add_iota_example(send_basic_output "wallet/send_basic_output.c") 28 | add_iota_example(create_alias_output "wallet/create_alias_output.c") 29 | add_iota_example(mint_native_tokens "wallet/mint_native_tokens.c") 30 | add_iota_example(send_native_tokens "wallet/send_native_tokens.c") 31 | endif() 32 | 33 | if(MQTT_CLIENT_ENABLE) 34 | add_iota_example(get_event_blocks "client/get_event_blocks.c") 35 | endif() 36 | -------------------------------------------------------------------------------- /examples/README.md: -------------------------------------------------------------------------------- 1 | # IOTA C Client Examples 2 | 3 | This folder contains simple examples for developing IOTA client applications. 4 | For building example, please enable example option, `-DIOTA_EXAMPLES=TRUE`, during CMake configuration. 5 | 6 | * `arduino_esp32_info` - fetch node info with Arduino IDE 7 | * `arduino_esp32_token_transfer` - transfer IOTA tokens with Arduino IDE 8 | * Client - examples use client APIs 9 | * `encrypted_tagged_data_block` - sending encrypted data to the Tangle 10 | * `tagged_data_block` - sending data to the Tangle 11 | * `get_block` - getting Block object by a given BlockID 12 | * `node_info` - fetching node info from the connected node 13 | * `get_event_blocks` - subscript event by Even APIs 14 | * Wallet - examples use wallet APIs 15 | * `create_alias_output` - Creating an Alias output 16 | * `int_native_tokens` - Minting a Native tokens 17 | * `send_basic_output` - Sending IOTA tokens to a receiver 18 | * `send_native_tokens` - Minting a Native tokens and send it to a receiver 19 | 20 | -------------------------------------------------------------------------------- /examples/arduino_esp32_info/arduino_esp32_info.ino: -------------------------------------------------------------------------------- 1 | // Copyright 2022 IOTA Stiftung 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | /** 5 | * @brief A simple example of getting a node info. 6 | * 7 | */ 8 | 9 | #include 10 | #include 11 | 12 | #include 13 | 14 | // please set your WiFi SSID and Password 15 | const char* ssid = "xxxxx"; 16 | const char* passwd = "sssss"; 17 | 18 | // please set the API endpoint of the IOTA node 19 | const char* node_host = "localhost"; 20 | const uint16_t node_port = 14265; 21 | const bool node_use_tls = false; 22 | 23 | uint32_t chipId = 0; 24 | 25 | int fetch_node_info() { 26 | iota_client_conf_t ctx = {}; 27 | strcpy(ctx.host, node_host); 28 | ctx.port = node_port; 29 | ctx.use_tls = node_use_tls; 30 | 31 | res_node_info_t* info = res_node_info_new(); 32 | if (!info) { 33 | printf("Failed to create a response node info object!\n"); 34 | return -1; 35 | } 36 | 37 | if (get_node_info(&ctx, info) != 0) { 38 | printf("Retrieving node info failed!\n"); 39 | res_node_info_free(info); 40 | return -1; 41 | } 42 | 43 | if (info->is_error) { 44 | // got an error message from node. 45 | printf("Error: %s\n", info->u.error->msg); 46 | } else { 47 | node_info_print(info, 0); 48 | } 49 | 50 | res_node_info_free(info); 51 | return 0; 52 | } 53 | 54 | void setup() { 55 | Serial.begin(115200); 56 | delay(10); 57 | 58 | // connecting to WiFi 59 | WiFi.begin(ssid, passwd); 60 | 61 | while (WiFi.status() != WL_CONNECTED) { 62 | delay(500); 63 | Serial.print("."); 64 | } 65 | 66 | Serial.println(""); 67 | Serial.print("IP address: "); 68 | Serial.println(WiFi.localIP()); 69 | } 70 | 71 | void loop() { 72 | for (int i = 0; i < 17; i = i + 8) { 73 | chipId |= ((ESP.getEfuseMac() >> (40 - i)) & 0xff) << i; 74 | } 75 | 76 | delay(10000); 77 | Serial.printf("ESP32 Chip model = %s Rev %d\n", ESP.getChipModel(), ESP.getChipRevision()); 78 | Serial.printf("This chip has %d cores\n", ESP.getChipCores()); 79 | Serial.print("Chip ID: "); 80 | Serial.println(chipId); 81 | fetch_node_info(); 82 | } 83 | -------------------------------------------------------------------------------- /examples/client/get_block.c: -------------------------------------------------------------------------------- 1 | // Copyright 2021 IOTA Stiftung 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | /** 5 | * @brief A simple example of getting a block by its ID from the Tangle. 6 | * 7 | */ 8 | 9 | #include 10 | 11 | #include "client/api/restful/get_block.h" 12 | 13 | // replace this block ID as needed 14 | // Milestone 15 | #define BLK_ID "c0192ab155b501d2b51d4342b32970360d03835cce84f3b5a8c58e5f0c403b57" 16 | // Tagged Data 17 | //#define BLK_ID "6fc54c980a7a7480d4cb029c64e9a73eb1d4c3a1df40a297b607e1e137322142" 18 | // Transaction 19 | //#define BLK_ID "e95846e997dc6dae80e9a6dea908577a167b5e7c53b9fd802a760486a8c90d0f" 20 | 21 | int main(void) { 22 | iota_client_conf_t ctx = {.host = "localhost", .port = 14265, .use_tls = false}; 23 | 24 | res_block_t *blk = res_block_new(); 25 | if (!blk) { 26 | printf("Failed to create a response block object!\n"); 27 | return -1; 28 | } 29 | 30 | if (get_block_by_id(&ctx, (char const *)BLK_ID, blk) != 0) { 31 | printf("Retrieving block from a node failed!\n"); 32 | res_block_free(blk); 33 | return -1; 34 | } 35 | 36 | if (blk->is_error) { 37 | printf("API response: %s\n", blk->u.error->msg); 38 | res_block_free(blk); 39 | return -1; 40 | } 41 | 42 | switch (blk->u.blk->payload_type) { 43 | case CORE_BLOCK_PAYLOAD_MILESTONE: 44 | printf("Milestone block received:\n"); 45 | core_block_print(blk->u.blk, 0); 46 | break; 47 | case CORE_BLOCK_PAYLOAD_TAGGED: 48 | printf("Tagged Data block received:\n"); 49 | core_block_print(blk->u.blk, 0); 50 | break; 51 | case CORE_BLOCK_PAYLOAD_TRANSACTION: 52 | printf("Transaction block received:\n"); 53 | core_block_print(blk->u.blk, 0); 54 | break; 55 | default: 56 | printf("Unsupported type of a block received!\n"); 57 | break; 58 | } 59 | 60 | res_block_free(blk); 61 | 62 | return 0; 63 | } 64 | -------------------------------------------------------------------------------- /examples/client/node_info.c: -------------------------------------------------------------------------------- 1 | // Copyright 2021 IOTA Stiftung 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | /** 5 | * @brief A simple example of getting a node info. 6 | * 7 | */ 8 | 9 | #include 10 | 11 | #include "client/api/restful/get_node_info.h" 12 | 13 | int main(void) { 14 | iota_client_conf_t ctx = {.host = "localhost", .port = 14265, .use_tls = false}; 15 | 16 | res_node_info_t *info = res_node_info_new(); 17 | if (!info) { 18 | printf("Failed to create a response node info object!\n"); 19 | return -1; 20 | } 21 | 22 | if (get_node_info(&ctx, info) != 0) { 23 | printf("Retrieving node info failed!\n"); 24 | res_node_info_free(info); 25 | return -1; 26 | } 27 | 28 | if (info->is_error) { 29 | // got an error message from node. 30 | printf("Error: %s\n", info->u.error->msg); 31 | } else { 32 | node_info_print(info, 0); 33 | } 34 | 35 | res_node_info_free(info); 36 | 37 | return 0; 38 | } 39 | -------------------------------------------------------------------------------- /examples/client/tagged_data_block.c: -------------------------------------------------------------------------------- 1 | // Copyright 2021 IOTA Stiftung 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | /** 5 | * @brief A simple example of sending a data to the Tangle. 6 | * 7 | */ 8 | 9 | #include 10 | #include 11 | 12 | #include "client/api/restful/get_block.h" 13 | #include "client/api/restful/send_tagged_data.h" 14 | #include "core/models/payloads/tagged_data.h" 15 | #include "core/utils/iota_str.h" 16 | 17 | #define TAG "iota.c\xF0\x9F\xA6\x8B" 18 | #define MESSAGE "Hello world" 19 | 20 | int main(void) { 21 | iota_client_conf_t ctx = {.host = "localhost", .port = 14265, .use_tls = false}; 22 | 23 | res_send_block_t res = {0}; 24 | 25 | // send Hello world to the Tangle 26 | printf("Sending data block to the Tangle...\n"); 27 | if (send_tagged_data_block(&ctx, 2, (byte_t *)TAG, strlen(TAG), (byte_t *)MESSAGE, strlen(MESSAGE), &res) == 0) { 28 | if (res.is_error) { 29 | printf("API response: %s\n", res.u.error->msg); 30 | return -1; 31 | } 32 | } else { 33 | printf("Sending block failed!\n"); 34 | return -1; 35 | } 36 | 37 | printf("Block successfully sent.\n"); 38 | printf("Block ID: %s\n", res.u.blk_id); 39 | 40 | res_block_t *blk = res_block_new(); 41 | if (!blk) { 42 | printf("Failed to create a response block object!\n"); 43 | return -1; 44 | } 45 | 46 | // fetch block from the Tangle 47 | printf("Fetching block from the Tangle...\n"); 48 | if (get_block_by_id(&ctx, res.u.blk_id, blk) == 0) { 49 | if (blk->is_error) { 50 | printf("API response: %s\n", blk->u.error->msg); 51 | res_block_free(blk); 52 | return -1; 53 | } 54 | } else { 55 | printf("Fetching block from a node failed!\n"); 56 | res_block_free(blk); 57 | return -1; 58 | } 59 | 60 | printf("Block successfully fetched.\n"); 61 | 62 | // check if fetched block is Tagged Data block 63 | if (blk->u.blk->payload_type != CORE_BLOCK_PAYLOAD_TAGGED) { 64 | printf("Fetched block is not a Tagged Data block!\n"); 65 | res_block_free(blk); 66 | return -1; 67 | } 68 | 69 | // Convert byte arrays to a strings 70 | if (!byte_buf2str(((tagged_data_payload_t *)blk->u.blk->payload)->tag)) { 71 | printf("Failed to convert byte array to a string!\n"); 72 | res_block_free(blk); 73 | return -1; 74 | } 75 | if (!byte_buf2str(((tagged_data_payload_t *)blk->u.blk->payload)->data)) { 76 | printf("Failed to convert byte array to a string!\n"); 77 | res_block_free(blk); 78 | return -1; 79 | } 80 | 81 | // print fetched block 82 | printf("Tagged Data:\n"); 83 | printf("\tTag: %s\n", ((tagged_data_payload_t *)blk->u.blk->payload)->tag->data); 84 | printf("\tData: %s\n", ((tagged_data_payload_t *)blk->u.blk->payload)->data->data); 85 | 86 | // clean up resources 87 | res_block_free(blk); 88 | 89 | return 0; 90 | } 91 | -------------------------------------------------------------------------------- /functional-tests/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | if(IOTA_WALLET_ENABLE) 2 | 3 | add_executable(functional-tests "functional_app.c" "functional_cases.c") 4 | 5 | set_target_properties(functional-tests PROPERTIES C_STANDARD_REQUIRED NO C_STANDARD 99) 6 | 7 | target_include_directories(functional-tests PRIVATE "${PROJECT_SOURCE_DIR}/src" "${CMAKE_INSTALL_PREFIX}/include" 8 | "${CMAKE_INSTALL_PREFIX}/include/cjson") 9 | 10 | add_custom_command( 11 | TARGET functional-tests 12 | POST_BUILD 13 | COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_SOURCE_DIR}/functional-tests/config.json 14 | ${CMAKE_CURRENT_BINARY_DIR}/config.json) 15 | 16 | add_dependencies(functional-tests iota_wallet) 17 | target_link_libraries(functional-tests PRIVATE iota_wallet) 18 | endif() 19 | -------------------------------------------------------------------------------- /functional-tests/README.md: -------------------------------------------------------------------------------- 1 | # Functional Test Application 2 | 3 | The `functional-tests` is an application which test the functionality of iota.c by interacting with the IOTA network. 4 | 5 | # Usage 6 | 7 | Make sure `IOTA_TESTS` and `IOTA_WALLET_ENABLE` is enabled during CMake configuration, for example: 8 | 9 | ``` 10 | git clone https://github.com/iotaledger/iota.c.git 11 | cd iota.c 12 | mkdir build && cd build 13 | cmake -DIOTA_TESTS=TRUE -DIOTA_WALLET_ENABLE=TRUE -DCryptoUse=libsodium -DCMAKE_INSTALL_PREFIX=$PWD .. 14 | make -j8 15 | ``` 16 | 17 | After build without problems the application is in `build/functional-tests` folder. 18 | 19 | ``` 20 | cd functional-tests 21 | ./functional-tests ./config.json 22 | ``` 23 | 24 | -------------------------------------------------------------------------------- /functional-tests/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "mnemonic": "acoustic trophy damage hint search taste love bicycle foster cradle brown govern endless depend situate athlete pudding blame question genius transfer van random vast", 3 | "sender_index": 0, 4 | "receiver_index": 1, 5 | "node":"localhost", 6 | "port": 14265, 7 | "use_tls": false, 8 | "faucet":"localhost", 9 | "faucet_port": 8091, 10 | "faucet_use_tls": false, 11 | "show_payload": true, 12 | "coin_type": 1, 13 | "delay": 10 14 | } 15 | -------------------------------------------------------------------------------- /iota-c.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iotaledger-archive/iota.c/bdcaf8e4e704fe32d0e8ed6ab7b75a90126eb390/iota-c.png -------------------------------------------------------------------------------- /library.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "iota_client", 3 | "version": "0.0.2", 4 | "keywords": "crypto, iota, client", 5 | "description": "IOTA C client library", 6 | "repository": { 7 | "type": "git", 8 | "url": "https://github.com/iotaledger/iota.c.git", 9 | "branch": "dev" 10 | }, 11 | "authors": { 12 | "name": "Sam Chen", 13 | "email": "sam.chen@iota.org", 14 | "maintainer": true 15 | }, 16 | "frameworks": "*", 17 | "platforms": "espressif32" 18 | } 19 | -------------------------------------------------------------------------------- /library.properties: -------------------------------------------------------------------------------- 1 | name=IOTA ESP32 Client 2 | version=1.0.1 3 | author=Sam Chen , Rabin Muhammed , Matjaz Verbole 4 | maintainer=Sam Chen 5 | sentence=The IOTA client library for arduino-esp32 6 | paragraph=Communicating with IOTA node software, sending trandactions to the Tangle. 7 | category=Communication 8 | url=https://github.com/iotaledger/iota.c 9 | architectures=esp32 10 | includes=iota_client.h 11 | depends=uthash 12 | -------------------------------------------------------------------------------- /src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | #[[ 2 | // Copyright 2020 IOTA Stiftung 3 | // SPDX-License-Identifier: Apache-2.0 4 | ]] 5 | 6 | if(IOTA_WALLET_ENABLE) 7 | add_subdirectory(wallet) 8 | endif(IOTA_WALLET_ENABLE) 9 | 10 | if(WITH_IOTA_CLIENT) 11 | add_subdirectory(client) 12 | endif() 13 | 14 | if(WITH_IOTA_CORE) 15 | add_subdirectory(core) 16 | endif() 17 | 18 | add_subdirectory(crypto) 19 | -------------------------------------------------------------------------------- /src/client/api/events/sub_blocks_metadata.c: -------------------------------------------------------------------------------- 1 | // Copyright 2021 IOTA Stiftung 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | #include 5 | 6 | #include "client/api/events/sub_blocks_metadata.h" 7 | #include "client/api/json_parser/json_utils.h" 8 | #include "client/constants.h" 9 | #include "client/network/mqtt/mqtt.h" 10 | 11 | int event_subscribe_blk_metadata(event_client_handle_t client, int *mid, char const blk_id[], int qos) { 12 | if (strlen(blk_id) != BIN_TO_HEX_BYTES(IOTA_BLOCK_ID_BYTES)) { 13 | printf("[%s:%d]: Block ID length is invalid\n", __func__, __LINE__); 14 | return -1; 15 | } 16 | // Buffer to store topic string : block-metadata/0x{blockid} 17 | char topic_buff[BIN_TO_HEX_BYTES(IOTA_BLOCK_ID_BYTES) + 20] = {0}; 18 | // Prepare topic string 19 | sprintf(topic_buff, "block-metadata/0x%s", blk_id); 20 | // Call to MQTT network layer 21 | return event_subscribe(client, mid, topic_buff, qos); 22 | } 23 | -------------------------------------------------------------------------------- /src/client/api/events/sub_blocks_metadata.h: -------------------------------------------------------------------------------- 1 | // Copyright 2021 IOTA Stiftung 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | #ifndef __SUB_BLOCKS_METADATA_H__ 5 | #define __SUB_BLOCKS_METADATA_H__ 6 | 7 | #include 8 | #include 9 | 10 | #include "client/api/events/node_event.h" 11 | #include "core/models/block.h" 12 | #include "core/utils/macros.h" 13 | 14 | #ifdef __cplusplus 15 | extern "C" { 16 | #endif 17 | 18 | /** 19 | * @brief Subscribes block-metadata/{blockid} event 20 | * 21 | * @param[in] client The event client instance 22 | * @param[out] mid If not NULL, mid will return the message id of the topic subscription 23 | * @param[in] msg_id A message id for the event 24 | * @param[in] qos A QoS level for the topic 25 | * @return int 0 If Success 26 | */ 27 | int event_subscribe_blk_metadata(event_client_handle_t client, int *mid, char const msg_id[], int qos); 28 | 29 | #ifdef __cplusplus 30 | } 31 | #endif 32 | 33 | #endif 34 | -------------------------------------------------------------------------------- /src/client/api/events/sub_milestone_payload.c: -------------------------------------------------------------------------------- 1 | // Copyright 2021 IOTA Stiftung 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | #include 5 | 6 | #include "client/api/events/sub_milestone_payload.h" 7 | #include "client/api/json_parser/json_utils.h" 8 | #include "client/network/mqtt/mqtt.h" 9 | 10 | int parse_milestone_payload(char *data, events_milestone_payload_t *res) { 11 | if (res == NULL) { 12 | printf("[%s:%d] invalid parameters\n", __func__, __LINE__); 13 | return -1; 14 | } 15 | 16 | cJSON *json_obj = cJSON_Parse((char *)data); 17 | if (json_obj == NULL) { 18 | printf("[%s:%d] OOM\n", __func__, __LINE__); 19 | return -1; 20 | } 21 | 22 | // Parse index 23 | if (json_get_uint32(json_obj, JSON_KEY_MILESTONE_INDEX, &(res->index)) != 0) { 24 | printf("[%s:%d]: parse %s failed\n", __func__, __LINE__, JSON_KEY_INDEX); 25 | return -1; 26 | } 27 | 28 | // Parse timestamp 29 | if (json_get_uint32(json_obj, JSON_KEY_MILESTONE_TIMESTAMP, &(res->timestamp)) != 0) { 30 | printf("[%s:%d]: parse %s failed\n", __func__, __LINE__, JSON_KEY_TIMESTAMP); 31 | return -1; 32 | } 33 | 34 | // parsing last milestone ID 35 | if (json_get_hex_str_to_bin(json_obj, JSON_KEY_MILESTONE_ID, res->milestone_id, sizeof(res->milestone_id)) != 0) { 36 | printf("[%s:%d]: parsing %s hex string failed\n", __func__, __LINE__, JSON_KEY_MILESTONE_ID); 37 | return -1; 38 | } 39 | 40 | cJSON_Delete(json_obj); 41 | return 0; 42 | } 43 | -------------------------------------------------------------------------------- /src/client/api/events/sub_milestone_payload.h: -------------------------------------------------------------------------------- 1 | // Copyright 2021 IOTA Stiftung 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | #ifndef __SUB_MILESTONE_LATEST_H__ 5 | #define __SUB_MILESTONE_LATEST_H__ 6 | 7 | #include 8 | #include 9 | 10 | #include "core/utils/byte_buffer.h" 11 | #include "crypto/iota_crypto.h" 12 | 13 | /** 14 | * @brief Stores timestamp and index 15 | * 16 | */ 17 | typedef struct { 18 | uint32_t timestamp; ///< The timestamp of milestone payload 19 | uint32_t index; ///< The index of milestone payload 20 | byte_t milestone_id[CRYPTO_BLAKE2B_256_HASH_BYTES]; ///< The milestone id 21 | } events_milestone_payload_t; 22 | 23 | #ifdef __cplusplus 24 | extern "C" { 25 | #endif 26 | 27 | /** 28 | * @brief Parse milestone payload response 29 | * @param[in] data Response data to parse 30 | * @param[out] res Parsed response object 31 | * @return int 0 If success 32 | */ 33 | int parse_milestone_payload(char *data, events_milestone_payload_t *res); 34 | 35 | #ifdef __cplusplus 36 | } 37 | #endif 38 | 39 | #endif -------------------------------------------------------------------------------- /src/client/api/events/sub_serialized_output.c: -------------------------------------------------------------------------------- 1 | // Copyright 2021 IOTA Stiftung 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | #include 5 | 6 | #include "client/api/events/sub_serialized_output.h" 7 | #include "core/address.h" 8 | #include "core/models/payloads/tagged_data.h" 9 | #include "core/utils/macros.h" 10 | 11 | int event_sub_txn_included_blk(event_client_handle_t client, int *mid, char const transaction_id[], int qos) { 12 | if (strlen(transaction_id) != BIN_TO_HEX_BYTES(IOTA_TRANSACTION_ID_BYTES)) { 13 | printf("[%s:%d]: Transaction id length is invalid\n", __func__, __LINE__); 14 | return -1; 15 | } 16 | // buffer for holding string "transactions/0x{transactionId}/included-block" 17 | char topic_buff[31 + BIN_TO_HEX_BYTES(IOTA_TRANSACTION_ID_BYTES)] = {0}; 18 | 19 | sprintf(topic_buff, "transactions/0x%s/included-block", transaction_id); 20 | 21 | return event_subscribe(client, mid, topic_buff, qos); 22 | } 23 | 24 | int event_sub_tx_blk_tagged_data(event_client_handle_t client, int *mid, byte_t tag[], uint8_t tag_len, int qos) { 25 | if (tag_len > TAGGED_DATA_TAG_MAX_LENGTH_BYTES) { 26 | printf("[%s:%d]: Tag length is invalid\n", __func__, __LINE__); 27 | return -1; 28 | } 29 | // 34 is the max length for string blocks/transaction/tagged-data/0x, max hex-encoded-tag is 128 30 | char topic_buff[34 + BIN_TO_HEX_BYTES(TAGGED_DATA_TAG_MAX_LENGTH_BYTES)] = {0}; 31 | 32 | // hex encoded tag string 33 | char tag_str[BIN_TO_HEX_STR_BYTES(TAGGED_DATA_TAG_MAX_LENGTH_BYTES)] = {0}; 34 | if (bin_2_hex(tag, tag_len, NULL, tag_str, sizeof(tag_str)) != 0) { 35 | printf("[%s:%d] bin to hex tag conversion failed\n", __func__, __LINE__); 36 | return -1; 37 | } 38 | 39 | sprintf(topic_buff, "blocks/transaction/tagged-data/0x%s", tag_str); 40 | 41 | return event_subscribe(client, mid, topic_buff, qos); 42 | } 43 | 44 | int event_sub_blk_tagged_data(event_client_handle_t client, int *mid, byte_t tag[], uint8_t tag_len, int qos) { 45 | if (tag_len > TAGGED_DATA_TAG_MAX_LENGTH_BYTES) { 46 | printf("[%s:%d]: Tag length is invalid\n", __func__, __LINE__); 47 | return -1; 48 | } 49 | 50 | // hex encoded tag string 51 | char tag_str[BIN_TO_HEX_STR_BYTES(TAGGED_DATA_TAG_MAX_LENGTH_BYTES)] = {0}; 52 | if (bin_2_hex(tag, tag_len, NULL, tag_str, sizeof(tag_str)) != 0) { 53 | printf("[%s:%d] bin to hex tag conversion failed\n", __func__, __LINE__); 54 | return -1; 55 | } 56 | 57 | // 22 is the max length for string blocks/tagged-data/0x, max hex-encoded-tag is 128 58 | char topic_buff[22 + BIN_TO_HEX_BYTES(TAGGED_DATA_TAG_MAX_LENGTH_BYTES)] = {0}; 59 | sprintf(topic_buff, "%s/0x%s", TOPIC_BLK_TAGGED_DATA, tag_str); 60 | 61 | return event_subscribe(client, mid, topic_buff, qos); 62 | } 63 | 64 | int event_unsub_blk_tagged_data(event_client_handle_t client, int *mid, byte_t tag[], uint8_t tag_len) { 65 | if (tag_len > TAGGED_DATA_TAG_MAX_LENGTH_BYTES) { 66 | printf("[%s:%d]: Tag length is invalid\n", __func__, __LINE__); 67 | return -1; 68 | } 69 | 70 | // hex encoded tag string 71 | char tag_str[BIN_TO_HEX_STR_BYTES(TAGGED_DATA_TAG_MAX_LENGTH_BYTES)] = {0}; 72 | if (bin_2_hex(tag, tag_len, NULL, tag_str, sizeof(tag_str)) != 0) { 73 | printf("[%s:%d] bin to hex tag conversion failed\n", __func__, __LINE__); 74 | return -1; 75 | } 76 | 77 | // 22 is the max length for string blocks/tagged-data/0x, max hex-encoded-tag is 128 78 | char topic_buff[22 + BIN_TO_HEX_BYTES(TAGGED_DATA_TAG_MAX_LENGTH_BYTES)] = {0}; 79 | sprintf(topic_buff, "%s/0x%s", TOPIC_BLK_TAGGED_DATA, tag_str); 80 | 81 | return event_unsubscribe(client, mid, topic_buff); 82 | } 83 | -------------------------------------------------------------------------------- /src/client/api/events/sub_serialized_output.h: -------------------------------------------------------------------------------- 1 | // Copyright 2021 IOTA Stiftung 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | #ifndef __SUB_SERIALIZED_OUTPUT_H__ 5 | #define __SUB_SERIALIZED_OUTPUT_H__ 6 | 7 | #include "client/api/events/node_event.h" 8 | #include "core/utils/byte_buffer.h" 9 | 10 | #ifdef __cplusplus 11 | extern "C" { 12 | #endif 13 | 14 | /** 15 | * @brief Subscribes transactions/{transactionId}/included_block topic 16 | * 17 | * @param[in] client The event client object 18 | * @param[out] mid If not NULL, mid will return the message id of the topic subscription 19 | * @param[in] transaction_id A transaction id 20 | * @param[in] qos The QoS level for the topic 21 | * @return int 0 If success 22 | */ 23 | int event_sub_txn_included_blk(event_client_handle_t client, int *mid, char const transaction_id[], int qos); 24 | 25 | /** 26 | * @brief Subscribes blocks/transaction/tagged-data/{tag} topic for receiving transaction blocks with {tag} 27 | * 28 | * @param[in] client The event client object 29 | * @param[in] mid If not NULL, mid will return the message id of the topic subscription 30 | * @param[in] tag A tag to get transaction blocks 31 | * @param[in] tag_len The length of the tag in bytes 32 | * @param[in] qos The QoS level for the topic 33 | * @return int 0 If success 34 | */ 35 | int event_sub_tx_blk_tagged_data(event_client_handle_t client, int *mid, byte_t tag[], uint8_t tag_len, int qos); 36 | 37 | /** 38 | * @brief Subscribes blocks/tagged-data/{tag} topic for receiving blocks with {tag} 39 | * 40 | * @param[in] client The event client object 41 | * @param[in] mid If not NULL, mid will return the message id of the topic subscription 42 | * @param[in] tag A tag to get blocks 43 | * @param[in] tag_len The length of the tag in bytes 44 | * @param[in] qos The QoS level for the topic 45 | * @return int 0 If success 46 | */ 47 | int event_sub_blk_tagged_data(event_client_handle_t client, int *mid, byte_t tag[], uint8_t tag_len, int qos); 48 | 49 | /** 50 | * @brief Unsubscribes blocks/tagged-data/{tag} topic for receiving blocks with {tag} 51 | * 52 | * @param[in] client The event client object 53 | * @param[in] mid If not NULL, mid will return the message id of the topic subscription 54 | * @param[in] tag A tag to get blocks 55 | * @param[in] tag_len The length of the tag in bytes 56 | * @return int 0 If success 57 | */ 58 | int event_unsub_blk_tagged_data(event_client_handle_t client, int *mid, byte_t tag[], uint8_t tag_len); 59 | 60 | #ifdef __cplusplus 61 | } 62 | #endif 63 | 64 | #endif 65 | -------------------------------------------------------------------------------- /src/client/api/json_parser/block.h: -------------------------------------------------------------------------------- 1 | // Copyright 2022 IOTA Stiftung 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | #ifndef __CLIENT_API_JSON_PARSER_BLOCK_H__ 5 | #define __CLIENT_API_JSON_PARSER_BLOCK_H__ 6 | 7 | #include "cJSON.h" 8 | #include "core/models/block.h" 9 | 10 | #ifdef __cplusplus 11 | extern "C" { 12 | #endif 13 | 14 | /** 15 | * @brief Deserialize a JSON object to block 16 | * 17 | * @param[in] json_obj A JSON object 18 | * @param[out] blk The output block object 19 | * @return int 0 on success 20 | */ 21 | int json_block_deserialize(cJSON* json_obj, core_block_t* blk); 22 | 23 | /** 24 | * @brief Serialize a block to JSON object 25 | * 26 | * @param[in] blk A block object 27 | * @return cJSON* NULL on errors 28 | */ 29 | cJSON* json_block_serialize(core_block_t* blk); 30 | 31 | #ifdef __cplusplus 32 | } 33 | #endif 34 | 35 | #endif // __CLIENT_API_JSON_PARSER_BLOCK_H__ 36 | -------------------------------------------------------------------------------- /src/client/api/json_parser/common.h: -------------------------------------------------------------------------------- 1 | // Copyright 2022 IOTA Stiftung 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | #ifndef __CLIENT_API_JSON_PARSER_COMMON_H__ 5 | #define __CLIENT_API_JSON_PARSER_COMMON_H__ 6 | 7 | #include "client/api/json_parser/json_utils.h" 8 | #include "core/address.h" 9 | 10 | #ifdef __cplusplus 11 | extern "C" { 12 | #endif 13 | 14 | /** 15 | * @brief Deserialize JSON address data to address object 16 | * 17 | * @param[in] json_obj JSON object 18 | * @param[in] json_address_key JSON key for address 19 | * @param[out] address Deserialized address 20 | * @return int 0 on success 21 | */ 22 | int json_parser_common_address_deserialize(cJSON *json_obj, char const *const json_address_key, address_t *address); 23 | 24 | /** 25 | * @brief Serialize An address to JSON object 26 | * 27 | * @param[in] address An address object 28 | * @return cJSON* NULL on error 29 | */ 30 | cJSON *json_parser_common_address_serialize(address_t *address); 31 | 32 | #ifdef __cplusplus 33 | } 34 | #endif 35 | 36 | #endif // __CLIENT_API_JSON_PARSER_COMMON_H__ 37 | -------------------------------------------------------------------------------- /src/client/api/json_parser/inputs/inputs.h: -------------------------------------------------------------------------------- 1 | // Copyright 2022 IOTA Stiftung 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | #ifndef __CLIENT_API_JSON_PARSER_INPUTS_INPUTS_H__ 5 | #define __CLIENT_API_JSON_PARSER_INPUTS_INPUTS_H__ 6 | 7 | #include "client/api/json_parser/json_utils.h" 8 | #include "core/models/payloads/transaction.h" 9 | 10 | #ifdef __cplusplus 11 | extern "C" { 12 | #endif 13 | 14 | /** 15 | * @brief Deserialize JSON data to an utxo input list object 16 | * 17 | * @param[in] inputs_obj inputs JSON object 18 | * @param[out] inputs An utxo input list 19 | * @return int 0 on success 20 | */ 21 | int json_inputs_deserialize(cJSON* inputs_obj, utxo_inputs_list_t** inputs); 22 | 23 | /** 24 | * @brief Serialize input list to JSON object 25 | * 26 | * @param[in] inputs An input list object 27 | * @return cJSON* NULL on errors 28 | */ 29 | cJSON* json_inputs_serialize(utxo_inputs_list_t* inputs); 30 | 31 | #ifdef __cplusplus 32 | } 33 | #endif 34 | 35 | #endif // __CLIENT_API_JSON_PARSER_INPUTS_INPUTS_H__ 36 | -------------------------------------------------------------------------------- /src/client/api/json_parser/outputs/features.h: -------------------------------------------------------------------------------- 1 | // Copyright 2022 IOTA Stiftung 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | #ifndef __CLIENT_API_JSON_PARSER_OUTPUTS_FEATURES_H__ 5 | #define __CLIENT_API_JSON_PARSER_OUTPUTS_FEATURES_H__ 6 | 7 | #include "client/api/json_parser/json_utils.h" 8 | #include "core/models/outputs/features.h" 9 | 10 | #ifdef __cplusplus 11 | extern "C" { 12 | #endif 13 | 14 | /** 15 | * @brief Deserialize JSON sender feature to feature object 16 | * 17 | * @param[in] feat_obj Feature JSON object 18 | * @param[out] feat_list Features list object 19 | * @return int 0 on success 20 | */ 21 | int json_feat_sender_deserialize(cJSON *feat_obj, feature_list_t **feat_list); 22 | 23 | /** 24 | * @brief Deserialize JSON issuer feature to feature object 25 | * 26 | * @param[in] feat_obj Feature JSON object 27 | * @param[out] feat_list Features list object 28 | * @return int 0 on success 29 | */ 30 | int json_feat_issuer_deserialize(cJSON *feat_obj, feature_list_t **feat_list); 31 | 32 | /** 33 | * @brief Deserialize JSON metadata feature to feature object 34 | * 35 | * @param[in] feat_obj Feature JSON object 36 | * @param[out] feat_list Features list object 37 | * @return int 0 on success 38 | */ 39 | int json_feat_metadata_deserialize(cJSON *feat_obj, feature_list_t **feat_list); 40 | 41 | /** 42 | * @brief Deserialize JSON tag feature to feature object 43 | * 44 | * @param[in] feat_obj Feature JSON object 45 | * @param[out] feat_list Features list object 46 | * @return int 0 on success 47 | */ 48 | int json_feat_tag_deserialize(cJSON *feat_obj, feature_list_t **feat_list); 49 | 50 | /** 51 | * @brief Deserialize JSON data to features list object 52 | * 53 | * @param[in] output_obj Output JSON object 54 | * @param[in] immutable Flag which indicates if feature is immutable 55 | * @param[out] feat_list Features list object 56 | * @return int 0 on success 57 | */ 58 | int json_features_deserialize(cJSON *output_obj, bool immutable, feature_list_t **feat_list); 59 | 60 | /** 61 | * @brief Serialize a feature list 62 | * 63 | * @param[in] feat_list A feature list 64 | * @return cJSON* NULL on errors 65 | */ 66 | cJSON *json_features_serialize(feature_list_t *feat_list); 67 | 68 | #ifdef __cplusplus 69 | } 70 | #endif 71 | 72 | #endif // __CLIENT_API_JSON_PARSER_OUTPUTS_FEAT_BLOCKS_H__ 73 | -------------------------------------------------------------------------------- /src/client/api/json_parser/outputs/native_tokens.h: -------------------------------------------------------------------------------- 1 | // Copyright 2022 IOTA Stiftung 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | #ifndef __CLIENT_API_JSON_PARSER_OUTPUTS_NATIVE_TOKENS_H__ 5 | #define __CLIENT_API_JSON_PARSER_OUTPUTS_NATIVE_TOKENS_H__ 6 | 7 | #include "client/api/json_parser/json_utils.h" 8 | #include "core/models/outputs/native_tokens.h" 9 | 10 | #ifdef __cplusplus 11 | extern "C" { 12 | #endif 13 | 14 | /** 15 | * @brief Deserialize JSON data to native tokens object 16 | * 17 | * @param[in] output_obj Output JSON object 18 | * @param[out] native_tokens Transaction Native Tokens object 19 | * @return int 0 on success 20 | */ 21 | int json_native_tokens_deserialize(cJSON *output_obj, native_tokens_list_t **native_tokens); 22 | 23 | /** 24 | * @brief Serialize native tokens 25 | * 26 | * @param[in] native_tokens 27 | * @return cJSON* NULL on errors 28 | */ 29 | cJSON *json_native_tokens_serialize(native_tokens_list_t *native_tokens); 30 | 31 | #ifdef __cplusplus 32 | } 33 | #endif 34 | 35 | #endif // __CLIENT_API_JSON_PARSER_OUTPUTS_NATIVE_TOKENS_H__ 36 | -------------------------------------------------------------------------------- /src/client/api/json_parser/outputs/output_alias.h: -------------------------------------------------------------------------------- 1 | // Copyright 2022 IOTA Stiftung 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | #ifndef __CLIENT_API_JSON_PARSER_OUTPUTS_OUTPUT_ALIAS_H__ 5 | #define __CLIENT_API_JSON_PARSER_OUTPUTS_OUTPUT_ALIAS_H__ 6 | 7 | #include "client/api/json_parser/json_utils.h" 8 | #include "core/models/outputs/output_alias.h" 9 | 10 | #ifdef __cplusplus 11 | extern "C" { 12 | #endif 13 | 14 | /** 15 | * @brief Deserialize JSON data to output alias object 16 | * 17 | * @param[in] output_obj An output JSON object 18 | * @param[out] alias A new alias object 19 | * @return int 0 on success 20 | */ 21 | int json_output_alias_deserialize(cJSON *output_obj, output_alias_t **alias); 22 | 23 | /** 24 | * @brief Serialize Alias output to JSON object 25 | * 26 | * @param[in] alias An alias output object 27 | * @return cJSON* NULL on errors 28 | */ 29 | cJSON *json_output_alias_serialize(output_alias_t *alias); 30 | 31 | #ifdef __cplusplus 32 | } 33 | #endif 34 | 35 | #endif // __CLIENT_API_JSON_PARSER_OUTPUTS_OUTPUT_ALIAS_H__ 36 | -------------------------------------------------------------------------------- /src/client/api/json_parser/outputs/output_basic.h: -------------------------------------------------------------------------------- 1 | // Copyright 2022 IOTA Stiftung 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | #ifndef __CLIENT_API_JSON_PARSER_OUTPUTS_OUTPUT_BASIC_H__ 5 | #define __CLIENT_API_JSON_PARSER_OUTPUTS_OUTPUT_BASIC_H__ 6 | 7 | #include "client/api/json_parser/json_utils.h" 8 | #include "core/models/outputs/output_basic.h" 9 | 10 | #ifdef __cplusplus 11 | extern "C" { 12 | #endif 13 | 14 | /** 15 | * @brief Deserialize JSON data to output basic object 16 | * 17 | * @param[in] output_obj An output JSON object 18 | * @param[out] basic A new basic object 19 | * @return int 0 on success 20 | */ 21 | int json_output_basic_deserialize(cJSON* output_obj, output_basic_t** basic); 22 | 23 | /** 24 | * @brief Serialize basic output to JSON object 25 | * 26 | * @param basic An basic output 27 | * @return cJSON* NULL on errors 28 | */ 29 | cJSON* json_output_basic_serialize(output_basic_t* basic); 30 | 31 | #ifdef __cplusplus 32 | } 33 | #endif 34 | 35 | #endif // __CLIENT_API_JSON_PARSER_OUTPUTS_OUTPUT_BASIC_H__ 36 | -------------------------------------------------------------------------------- /src/client/api/json_parser/outputs/output_foundry.h: -------------------------------------------------------------------------------- 1 | // Copyright 2022 IOTA Stiftung 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | #ifndef __CLIENT_API_JSON_PARSER_OUTPUTS_OUTPUT_FOUNDRY_H__ 5 | #define __CLIENT_API_JSON_PARSER_OUTPUTS_OUTPUT_FOUNDRY_H__ 6 | 7 | #include "client/api/json_parser/json_utils.h" 8 | #include "core/models/outputs/output_foundry.h" 9 | 10 | #ifdef __cplusplus 11 | extern "C" { 12 | #endif 13 | 14 | /** 15 | * @brief Deserialize a JSON token scheme object 16 | * 17 | * @param[in] output_obj Output JSON object 18 | * @param[out] token_scheme A token scheme object 19 | * @return int 0 on success 20 | */ 21 | int json_token_scheme_deserialize(cJSON *output_obj, token_scheme_t **token_scheme); 22 | 23 | /** 24 | * @brief Serialize token scheme 25 | * 26 | * @param[in] scheme A token scheme object 27 | * @return cJSON* NULL on errors 28 | */ 29 | cJSON *json_token_scheme_serialize(token_scheme_t *scheme); 30 | 31 | /** 32 | * @brief Deserialize JSON data to output foundry object 33 | * 34 | * @param[in] output_obj An output JSON object 35 | * @param[out] foundry A new foundry object 36 | * @return int 0 on success 37 | */ 38 | int json_output_foundry_deserialize(cJSON *output_obj, output_foundry_t **foundry); 39 | 40 | /** 41 | * @brief Serialize a foundry output to a JSON object 42 | * 43 | * @param[in] foundry A foundry output 44 | * @return cJSON* NULL on errors 45 | */ 46 | cJSON *json_output_foundry_serialize(output_foundry_t *foundry); 47 | 48 | #ifdef __cplusplus 49 | } 50 | #endif 51 | 52 | #endif // __CLIENT_API_JSON_PARSER_OUTPUTS_OUTPUT_FOUNDRY_H__ 53 | -------------------------------------------------------------------------------- /src/client/api/json_parser/outputs/output_nft.h: -------------------------------------------------------------------------------- 1 | // Copyright 2022 IOTA Stiftung 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | #ifndef __CLIENT_API_JSON_PARSER_OUTPUTS_OUTPUT_NFT_H__ 5 | #define __CLIENT_API_JSON_PARSER_OUTPUTS_OUTPUT_NFT_H__ 6 | 7 | #include "client/api/json_parser/json_utils.h" 8 | #include "core/models/outputs/output_nft.h" 9 | 10 | #ifdef __cplusplus 11 | extern "C" { 12 | #endif 13 | 14 | /** 15 | * @brief Deserialize JSON data to output NFT object 16 | * 17 | * @param[in] output_obj Output JSON object 18 | * @param[out] nft A new NFT object 19 | * @return int 0 on success 20 | */ 21 | int json_output_nft_deserialize(cJSON *output_obj, output_nft_t **nft); 22 | 23 | /** 24 | * @brief Serialize a NFT output to a JSON object 25 | * 26 | * @param[in] nft A NFT output 27 | * @return cJSON* NULL on errors 28 | */ 29 | cJSON *json_output_nft_serialize(output_nft_t *nft); 30 | 31 | #ifdef __cplusplus 32 | } 33 | #endif 34 | 35 | #endif // __CLIENT_API_JSON_PARSER_OUTPUTS_OUTPUT_NFT_H__ 36 | -------------------------------------------------------------------------------- /src/client/api/json_parser/outputs/outputs.h: -------------------------------------------------------------------------------- 1 | // Copyright 2022 IOTA Stiftung 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | #ifndef __CLIENT_API_JSON_PARSER_OUTPUTS_OUTPUTS_H__ 5 | #define __CLIENT_API_JSON_PARSER_OUTPUTS_OUTPUTS_H__ 6 | 7 | #include "client/api/json_parser/json_utils.h" 8 | #include "core/models/outputs/outputs.h" 9 | 10 | #ifdef __cplusplus 11 | extern "C" { 12 | #endif 13 | 14 | /** 15 | * @brief Deserialize JSON data to outputs list object 16 | * 17 | * @param[in] outputs_obj An outputs JSON object 18 | * @param[out] outputs An output list object 19 | * @return int 0 on success 20 | */ 21 | int json_outputs_deserialize(cJSON *outputs_obj, utxo_outputs_list_t **outputs); 22 | 23 | /** 24 | * @brief Serialise an output list to a JSON object 25 | * 26 | * @param[in] outputs An output list 27 | * @return cJSON* NULL on errors 28 | */ 29 | cJSON *json_outputs_serialize(utxo_outputs_list_t *outputs); 30 | 31 | #ifdef __cplusplus 32 | } 33 | #endif 34 | 35 | #endif // __CLIENT_API_JSON_PARSER_OUTPUTS_OUTPUTS_H__ 36 | -------------------------------------------------------------------------------- /src/client/api/json_parser/outputs/unlock_conditions.h: -------------------------------------------------------------------------------- 1 | // Copyright 2022 IOTA Stiftung 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | #ifndef __CLIENT_API_JSON_PARSER_OUTPUTS_UNLOCK_CONDITIONS_H__ 5 | #define __CLIENT_API_JSON_PARSER_OUTPUTS_UNLOCK_CONDITIONS_H__ 6 | 7 | #include "client/api/json_parser/json_utils.h" 8 | #include "core/models/outputs/unlock_conditions.h" 9 | 10 | #ifdef __cplusplus 11 | extern "C" { 12 | #endif 13 | 14 | /** 15 | * @brief Deserialize JSON address unlock condition to unlock condition object 16 | * 17 | * @param[in] unlock_cond_obj Unlock conditions JSON object 18 | * @param[out] cond_list Unlock conditions list object 19 | * @return int 0 on success 20 | */ 21 | int json_condition_addr_deserialize(cJSON *unlock_cond_obj, unlock_cond_list_t **cond_list); 22 | 23 | /** 24 | * @brief Deserialize JSON storage deposit return unlock condition to unlock condition object 25 | * 26 | * @param[in] unlock_cond_obj Unlock conditions JSON object 27 | * @param[out] cond_list Unlock conditions list object 28 | * @return int 0 on success 29 | */ 30 | int json_condition_storage_deserialize(cJSON *unlock_cond_obj, unlock_cond_list_t **cond_list); 31 | 32 | /** 33 | * @brief Deserialize JSON timelock unlock condition to unlock condition object 34 | * 35 | * @param[in] unlock_cond_obj Unlock conditions JSON object 36 | * @param[out] cond_list Unlock conditions list object 37 | * @return int 0 on success 38 | */ 39 | int json_condition_timelock_deserialize(cJSON *unlock_cond_obj, unlock_cond_list_t **cond_list); 40 | 41 | /** 42 | * @brief Deserialize JSON expiration unlock condition to unlock condition object 43 | * 44 | * @param[in] unlock_cond_obj Unlock conditions JSON object 45 | * @param[out] cond_list Unlock conditions list object 46 | * @return int 0 on success 47 | */ 48 | int json_condition_expir_deserialize(cJSON *unlock_cond_obj, unlock_cond_list_t **cond_list); 49 | 50 | /** 51 | * @brief Deserialize JSON state controller address unlock condition to unlock condition object 52 | * 53 | * @param[in] unlock_cond_obj Unlock conditions JSON object 54 | * @param[out] cond_list Unlock conditions list object 55 | * @return int 0 on success 56 | */ 57 | int json_condition_state_deserialize(cJSON *unlock_cond_obj, unlock_cond_list_t **cond_list); 58 | 59 | /** 60 | * @brief Deserialize JSON governor address unlock condition to unlock condition object 61 | * 62 | * @param[in] unlock_cond_obj Unlock conditions JSON object 63 | * @param[out] cond_list Unlock conditions list object 64 | * @return int 0 on success 65 | */ 66 | int json_condition_governor_deserialize(cJSON *unlock_cond_obj, unlock_cond_list_t **cond_list); 67 | 68 | /** 69 | * @brief Deserialize JSON immutable alias address unlock condition to unlock condition object 70 | * 71 | * @param[in] unlock_cond_obj Unlock conditions JSON object 72 | * @param[out] cond_list Unlock conditions list object 73 | * @return int 0 on success 74 | */ 75 | int json_condition_immut_alias_deserialize(cJSON *unlock_cond_obj, unlock_cond_list_t **cond_list); 76 | 77 | /** 78 | * @brief Deserialize JSON unlock conditions list to unlock conditions list object 79 | * 80 | * @param[in] output_obj Output JSON object 81 | * @param[out] cond_list Unlock conditions list object 82 | * @return int 0 on success 83 | */ 84 | int json_condition_list_deserialize(cJSON *output_obj, unlock_cond_list_t **cond_list); 85 | 86 | /** 87 | * @brief Serialize unlock conditions 88 | * 89 | * @param[in] cond_list An unlock conditions object 90 | * @return cJSON* NULL on errors 91 | */ 92 | cJSON *json_condition_list_serialize(unlock_cond_list_t *cond_list); 93 | 94 | #ifdef __cplusplus 95 | } 96 | #endif 97 | 98 | #endif // __CLIENT_API_JSON_PARSER_OUTPUTS_UNLOCK_CONDITIONS_H__ 99 | -------------------------------------------------------------------------------- /src/client/api/json_parser/payloads/payloads.h: -------------------------------------------------------------------------------- 1 | // Copyright 2022 IOTA Stiftung 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | #ifndef __CLIENT_API_JSON_PARSER_PAYLOADS_PAYLOADS_H__ 5 | #define __CLIENT_API_JSON_PARSER_PAYLOADS_PAYLOADS_H__ 6 | 7 | #include "cJSON.h" 8 | #include "core/models/payloads/milestone.h" 9 | #include "core/models/payloads/tagged_data.h" 10 | #include "core/models/payloads/transaction.h" 11 | 12 | #ifdef __cplusplus 13 | extern "C" { 14 | #endif 15 | 16 | /** 17 | * @brief Deserialize JSON payload to transaction payload object 18 | * 19 | * @param[in] payload A payload JSON object 20 | * @param[out] tx A transaction payload object 21 | * @return int 0 on success 22 | */ 23 | int json_transaction_deserialize(cJSON* payload, transaction_payload_t* tx); 24 | 25 | /** 26 | * @brief Serialize a transaction payload object to JSON object 27 | * 28 | * @param[in] tx A transaction payload object 29 | * @return cJSON* NULL on errors 30 | */ 31 | cJSON* json_transaction_serialize(transaction_payload_t* tx); 32 | 33 | /** 34 | * @brief Deserialize JSON payload to milestone payload object 35 | * 36 | * @param[in] payload A payload JSON object 37 | * @param[out] ms A milestone payload object 38 | * @return int 0 on success 39 | */ 40 | int milestone_deserialize(cJSON* payload, milestone_payload_t* ms); 41 | 42 | /** 43 | * @brief Deserialize JSON data to tagged data object 44 | * 45 | * @param[in] payload A payload JSON object 46 | * @param[out] tagged_data A tagged data object 47 | * @return int 0 on success 48 | */ 49 | int json_tagged_deserialize(cJSON* payload, tagged_data_payload_t** tagged_data); 50 | 51 | /** 52 | * @brief Serialize a tagged data payload object to JSON object 53 | * 54 | * @param[in] tagged_data A tagged data object 55 | * @return cJSON* NULL on errors 56 | */ 57 | cJSON* json_tagged_serialize(tagged_data_payload_t* tagged_data); 58 | 59 | #ifdef __cplusplus 60 | } 61 | #endif 62 | 63 | #endif // __CLIENT_API_JSON_PARSER_PAYLOADS_PAYLOADS_H__ 64 | -------------------------------------------------------------------------------- /src/client/api/json_parser/unlocks.h: -------------------------------------------------------------------------------- 1 | // Copyright 2022 IOTA Stiftung 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | #ifndef __CLIENT_API_JSON_PARSER_UNLOCKS_H__ 5 | #define __CLIENT_API_JSON_PARSER_UNLOCKS_H__ 6 | 7 | #include "client/api/json_parser/json_utils.h" 8 | #include "core/models/unlocks.h" 9 | 10 | #ifdef __cplusplus 11 | extern "C" { 12 | #endif 13 | 14 | /** 15 | * @brief Deserialize JSON data to an unlock list object 16 | * 17 | * @param[in] unlocks_obj Unlocks JSON object 18 | * @param[out] unlock_list Unlocks object 19 | * @return int 0 on success 20 | */ 21 | int json_unlocks_deserialize(cJSON* unlocks_obj, unlock_list_t** unlock_list); 22 | 23 | /** 24 | * @brief Serialize an unlock list to a JSON object 25 | * 26 | * @param[in] unlock_list An unlock list 27 | * @return cJSON* NULL on errors 28 | */ 29 | cJSON* json_unlocks_serialize(unlock_list_t* unlock_list); 30 | 31 | #ifdef __cplusplus 32 | } 33 | #endif 34 | 35 | #endif // __CLIENT_API_JSON_PARSER_UNLOCKS_H__ 36 | -------------------------------------------------------------------------------- /src/client/api/restful/faucet_enqueue.h: -------------------------------------------------------------------------------- 1 | // Copyright 2022 IOTA Stiftung 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | #ifndef __CLIENT_FAUCET_ENQUEUE_H__ 5 | #define __CLIENT_FAUCET_ENQUEUE_H__ 6 | 7 | #include 8 | 9 | #include "client/api/restful/response_error.h" 10 | #include "client/client_service.h" 11 | #include "core/address.h" 12 | #include "core/utils/macros.h" 13 | 14 | /** 15 | * @brief Store address and waiting requests count returned in response of faucet enqueue request 16 | * 17 | */ 18 | typedef struct { 19 | char bech32_address[BIN_TO_HEX_STR_BYTES(ED25519_PUBKEY_BYTES)]; ///< The Bech32 encoded address that is 20 | ///< returned in response 21 | uint32_t waiting_reqs_count; ///< The number of requests in faucet queue 22 | } faucet_enqueue_t; 23 | 24 | /** 25 | * @brief The response of faucet enqueue request 26 | * 27 | */ 28 | typedef struct { 29 | bool is_error; ///< True if got an error from the node. 30 | union { 31 | res_err_t *error; ///< Error message if is_error is True 32 | faucet_enqueue_t req_res; ///< Faucet enqueue response if is_error is False 33 | } u; 34 | } res_faucet_enqueue_t; 35 | 36 | #ifdef __cplusplus 37 | extern "C" { 38 | #endif 39 | 40 | /** 41 | * @brief Faucet enqueue response JSON deserialization 42 | * 43 | * @param[in] j_str A string of the JSON object 44 | * @param[out] res A response object 45 | * @return int 0 on success 46 | */ 47 | int deser_faucet_enqueue_response(char const *const j_str, res_faucet_enqueue_t *res); 48 | 49 | /** 50 | * @brief Request tokens to address from faucet 51 | * @param[in] conf The client endpoint configuration 52 | * @param[in] addr_bech32 The Bech32 address to which the tokens needs to be requested from faucet 53 | * @param[out] res The faucet enqueue response object 54 | * 55 | * @return res_faucet_enqueue_t* 56 | */ 57 | int req_tokens_to_addr_from_faucet(iota_client_conf_t const *conf, char const addr_bech32[], res_faucet_enqueue_t *res); 58 | 59 | #ifdef __cplusplus 60 | } 61 | #endif 62 | 63 | #endif 64 | -------------------------------------------------------------------------------- /src/client/api/restful/get_block.h: -------------------------------------------------------------------------------- 1 | // Copyright 2020 IOTA Stiftung 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | #ifndef __CLIENT_API_RESTFUL_GET_MSG_H__ 5 | #define __CLIENT_API_RESTFUL_GET_MSG_H__ 6 | 7 | #include 8 | #include 9 | 10 | #include "client/api/restful/response_error.h" 11 | #include "client/client_service.h" 12 | #include "core/models/block.h" 13 | 14 | /** 15 | * @brief The response of get block 16 | * 17 | */ 18 | typedef struct { 19 | bool is_error; ///< True if got an error from the node. 20 | union { 21 | res_err_t *error; ///< Error message if is_error is True 22 | core_block_t *blk; ///< a block object if is_error is False 23 | } u; 24 | } res_block_t; 25 | 26 | #ifdef __cplusplus 27 | extern "C" { 28 | #endif 29 | 30 | /** 31 | * @brief Allocate a block for API response 32 | * 33 | * @return res_block_t* 34 | */ 35 | res_block_t *res_block_new(); 36 | 37 | /** 38 | * @brief Free a block object 39 | * 40 | * @param[in] blk A block object 41 | */ 42 | void res_block_free(res_block_t *blk); 43 | 44 | /** 45 | * @brief The block response deserialization 46 | * 47 | * @param[in] j_str A string of the JSON object 48 | * @param[out] res the block object 49 | * @return int 0 on success 50 | */ 51 | int deser_get_block(char const *const j_str, res_block_t *res); 52 | 53 | /** 54 | * @brief Get the block data from a given block ID 55 | * 56 | * @param[in] conf The client endpoint configuration 57 | * @param[in] blk_id A block ID to query 58 | * @param[out] res The block body of the given ID 59 | * @return int 0 on success 60 | */ 61 | int get_block_by_id(iota_client_conf_t const *conf, char const blk_id[], res_block_t *res); 62 | 63 | #ifdef __cplusplus 64 | } 65 | #endif 66 | 67 | #endif 68 | -------------------------------------------------------------------------------- /src/client/api/restful/get_health.c: -------------------------------------------------------------------------------- 1 | // Copyright 2020 IOTA Stiftung 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | #include 5 | #include 6 | 7 | #include "client/api/restful/get_health.h" 8 | #include "client/network/http.h" 9 | #include "core/utils/iota_str.h" 10 | 11 | int get_health(iota_client_conf_t const *conf, bool *health) { 12 | int ret = -1; 13 | long st = 0; 14 | byte_buf_t *http_res = NULL; 15 | 16 | // http client configuration 17 | http_client_config_t http_conf = { 18 | .host = conf->host, .path = "/health", .use_tls = conf->use_tls, .port = conf->port}; 19 | 20 | if ((http_res = byte_buf_new()) == NULL) { 21 | printf("[%s:%d]: OOM\n", __func__, __LINE__); 22 | goto done; 23 | } 24 | 25 | ret = http_client_get(&http_conf, http_res, &st); 26 | if (st == 200 && ret == 0) { 27 | *health = true; 28 | } else { 29 | *health = false; 30 | } 31 | 32 | done: 33 | // cleanup command 34 | byte_buf_free(http_res); 35 | 36 | return ret; 37 | } 38 | -------------------------------------------------------------------------------- /src/client/api/restful/get_health.h: -------------------------------------------------------------------------------- 1 | // Copyright 2020 IOTA Stiftung 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | #ifndef __CLIENT_API_RESTFUL_HEALTH_H__ 5 | #define __CLIENT_API_RESTFUL_HEALTH_H__ 6 | 7 | #include 8 | #include 9 | 10 | #include "client/client_service.h" 11 | 12 | #ifdef __cplusplus 13 | extern "C" { 14 | #endif 15 | 16 | /** 17 | * @brief Returns the health of the node. 18 | * 19 | * A node considers itself healthy if its current confirmed milestone is at most two delta away from the latest known 20 | * milestone, has at least one ongoing gossip stream and the latest known milestone is newer than 5 minutes. 21 | * 22 | * @param[in] conf The endpoint configuration 23 | * @param[out] health Is node health? 24 | * @return int 0 on success 25 | */ 26 | int get_health(iota_client_conf_t const *conf, bool *health); 27 | 28 | #ifdef __cplusplus 29 | } 30 | #endif 31 | 32 | #endif 33 | -------------------------------------------------------------------------------- /src/client/api/restful/get_tips.h: -------------------------------------------------------------------------------- 1 | // Copyright 2020 IOTA Stiftung 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | #ifndef __CLIENT_API_RESTFUL_TIPS_H__ 5 | #define __CLIENT_API_RESTFUL_TIPS_H__ 6 | 7 | #include 8 | #include 9 | 10 | #include "client/api/restful/response_error.h" 11 | #include "client/client_service.h" 12 | #include "client/network/http.h" 13 | #include "utarray.h" 14 | 15 | typedef UT_array get_tips_t; 16 | 17 | /** 18 | * @brief The response of get tips 19 | * 20 | */ 21 | typedef struct { 22 | bool is_error; ///< True if got an error from the node. 23 | union { 24 | res_err_t *error; ///< Error message if is_error is True 25 | get_tips_t *tips; ///< list of tips if is_error is False 26 | } u; 27 | } res_tips_t; 28 | 29 | #ifdef __cplusplus 30 | extern "C" { 31 | #endif 32 | 33 | /** 34 | * @brief Allocate a res_tips_t response object 35 | * 36 | * @return res_tips_t* 37 | */ 38 | res_tips_t *res_tips_new(); 39 | 40 | /** 41 | * @brief Free a res_tips_t response object 42 | * 43 | * @param[in] tips a response object 44 | */ 45 | void res_tips_free(res_tips_t *tips); 46 | 47 | /** 48 | * @brief Gets tips for attaching to a block 49 | * 50 | * Returns tips that are ideal for attaching to a block. The tips can be considered as `non-lazy` and are therefore 51 | * ideal for attaching a block. 52 | * 53 | * @param[in] conf The client endpoint configuration 54 | * @param[out] res A response object of tips object 55 | * @return int 0 on success 56 | */ 57 | int get_tips(iota_client_conf_t const *conf, res_tips_t *res); 58 | 59 | /** 60 | * @brief Tips response deserialization 61 | * 62 | * @param[in] j_str A string of the JSON object 63 | * @param[out] res A response object of tips object 64 | * @return int 0 on success 65 | */ 66 | int get_tips_deserialize(char const *const j_str, res_tips_t *res); 67 | 68 | /** 69 | * @brief Gets the number of block IDs 70 | * 71 | * @param[in] tips A response object 72 | * @return size_t 73 | */ 74 | size_t get_tips_id_count(res_tips_t *tips); 75 | 76 | /** 77 | * @brief Gets a block ID by a given index 78 | * 79 | * @param[in] tips A response object 80 | * @param[in] index A index of a block ID 81 | * @return char* 82 | */ 83 | char *get_tips_id(res_tips_t *tips, size_t index); 84 | 85 | #ifdef __cplusplus 86 | } 87 | #endif 88 | 89 | #endif 90 | -------------------------------------------------------------------------------- /src/client/api/restful/get_transaction_included_block.c: -------------------------------------------------------------------------------- 1 | // Copyright 2020 IOTA Stiftung 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | #include "client/api/restful/get_transaction_included_block.h" 5 | #include "client/constants.h" 6 | #include "client/network/http.h" 7 | #include "core/models/inputs/utxo_input.h" 8 | #include "core/utils/iota_str.h" 9 | #include "core/utils/macros.h" 10 | 11 | int get_transaction_included_block_by_id(iota_client_conf_t const *conf, char const tx_id[], res_block_t *res) { 12 | if (conf == NULL || tx_id == NULL || res == NULL) { 13 | printf("[%s:%d] invalid parameter\n", __func__, __LINE__); 14 | return -1; 15 | } 16 | 17 | if (strlen(tx_id) != BIN_TO_HEX_BYTES(IOTA_TRANSACTION_ID_BYTES)) { 18 | printf("[%s:%d]: invalid transaction id length: %zu\n", __func__, __LINE__, strlen(tx_id)); 19 | return -1; 20 | } 21 | 22 | int ret = -1; 23 | byte_buf_t *http_res = NULL; 24 | 25 | iota_str_t *cmd = NULL; 26 | char const *const cmd_pre = "/transactions/0x"; 27 | char const *const cmd_post = "/included-block"; 28 | 29 | cmd = iota_str_reserve(strlen(CORE_API_ROUTE) + strlen(cmd_pre) + strlen(cmd_post) + 30 | BIN_TO_HEX_BYTES(IOTA_TRANSACTION_ID_BYTES) + 1); 31 | if (cmd == NULL) { 32 | printf("[%s:%d]: allocate command buffer failed\n", __func__, __LINE__); 33 | return -1; 34 | } 35 | 36 | // composing API command 37 | snprintf(cmd->buf, cmd->cap, "%s%s%s%s", CORE_API_ROUTE, cmd_pre, tx_id, cmd_post); 38 | cmd->len = strlen(cmd->buf); 39 | 40 | // http client configuration 41 | http_client_config_t http_conf = {.host = conf->host, .path = cmd->buf, .use_tls = conf->use_tls, .port = conf->port}; 42 | 43 | if ((http_res = byte_buf_new()) == NULL) { 44 | printf("[%s:%d]: OOM\n", __func__, __LINE__); 45 | goto done; 46 | } 47 | 48 | // send request via http client 49 | long status = 0; 50 | if ((ret = http_client_get(&http_conf, http_res, &status)) == 0) { 51 | byte_buf2str(http_res); 52 | // json deserialization 53 | ret = deser_get_block((char const *const)http_res->data, res); 54 | } 55 | 56 | done: 57 | // cleanup command 58 | iota_str_destroy(cmd); 59 | byte_buf_free(http_res); 60 | return ret; 61 | } 62 | 63 | int deser_get_transaction_included_block(char const *const j_str, res_block_t *res) { 64 | if (j_str == NULL || res == NULL) { 65 | printf("[%s:%d] invalid parameter\n", __func__, __LINE__); 66 | return -1; 67 | } 68 | 69 | if (deser_get_block(j_str, res) != 0) { 70 | return -1; 71 | } 72 | 73 | // only transaction payload is a valid payload for a deserialized block 74 | if (!res->is_error && res->u.blk->payload_type != CORE_BLOCK_PAYLOAD_TRANSACTION) { 75 | return -1; 76 | } 77 | 78 | return 0; 79 | } 80 | -------------------------------------------------------------------------------- /src/client/api/restful/get_transaction_included_block.h: -------------------------------------------------------------------------------- 1 | // Copyright 2020 IOTA Stiftung 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | #ifndef __CLIENT_API_RESTFUL_TRANSACTION_INCLUDED_BLOCK_H__ 5 | #define __CLIENT_API_RESTFUL_TRANSACTION_INCLUDED_BLOCK_H__ 6 | 7 | #include "client/api/restful/get_block.h" 8 | 9 | #ifdef __cplusplus 10 | extern "C" { 11 | #endif 12 | 13 | /** 14 | * @brief Get included block data from a given transaction ID 15 | * 16 | * @param[in] conf The client endpoint configuration 17 | * @param[in] tx_id A transaction ID to query 18 | * @param[out] res The block body of the given ID 19 | * @return int 0 on success 20 | */ 21 | int get_transaction_included_block_by_id(iota_client_conf_t const *conf, char const tx_id[], res_block_t *res); 22 | 23 | /** 24 | * @brief The block response deserialization 25 | * 26 | * @param[in] j_str A string of the JSON object 27 | * @param[out] res the block object 28 | * @return int 0 on success 29 | */ 30 | int deser_get_transaction_included_block(char const *const j_str, res_block_t *res); 31 | 32 | #ifdef __cplusplus 33 | } 34 | #endif 35 | 36 | #endif // __CLIENT_API_V1_TRANSACTION_INCLUDED_BLOCK_H__ 37 | -------------------------------------------------------------------------------- /src/client/api/restful/response_error.c: -------------------------------------------------------------------------------- 1 | // Copyright 2021 IOTA Stiftung 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | #include 5 | #include 6 | 7 | #include "client/api/json_parser/json_keys.h" 8 | #include "client/api/restful/response_error.h" 9 | #include "core/utils/allocator.h" 10 | 11 | void res_err_free(res_err_t *err) { 12 | if (err) { 13 | if (err->code) { 14 | free(err->code); 15 | } 16 | 17 | if (err->msg) { 18 | free(err->msg); 19 | } 20 | 21 | free(err); 22 | } 23 | } 24 | 25 | res_err_t *deser_error(cJSON *j_obj) { 26 | if (j_obj == NULL) { 27 | printf("[%s:%d] invalid parameter\n", __func__, __LINE__); 28 | return NULL; 29 | } 30 | 31 | // check if it is an error response; 32 | cJSON *err_obj = cJSON_GetObjectItemCaseSensitive(j_obj, JSON_KEY_ERROR); 33 | if (err_obj == NULL) { 34 | // it is not exactly an error 35 | // printf("INFO [%s:%d]: error object not found in this response\n", __func__, __LINE__); 36 | return NULL; 37 | } 38 | 39 | cJSON *err_code = cJSON_GetObjectItemCaseSensitive(err_obj, JSON_KEY_CODE); 40 | if (!err_code) { 41 | printf("[%s:%d]: error code found\n", __func__, __LINE__); 42 | return NULL; 43 | } 44 | if (!cJSON_IsString(err_code) || (err_code->valuestring == NULL)) { 45 | printf("[%s:%d] error message is not a string\n", __func__, __LINE__); 46 | return NULL; 47 | } 48 | 49 | cJSON *err_msg = cJSON_GetObjectItemCaseSensitive(err_obj, JSON_KEY_MSG); 50 | if (err_msg == NULL) { 51 | printf("[%s:%d] error message not found\n", __func__, __LINE__); 52 | return NULL; 53 | } 54 | if (!cJSON_IsString(err_msg) || (err_msg->valuestring == NULL)) { 55 | printf("[%s:%d] error message is not a string\n", __func__, __LINE__); 56 | return NULL; 57 | } 58 | 59 | res_err_t *res_err = malloc(sizeof(res_err_t)); 60 | if (res_err == NULL) { 61 | printf("[%s:%d] OOM\n", __func__, __LINE__); 62 | return NULL; 63 | } 64 | 65 | size_t len = strlen(err_msg->valuestring); 66 | res_err->msg = malloc(len + 1); 67 | if (res_err->msg == NULL) { 68 | res_err_free(res_err); 69 | printf("[%s:%d] OOM\n", __func__, __LINE__); 70 | return NULL; 71 | } 72 | strncpy(res_err->msg, err_msg->valuestring, len); 73 | res_err->msg[len] = '\0'; 74 | 75 | len = strlen(err_code->valuestring); 76 | res_err->code = malloc(len + 1); 77 | if (res_err->code == NULL) { 78 | res_err_free(res_err); 79 | printf("[%s:%d] OOM\n", __func__, __LINE__); 80 | return NULL; 81 | } 82 | strncpy(res_err->code, err_code->valuestring, len); 83 | res_err->code[len] = '\0'; 84 | 85 | return res_err; 86 | } -------------------------------------------------------------------------------- /src/client/api/restful/response_error.h: -------------------------------------------------------------------------------- 1 | // Copyright 2021 IOTA Stiftung 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | #ifndef __CLIENT_API_RESTFUL_RES_ERR_H__ 5 | #define __CLIENT_API_RESTFUL_RES_ERR_H__ 6 | 7 | #include 8 | 9 | #include "cJSON.h" 10 | 11 | /** 12 | * @brief Node API error response 13 | * 14 | */ 15 | typedef struct { 16 | char *code; ///< an error code from node response 17 | char *msg; ///< a error message from node response 18 | } res_err_t; 19 | 20 | #ifdef __cplusplus 21 | extern "C" { 22 | #endif 23 | 24 | /** 25 | * @brief Free an error response object 26 | * 27 | * @param err The error response 28 | */ 29 | void res_err_free(res_err_t *err); 30 | 31 | /** 32 | * @brief The error object deserialization 33 | * 34 | * @param j_obj A string of the JSON object 35 | * 36 | * @return res_err_t* 37 | */ 38 | res_err_t *deser_error(cJSON *j_obj); 39 | 40 | #ifdef __cplusplus 41 | } 42 | #endif 43 | 44 | #endif 45 | -------------------------------------------------------------------------------- /src/client/api/restful/send_block.h: -------------------------------------------------------------------------------- 1 | // Copyright 2020 IOTA Stiftung 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | #ifndef __CLIENT_API_RESTFUL_SEND_BLOCK_H__ 5 | #define __CLIENT_API_RESTFUL_SEND_BLOCK_H__ 6 | 7 | #include 8 | #include 9 | 10 | #include "client/api/restful/response_error.h" 11 | #include "client/client_service.h" 12 | #include "client/constants.h" 13 | #include "core/models/block.h" 14 | #include "core/utils/macros.h" 15 | 16 | /** 17 | * @brief The response of send block 18 | * 19 | */ 20 | typedef struct { 21 | bool is_error; ///< True if got an error from the node. 22 | union { 23 | res_err_t* error; ///< Error message if is_error is True 24 | char blk_id[BIN_TO_HEX_STR_BYTES(IOTA_BLOCK_ID_BYTES)]; ///< a block IDs string if is_error is False 25 | } u; 26 | } res_send_block_t; 27 | 28 | #ifdef __cplusplus 29 | extern "C" { 30 | #endif 31 | 32 | /** 33 | * @brief Deserialize the response of send_block 34 | * 35 | * @param[in] json_str The response string 36 | * @param[out] res The response object 37 | * @return int 0 on success 38 | */ 39 | int deser_send_block_response(char const* json_str, res_send_block_t* res); 40 | 41 | /** 42 | * @brief Send block thought core block object 43 | * 44 | * @param[in] conf The client endpoint configuration 45 | * @param[in] blk A Block object 46 | * @param[out] res An error or block ID 47 | * @return int 0 on success 48 | */ 49 | int send_core_block(iota_client_conf_t const* const conf, core_block_t* blk, res_send_block_t* res); 50 | 51 | #ifdef __cplusplus 52 | } 53 | #endif 54 | 55 | #endif 56 | -------------------------------------------------------------------------------- /src/client/api/restful/send_tagged_data.h: -------------------------------------------------------------------------------- 1 | // Copyright 2022 IOTA Stiftung 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | #ifndef __CLIENT_API_RESTFUL_SEND_TAGGED_DATA_H__ 5 | #define __CLIENT_API_RESTFUL_SEND_TAGGED_DATA_H__ 6 | 7 | #include "client/api/restful/send_block.h" 8 | #include "core/utils/byte_buffer.h" 9 | 10 | #ifdef __cplusplus 11 | extern "C" { 12 | #endif 13 | 14 | /** 15 | * @brief Send tagged data block 16 | * 17 | * @param[in] conf The client endpoint configuration 18 | * @param[in] ver The protocol version 19 | * @param[in] tag The binary tag of the tagged data payload 20 | * @param[in] tag_len The length of the binary tag 21 | * @param[in] data The binary data of the tagged data payload 22 | * @param[in] data_len The length of the tagged data payload binary data 23 | * @param[out] res An error or block ID 24 | * @return int 0 on success 25 | */ 26 | int send_tagged_data_block(iota_client_conf_t const* conf, uint8_t ver, byte_t tag[], uint8_t tag_len, byte_t data[], 27 | uint32_t data_len, res_send_block_t* res); 28 | 29 | #ifdef __cplusplus 30 | } 31 | #endif 32 | 33 | #endif 34 | -------------------------------------------------------------------------------- /src/client/client_service.h: -------------------------------------------------------------------------------- 1 | // Copyright 2021 IOTA Stiftung 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | #ifndef __CLIENT_SERVICE_H__ 5 | #define __CLIENT_SERVICE_H__ 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | #include "client/constants.h" 12 | 13 | /** 14 | * @brief Client endpoint configuration 15 | * 16 | */ 17 | typedef struct { 18 | char host[IOTA_ENDPOINT_MAX_LEN]; ///< domain name or IP as string 19 | uint16_t port; ///< port to connect 20 | bool use_tls; ///< Use TLS or not 21 | } iota_client_conf_t; 22 | 23 | #ifdef __cplusplus 24 | extern "C" { 25 | #endif 26 | 27 | #ifdef __cplusplus 28 | } 29 | #endif 30 | 31 | #endif 32 | -------------------------------------------------------------------------------- /src/client/constants.h: -------------------------------------------------------------------------------- 1 | // Copyright 2022 IOTA Stiftung 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | #ifndef __CLIENT_CONSTANTS_H__ 5 | #define __CLIENT_CONSTANTS_H__ 6 | 7 | #include "core/constants.h" 8 | 9 | // supported protoocl version of this client library 10 | #define SUPPORTED_PROTOCOL_VERSION 2 11 | // Core API route prefix of the node 12 | #define CORE_API_ROUTE "/api/core/v2" 13 | // Indexer API route prefix of the node 14 | #define INDEXER_API_ROUTE "/api/indexer/v1" 15 | 16 | #define IOTA_ENDPOINT_MAX_LEN 256 17 | 18 | #endif 19 | -------------------------------------------------------------------------------- /src/client/network/http.h: -------------------------------------------------------------------------------- 1 | // Copyright 2021 IOTA Stiftung 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | #ifndef __CLIENT_NETWORK_HTTP_H__ 5 | #define __CLIENT_NETWORK_HTTP_H__ 6 | 7 | /** 8 | * @brief Abstract layer of http client for IOTA client 9 | * 10 | */ 11 | 12 | #include 13 | #include 14 | 15 | #include "core/utils/byte_buffer.h" 16 | 17 | typedef struct { 18 | char const* url; ///< HTTP URL, it overrides fields below, if any 19 | char const* host; ///< Domain name or IP as string 20 | char const* path; ///< HTTP path 21 | char const* query; ///< HTTP query 22 | char const* cert_pem; ///< SSL certification in PEM format 23 | uint16_t port; ///< port to connect 24 | bool use_tls; ///< Use TLS or not 25 | } http_client_config_t; 26 | 27 | #ifdef __cplusplus 28 | extern "C" { 29 | #endif 30 | 31 | /** 32 | * @brief Inits http client instance 33 | * 34 | */ 35 | void http_client_init(); 36 | 37 | /** 38 | * @brief Clean up http client instance 39 | * 40 | */ 41 | void http_client_clean(); 42 | 43 | /** 44 | * @brief Performs http POST 45 | * 46 | * @param[in] url The server url 47 | * @param[in] request The request of body 48 | * @param[out] response The response data 49 | * @param[out] status HTTP status code 50 | * @return int 0 on success 51 | */ 52 | int http_client_post(http_client_config_t const* const config, byte_buf_t const* const request, 53 | byte_buf_t* const response, long* status); 54 | 55 | /** 56 | * @brief Performs http GET 57 | * 58 | * @param[in] url The server url 59 | * @param[out] response The response data 60 | * @param[out] status HTTP status code 61 | * @return int 0 on success 62 | */ 63 | int http_client_get(http_client_config_t const* const config, byte_buf_t* const response, long* status); 64 | 65 | #ifdef __cplusplus 66 | } 67 | #endif 68 | 69 | #endif 70 | -------------------------------------------------------------------------------- /src/core/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | #[[ 2 | // Copyright 2020 IOTA Stiftung 3 | // SPDX-License-Identifier: Apache-2.0 4 | ]] 5 | 6 | add_library(iota_core STATIC) 7 | # the required minimum C standard 8 | set_target_properties(iota_core PROPERTIES C_STANDARD_REQUIRED NO C_STANDARD 99) 9 | 10 | target_sources( 11 | iota_core 12 | PRIVATE "address.c" 13 | "utils/iota_str.c" 14 | "utils/byte_buffer.c" 15 | "utils/slip10.c" 16 | "utils/bech32.c" 17 | "utils/uint256.c" 18 | "utils/macros.h" 19 | "models/inputs/utxo_input.c" 20 | "models/outputs/byte_cost_config.c" 21 | "models/outputs/features.c" 22 | "models/outputs/output_alias.c" 23 | "models/outputs/output_basic.c" 24 | "models/outputs/output_foundry.c" 25 | "models/outputs/output_nft.c" 26 | "models/outputs/native_tokens.c" 27 | "models/outputs/outputs.c" 28 | "models/outputs/storage_deposit.c" 29 | "models/outputs/unlock_conditions.c" 30 | "models/payloads/transaction.c" 31 | "models/payloads/tagged_data.c" 32 | "models/payloads/milestone.c" 33 | "models/block.c" 34 | "models/signing.c" 35 | "models/unlocks.c" 36 | PUBLIC "address.h" 37 | "constants.h" 38 | "utils/iota_str.h" 39 | "utils/byte_buffer.h" 40 | "utils/slip10.h" 41 | "utils/bech32.h" 42 | "utils/uint256.h" 43 | "utils/macros.h" 44 | "models/inputs/utxo_input.h" 45 | "models/outputs/byte_cost_config.h" 46 | "models/outputs/features.h" 47 | "models/outputs/output_alias.h" 48 | "models/outputs/output_basic.h" 49 | "models/outputs/output_foundry.h" 50 | "models/outputs/output_nft.h" 51 | "models/outputs/native_tokens.h" 52 | "models/outputs/outputs.h" 53 | "models/outputs/storage_deposit.h" 54 | "models/outputs/unlock_conditions.h" 55 | "models/payloads/transaction.h" 56 | "models/payloads/tagged_data.h" 57 | "models/payloads/milestone.h" 58 | "models/block.h" 59 | "models/signing.h" 60 | "models/unlocks.h") 61 | 62 | target_include_directories(iota_core PUBLIC "${PROJECT_SOURCE_DIR}/src" "${CMAKE_INSTALL_PREFIX}/include") 63 | 64 | add_dependencies(iota_core iota_crypto ext_uthash) 65 | 66 | target_compile_options(iota_core PRIVATE -Wall -Wextra) 67 | 68 | target_link_libraries(iota_core PUBLIC iota_crypto) 69 | 70 | if(__JEMALLOC_INCLUDED) 71 | add_dependencies(iota_core jemalloc) 72 | target_link_libraries(iota_core PUBLIC jemalloc${CMAKE_STATIC_LIBRARY_SUFFIX} Threads::Threads) 73 | target_compile_definitions(iota_core PUBLIC USE_JEMALLOC) 74 | target_link_options(iota_core PUBLIC -Wl,--no-as-needed -ldl) 75 | endif() 76 | 77 | # install client lib and headers 78 | install(TARGETS iota_core DESTINATION "${CMAKE_INSTALL_PREFIX}/lib") 79 | install( 80 | DIRECTORY "${PROJECT_SOURCE_DIR}/src/core/" 81 | DESTINATION "${CMAKE_INSTALL_PREFIX}/include/core" 82 | FILES_MATCHING 83 | PATTERN "*.h") 84 | -------------------------------------------------------------------------------- /src/core/constants.h: -------------------------------------------------------------------------------- 1 | // Copyright 2022 IOTA Stiftung 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | #ifndef __CORE_CONSTANTS_H__ 5 | #define __CORE_CONSTANTS_H__ 6 | 7 | #include 8 | 9 | #include "crypto/constants.h" 10 | 11 | /****** Constants related to Block******/ 12 | // Block ID length in binary form 13 | #define IOTA_BLOCK_ID_BYTES 32 14 | 15 | /****** Constants related to transactions ******/ 16 | // Transaction ID bytes 17 | #define IOTA_TRANSACTION_ID_BYTES 32 18 | // OUTPUT ID bytes = 34 (IOTA_TRANSACTION_ID + OUTPUT INDEX) 19 | #define IOTA_OUTPUT_ID_BYTES (IOTA_TRANSACTION_ID_BYTES + sizeof(uint16_t)) 20 | // Have one transaction essence type only which is 1 21 | #define TRANSACTION_ESSENCE_TYPE 1 22 | 23 | /****** Constants related to addresses ******/ 24 | // An Ed25519 address is the Blake2b-256 hash of an Ed25519 public key. 25 | #define ED25519_PUBKEY_BYTES ED_PUBLIC_KEY_BYTES 26 | // An Alias address is the Blake2b-256 hash of the OutputID which created it. 27 | #define ALIAS_ID_BYTES CRYPTO_BLAKE2B_256_HASH_BYTES 28 | // A NFT address is the Blake2b-256 hash of the OutputID which created it. 29 | #define NFT_ID_BYTES CRYPTO_BLAKE2B_256_HASH_BYTES 30 | // The genral hash lengh of address which is equal to ED25519_PUBKEY_BYTES, ALIAS_ID_BYTES, and NFT_ID_BYTES 31 | #define ADDRESS_HASH_BYTES 32 32 | // The number of bytes a serialized address can hold. 33 | #define ADDRESS_SERIALIZED_BYTES (1 + ADDRESS_HASH_BYTES) 34 | 35 | /****** Constants related to unlocks ******/ 36 | // ed25519 signature object = signature type + public key + signature 37 | #define ED25519_SIGNATURE_BLOCK_BYTES (1 + ED_PUBLIC_KEY_BYTES + ED_SIGNATURE_BYTES) // 97 bytes 38 | // unlock_type_t + reference = 1 + 2 39 | #define UNLOCK_REFERENCE_SERIALIZE_BYTES (1 + sizeof(uint16_t)) 40 | // unlock_type_t + signature type + pub_key + signature 41 | #define UNLOCK_SIGNATURE_SERIALIZE_BYTES (1 + ED25519_SIGNATURE_BLOCK_BYTES) 42 | // unlock_type_t + alias index = 1 + 2 43 | #define UNLOCK_ALIAS_SERIALIZE_BYTES (1 + sizeof(uint16_t)) 44 | // unlock_type_t + NFT index = 1 + 2 45 | #define UNLOCK_NFT_SERIALIZE_BYTES (1 + sizeof(uint16_t)) 46 | 47 | /****** Constants related to tagged data ******/ 48 | // Maximum length of tag in bytes 49 | #define TAGGED_DATA_TAG_MAX_LENGTH_BYTES 64 50 | 51 | /****** Constants related to features ******/ 52 | // Maximum possible length in bytes of a Tag 53 | #define MAX_INDEX_TAG_BYTES 64 54 | // Maximun possible length in bytes of Metadata 55 | #define MAX_METADATA_LENGTH_BYTES 8192 56 | // Maximun Features in a list 57 | #define MAX_FEATURE_BLOCK_COUNT 4 58 | 59 | /****** Constants related to native tokens ******/ 60 | // Maximum number of Native Tokens in an output 61 | #define NATIVE_TOKENS_MAX_COUNT 64 62 | // Native Token ID length in bytes 63 | #define NATIVE_TOKEN_ID_BYTES 38 64 | // Serialized bytes = token ID(38 bytes) + amount(uint256_t) 65 | #define NATIVE_TOKENS_SERIALIZED_BYTES (NATIVE_TOKEN_ID_BYTES + 32) 66 | 67 | /****** Constants related to foundry output ******/ 68 | // The concatenation of Address || Serial Number || Token Scheme Type 69 | #define FOUNDRY_ID_BYTES 38 70 | 71 | /****** Constants related to UTXO output ******/ 72 | // Maximum number of outputs in a transaction payload. 73 | #define UTXO_OUTPUT_MAX_COUNT 128 74 | // Maximum IOTA token supply 75 | static const uint64_t MAX_IOTA_SUPPLY = 2779530283277761; 76 | 77 | /****** Constants related to unlock conditions ******/ 78 | // Maximun Unlock Conditions in a list 79 | #define MAX_UNLOCK_CONDITION_BLOCK_COUNT 4 80 | 81 | /****** Constants related to UTXO inputs ******/ 82 | // Maximum number of inputs in a transaction payload. 83 | #define UTXO_INPUT_MAX_COUNT 128 84 | 85 | #endif 86 | -------------------------------------------------------------------------------- /src/core/models/outputs/byte_cost_config.c: -------------------------------------------------------------------------------- 1 | // Copyright 2022 IOTA Stiftung 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | #include 5 | 6 | #include "core/models/inputs/utxo_input.h" 7 | #include "core/models/outputs/byte_cost_config.h" 8 | 9 | // Defines the rent of a single virtual byte denoted in IOTA tokens 10 | #define DEFAULT_BYTE_COST 500 11 | // Defines the multiplier for data fields 12 | #define DEFAULT_BYTE_COST_FACTOR_DATA 1 13 | // Defines the multiplier for fields which can act as keys for lookups 14 | #define DEFAULT_BYTE_COST_FACTOR_KEY 10 15 | 16 | byte_cost_config_t *byte_cost_config_new(uint16_t byte_cost, uint8_t byte_factor_data, uint8_t byte_factor_key) { 17 | byte_cost_config_t *config = malloc(sizeof(byte_cost_config_t)); 18 | if (!config) { 19 | printf("[%s:%d] can not create storage config\n", __func__, __LINE__); 20 | return NULL; 21 | } 22 | 23 | config->v_byte_cost = byte_cost; 24 | config->v_byte_factor_data = byte_factor_data; 25 | config->v_byte_factor_key = byte_factor_key; 26 | 27 | // size of: output ID + Block ID + confirmation milestone index + confirmation unix timestamp 28 | config->v_byte_offset = (IOTA_OUTPUT_ID_BYTES * byte_factor_key) + // output ID 29 | (IOTA_BLOCK_ID_BYTES * byte_factor_data) + // Block ID 30 | (sizeof(uint32_t) * byte_factor_data) + // confirmation milestone index 31 | (sizeof(uint32_t) * byte_factor_data); // confirmation unix timestamp 32 | 33 | return config; 34 | } 35 | 36 | byte_cost_config_t *byte_cost_config_default_new() { 37 | return byte_cost_config_new(DEFAULT_BYTE_COST, DEFAULT_BYTE_COST_FACTOR_DATA, DEFAULT_BYTE_COST_FACTOR_KEY); 38 | } 39 | 40 | void byte_cost_config_free(byte_cost_config_t *config) { 41 | if (config) { 42 | free(config); 43 | } 44 | } 45 | 46 | void byte_cost_config_set(byte_cost_config_t *config, uint16_t byte_cost, uint8_t byte_factor_data, 47 | uint8_t byte_factor_key) { 48 | if (config) { 49 | config->v_byte_cost = byte_cost; 50 | config->v_byte_factor_data = byte_factor_data; 51 | config->v_byte_factor_key = byte_factor_key; 52 | 53 | // size of: output ID + Block ID + confirmation milestone index + confirmation unix timestamp 54 | config->v_byte_offset = (IOTA_OUTPUT_ID_BYTES * byte_factor_key) + // output ID 55 | (IOTA_BLOCK_ID_BYTES * byte_factor_data) + // Block ID 56 | (sizeof(uint32_t) * byte_factor_data) + // confirmation milestone index 57 | (sizeof(uint32_t) * byte_factor_data); // confirmation unix timestamp 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/core/models/outputs/byte_cost_config.h: -------------------------------------------------------------------------------- 1 | // Copyright 2022 IOTA Stiftung 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | #ifndef __CORE_MODELS_OUTPUTS_BYTE_COST_CONFIG_H__ 5 | #define __CORE_MODELS_OUTPUTS_BYTE_COST_CONFIG_H__ 6 | 7 | #include 8 | 9 | /** 10 | * @brief Specifies the current parameters for the byte cost computation 11 | * 12 | */ 13 | typedef struct { 14 | uint16_t v_byte_cost; ///< Defines the rent of a single virtual byte denoted in IOTA tokens 15 | uint8_t v_byte_factor_data; ///< Defines the multiplier for data fields 16 | uint8_t v_byte_factor_key; ///< Defines the multiplier for fields which can act as keys for lookups 17 | uint16_t v_byte_offset; ///< Additional virtual bytes that are caused by additional data that has to be stored in the 18 | ///< database but is not part of the output itself 19 | } byte_cost_config_t; 20 | 21 | #ifdef __cplusplus 22 | extern "C" { 23 | #endif 24 | 25 | /** 26 | * @brief Create new byte cost configuration 27 | * 28 | * @param[in] byte_cost Rent of a single virtual byte denoted in IOTA tokens 29 | * @param[in] byte_factor_data Multiplier for data fields 30 | * @param[in] byte_factor_key Multiplier for key fields 31 | * @return *byte_cost_config_t 32 | */ 33 | byte_cost_config_t *byte_cost_config_new(uint16_t byte_cost, uint8_t byte_factor_data, uint8_t byte_factor_key); 34 | 35 | /** 36 | * @brief Create new default byte cost configuration 37 | * 38 | * @return *byte_cost_config_t 39 | */ 40 | byte_cost_config_t *byte_cost_config_default_new(); 41 | 42 | /** 43 | * @brief Free byte cost configuration 44 | * 45 | * @param[in] config A byte cost configuration 46 | */ 47 | void byte_cost_config_free(byte_cost_config_t *config); 48 | 49 | /** 50 | * @brief Set byte cost configuration 51 | * 52 | * @param[in, out] config A pointer to byte cost config object 53 | * @param[in] byte_cost Rent of a single virtual byte denoted in IOTA tokens 54 | * @param[in] byte_factor_data Multiplier for data fields 55 | * @param[in] byte_factor_key Multiplier for key fields 56 | */ 57 | void byte_cost_config_set(byte_cost_config_t *config, uint16_t byte_cost, uint8_t byte_factor_data, 58 | uint8_t byte_factor_key); 59 | 60 | #ifdef __cplusplus 61 | } 62 | #endif 63 | 64 | #endif // __CORE_MODELS_OUTPUTS_BYTE_COST_CONFIG_H__ 65 | -------------------------------------------------------------------------------- /src/core/models/outputs/output_basic.h: -------------------------------------------------------------------------------- 1 | // Copyright 2021 IOTA Stiftung 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | #ifndef __CORE_MODELS_OUTPUT_BASIC_H__ 5 | #define __CORE_MODELS_OUTPUT_BASIC_H__ 6 | 7 | #include 8 | 9 | #include "core/address.h" 10 | #include "core/models/outputs/features.h" 11 | #include "core/models/outputs/native_tokens.h" 12 | #include "core/models/outputs/unlock_conditions.h" 13 | 14 | /** 15 | * @brief An output type which can hold native tokens and features 16 | * 17 | */ 18 | typedef struct { 19 | uint64_t amount; ///< The amount of IOTA tokens to held by the output 20 | native_tokens_list_t* native_tokens; ///< The native tokens held by the output 21 | unlock_cond_list_t* unlock_conditions; ///< Define how the output can be unlocked and spent 22 | feature_list_t* features; ///< The features which modulate the constraints on the output 23 | } output_basic_t; 24 | 25 | #ifdef __cplusplus 26 | extern "C" { 27 | #endif 28 | 29 | /** 30 | * @brief Create new Basic Output object 31 | * 32 | * @param[in] amount The amount of IOTA tokens to held by the output 33 | * @param[in] tokens List of native tokens held by the output 34 | * @param[in] cond_list Set of unlock conditions 35 | * @param[in] features List of features 36 | * 37 | * @return output_basic_t* or NULL on failure 38 | */ 39 | output_basic_t* output_basic_new(uint64_t amount, native_tokens_list_t* tokens, unlock_cond_list_t* cond_list, 40 | feature_list_t* features); 41 | 42 | /** 43 | * @brief Free Basic Output object 44 | * 45 | * @param[in] output Basic Output object 46 | */ 47 | void output_basic_free(output_basic_t* output); 48 | 49 | /** 50 | * @brief Get the length of a serialized Basic Output 51 | * 52 | * @param[in] output Basic Output object 53 | * @return size_t The number of bytes of serialized data 54 | */ 55 | size_t output_basic_serialize_len(output_basic_t* output); 56 | 57 | /** 58 | * @brief Serialize Basic Output to a binary data 59 | * 60 | * @param[in] output Basic Output object 61 | * @param[out] buf A buffer holds the serialized data 62 | * @param[in] buf_len The length of buffer 63 | * @return size_t The bytes written is returned, 0 on errors 64 | */ 65 | size_t output_basic_serialize(output_basic_t* output, byte_t buf[], size_t buf_len); 66 | 67 | /** 68 | * @brief Deserialize a binary data to a Basic Output object 69 | * 70 | * @param[in] buf The basic output data in binary 71 | * @param[in] buf_len The length of the data 72 | * @return output_basic_t* or NULL on failure 73 | */ 74 | output_basic_t* output_basic_deserialize(byte_t buf[], size_t buf_len); 75 | 76 | /** 77 | * @brief Clone Basic Output object, it should be freed after use. 78 | * 79 | * @param[in] output Basic Output object for clone 80 | * @return output_basic_t* New Basic Output object 81 | */ 82 | output_basic_t* output_basic_clone(output_basic_t const* const output); 83 | 84 | /** 85 | * @brief Print Basic Output 86 | * 87 | * @param[in] output Basic Output object 88 | * @param[in] indentation Tab indentation when printing Basic Output 89 | */ 90 | void output_basic_print(output_basic_t* output, uint8_t indentation); 91 | 92 | /** 93 | * @brief Basic Output syntactic validation 94 | * 95 | * @param[in] output A Basic output 96 | * @return true Valid 97 | * @return false Invalid 98 | */ 99 | bool output_basic_syntactic(output_basic_t* output); 100 | 101 | #ifdef __cplusplus 102 | } 103 | #endif 104 | 105 | #endif 106 | -------------------------------------------------------------------------------- /src/core/models/outputs/storage_deposit.h: -------------------------------------------------------------------------------- 1 | // Copyright 2022 IOTA Stiftung 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | #ifndef __CORE_MODELS_OUTPUT_STORAGE_DEPOSIT_H__ 5 | #define __CORE_MODELS_OUTPUT_STORAGE_DEPOSIT_H__ 6 | 7 | #include "core/models/outputs/byte_cost_config.h" 8 | #include "core/models/outputs/outputs.h" 9 | 10 | #ifdef __cplusplus 11 | extern "C" { 12 | #endif 13 | 14 | /** 15 | * @brief Calculate minimum storage deposit for the given output 16 | * 17 | * @param[in] config A byte cost configuration 18 | * @param[in] output_type UTXO output type 19 | * @param[in] output Pointer to an output 20 | * @return true if output has enough storage deposit amount 21 | */ 22 | uint64_t calc_minimum_output_deposit(byte_cost_config_t *config, utxo_output_type_t output_type, void *output); 23 | 24 | /** 25 | * @brief Check if a sufficient storage deposit was made for the given output 26 | * 27 | * @param[in] config A byte cost configuration 28 | * @param[in] output_type UTXO output type 29 | * @param[in] output Pointer to an output 30 | * @return true if output has enough storage deposit amount 31 | */ 32 | bool storage_deposit_check(byte_cost_config_t *config, utxo_output_type_t output_type, void *output); 33 | 34 | #ifdef __cplusplus 35 | } 36 | #endif 37 | 38 | #endif // __CORE_MODELS_OUTPUT_STORAGE_DEPOSIT_H__ 39 | -------------------------------------------------------------------------------- /src/core/models/payloads/tagged_data.h: -------------------------------------------------------------------------------- 1 | // Copyright 2022 IOTA Stiftung 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | #ifndef __CORE_MODELS_PL_TAGGED_DATA_H__ 5 | #define __CORE_MODELS_PL_TAGGED_DATA_H__ 6 | 7 | #include 8 | 9 | #include "core/utils/byte_buffer.h" 10 | 11 | /** 12 | * @brief Tagged data structure 13 | * 14 | * The payload type of tagged data is 5 15 | */ 16 | typedef struct { 17 | byte_buf_t *tag; ///< The tag of the data 18 | byte_buf_t *data; ///< Binary data 19 | } tagged_data_payload_t; 20 | 21 | #ifdef __cplusplus 22 | extern "C" { 23 | #endif 24 | 25 | /** 26 | * @brief Create a tagged data object with tag and binary data 27 | * 28 | * @param[in] tag The binary tag in tagged data payload 29 | * @param[in] tag_len The length of the binary tag 30 | * @param[in] data The binary data in tagged data payload 31 | * @param[in] data_len The length of the binary data 32 | * @return tagged_data_payload_t* A pointer to tagged data object 33 | */ 34 | tagged_data_payload_t *tagged_data_new(byte_t tag[], uint8_t tag_len, byte_t data[], uint32_t data_len); 35 | 36 | /** 37 | * @brief Free a tagged data object 38 | * 39 | * @param[in] tagged_data A tagged data object 40 | */ 41 | void tagged_data_free(tagged_data_payload_t *tagged_data); 42 | 43 | /** 44 | * @brief Get a serialized length of a tagged data 45 | * 46 | * @param[in] tagged_data A tagged data object 47 | * @return size_t The number of bytes of serialized data 48 | */ 49 | size_t tagged_data_serialize_len(tagged_data_payload_t *tagged_data); 50 | 51 | /** 52 | * @brief Serialize a tagged data to a binary data 53 | * 54 | * @param[in] tagged_data A tagged data object 55 | * @param[out] buf A buffer holds the serialized data 56 | * @param[in] buf_len The length of buffer 57 | * @return size_t The bytes written is returned, 0 on errors 58 | */ 59 | size_t tagged_data_serialize(tagged_data_payload_t *tagged_data, byte_t buf[], size_t buf_len); 60 | 61 | /** 62 | * @brief Deserialize a binary data to a tagged data object 63 | * 64 | * @param[in] buf The block data in binary 65 | * @param[in] buf_len The length of the data 66 | * @return tagged_data_payload_t* or NULL on failure 67 | */ 68 | tagged_data_payload_t *tagged_data_deserialize(byte_t buf[], size_t buf_len); 69 | 70 | /** 71 | * @brief Clone tagged data object, it should be freed after use. 72 | * 73 | * @param[in] tagged_data tagged data object for clone 74 | * @return tagged_data_payload_t* New tagged data object 75 | */ 76 | tagged_data_payload_t *tagged_data_clone(tagged_data_payload_t const *const tagged_data); 77 | 78 | /** 79 | * @brief Print a tagged data object 80 | * 81 | * @param[in] tagged_data A tagged data object 82 | * @param[in] indentation Tab indentation when printing a tagged data 83 | */ 84 | void tagged_data_print(tagged_data_payload_t *tagged_data, uint8_t indentation); 85 | 86 | #ifdef __cplusplus 87 | } 88 | #endif 89 | 90 | #endif 91 | -------------------------------------------------------------------------------- /src/core/models/signing.h: -------------------------------------------------------------------------------- 1 | // Copyright 2022 IOTA Stiftung 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | #ifndef __CORE_MODELS_SIGNING_H__ 5 | #define __CORE_MODELS_SIGNING_H__ 6 | 7 | #include 8 | 9 | #include "core/address.h" 10 | #include "core/models/inputs/utxo_input.h" 11 | #include "core/models/unlocks.h" 12 | 13 | /** 14 | * @brief A signing data structure. This data is needed when unlocks are creating and transaction gets signed. 15 | * 16 | */ 17 | typedef struct { 18 | address_t unlock_address; ///< Address in Unlock Condition (Address, Governor, State Controller) - ED25519/NFT/Alias 19 | byte_t hash[CRYPTO_BLAKE2B_256_HASH_BYTES]; ///< Optional, a NFT/Alias ID in the utxo_output 20 | ed25519_keypair_t* keypair; ///< Optional, ed25519 keypair (this is for ed25519 address) 21 | } signing_data_t; 22 | 23 | /** 24 | * @brief A list of signing data. 25 | * 26 | * This list needs to have the same order of signing data for unspent outputs as in utxo_inputs_list_t. 27 | * 28 | */ 29 | typedef struct signing_data_list { 30 | signing_data_t* sign_data; //< Points to a current signing data 31 | struct signing_data_list* next; //< Points to a next signing data list 32 | } signing_data_list_t; 33 | 34 | #ifdef __cplusplus 35 | extern "C" { 36 | #endif 37 | 38 | /** 39 | * @brief Initialize a signing data list 40 | * 41 | * @return a NULL pointer 42 | */ 43 | signing_data_list_t* signing_new(); 44 | 45 | /** 46 | * @brief Free a signing data list 47 | * 48 | * @param[in] signing_data_list Signing data list 49 | */ 50 | void signing_free(signing_data_list_t* signing_data_list); 51 | 52 | /** 53 | * @brief Add a signing data into the list 54 | * 55 | * @param[in] unlock_address Address Unlock Condition Address - ED25519/NFT/Alias 56 | * @param[in] hash Optional, a NFT/Alias ID in the utxo_output 57 | * @param[in] hash_len A length of hash array, 0 if hash is NULL 58 | * @param[in] keypair Optional, ed25519 keypair of this input (this is for ed25519 address) 59 | * @param[out] sign_data_list Signing data list which will be populated by a new element 60 | * @return int 0 on success 61 | */ 62 | int signing_data_add(address_t* unlock_address, byte_t hash[], uint8_t hash_len, ed25519_keypair_t* keypair, 63 | signing_data_list_t** sign_data_list); 64 | 65 | /** 66 | * @brief Get number of elements in a signing data list 67 | * 68 | * @param[in] signing_data_list Signing data list 69 | * @return uint8_t Number of elements 70 | */ 71 | uint8_t signing_data_count(signing_data_list_t* signing_data_list); 72 | 73 | /** 74 | * @brief Find a signing data by a given index 75 | * 76 | * @param[in] signing_data_list Signing data list 77 | * @param[in] index An index in the list 78 | * @return signing_data_t* or NULL pointer 79 | */ 80 | signing_data_t* signing_get_data_by_index(signing_data_list_t* signing_data_list, uint8_t index); 81 | 82 | /** 83 | * @brief Create unlocks and sign transaction 84 | * 85 | * @param[in] essence_hash An essence hash 86 | * @param[in] essence_hash_len Length of an essence hash array 87 | * @param[in] inputs An UTXO input list 88 | * @param[in] sign_data_list Signing data list 89 | * @param[out] unlock_list A list of unlocks which will be created 90 | * @return int 0 on success 91 | */ 92 | int signing_transaction_sign(byte_t essence_hash[], uint8_t essence_hash_len, utxo_inputs_list_t* inputs, 93 | signing_data_list_t* sign_data_list, unlock_list_t** unlock_list); 94 | 95 | #ifdef __cplusplus 96 | } 97 | #endif 98 | 99 | #endif // __CORE_MODELS_SIGNING_H__ 100 | -------------------------------------------------------------------------------- /src/core/utils/allocator.h: -------------------------------------------------------------------------------- 1 | // Copyright 2021 IOTA Stiftung 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | #ifndef __CORE_UTILS_ALLOCATOR_H__ 5 | #define __CORE_UTILS_ALLOCATOR_H__ 6 | 7 | /** 8 | * @brief Memory Allocator abstract layer 9 | * 10 | */ 11 | 12 | #ifdef USE_JEMALLOC 13 | #warning "Use jemalloc allocator" 14 | #include "jemalloc/jemalloc.h" 15 | #else 16 | #include 17 | #endif 18 | 19 | #ifdef __cplusplus 20 | extern "C" { 21 | #endif 22 | 23 | #ifdef __cplusplus 24 | } 25 | #endif 26 | 27 | #endif 28 | -------------------------------------------------------------------------------- /src/core/utils/bech32.h: -------------------------------------------------------------------------------- 1 | // Copyright 2020 IOTA Stiftung 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | #ifndef __CORE_UTILS_BECH32_H__ 5 | #define __CORE_UTILS_BECH32_H__ 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | // A Bech32[2] string is at most 90 characters long and consists of: [HRP, "1", data] 12 | #define BECH32_MAX_STRING_LEN 90 13 | 14 | #ifdef __cplusplus 15 | extern "C" { 16 | #endif 17 | 18 | /** 19 | * @brief bech32 encode 20 | * 21 | * @param[out] output The output bech32 string 22 | * @param[in] hrp A human-readable string 23 | * @param[in] data The encode data in bytes 24 | * @param[in] data_len The length of data 25 | * @return int 1 on success 26 | */ 27 | int bech32_encode(char *output, const char *hrp, const uint8_t *data, size_t data_len); 28 | 29 | /** 30 | * @brief bech32 decode 31 | * 32 | * @param[out] hrp The human-readable part 33 | * @param[out] data The data in bytes 34 | * @param[out] data_len The length of data 35 | * @param[in] input A bech32 string 36 | * @return int 1 on success 37 | */ 38 | int bech32_decode(char *hrp, uint8_t *data, size_t *data_len, const char *input); 39 | 40 | /** 41 | * @brief Convert raw binary to X bit per byte encoded byte string. 42 | * 43 | * @param[out] out A outout buffer hold the encoded string 44 | * @param[in] outlen The length of output buffer 45 | * @param[in] outbits The output bits per byte 46 | * @param[in] in The input data buffer 47 | * @param[in] inlen The length of input buffer 48 | * @param[in] inbits The input bits per byte 49 | * @param[in] pad set 1 to add padding 50 | * @return int 1 on success 51 | */ 52 | int bech32_convert_bits(uint8_t *out, size_t *outlen, int outbits, const uint8_t *in, size_t inlen, int inbits, 53 | int pad); 54 | 55 | /** 56 | * @brief Validates Bech32 address length 57 | * 58 | * https://github.com/bitcoin/bips/blob/master/bip-0173.mediawiki 59 | * the length of Bech32 should be (HRP length) < x <= 90, where the HRP length is 1 to 83 ASCII characters 60 | * 61 | * @param[in] addr A string of Bech32 address 62 | * @return true Valid Bech32 address 63 | * @return false Invalid Bech32 address 64 | */ 65 | bool is_valid_bech32_len(char const *const addr); 66 | 67 | #ifdef __cplusplus 68 | } 69 | #endif 70 | 71 | #endif 72 | -------------------------------------------------------------------------------- /src/core/utils/iota_str.c: -------------------------------------------------------------------------------- 1 | // Copyright 2021 IOTA Stiftung 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | #include "core/utils/iota_str.h" 5 | #include "core/utils/allocator.h" 6 | 7 | iota_str_t *iota_str_new(char const s[]) { 8 | iota_str_t *istr = malloc(sizeof(iota_str_t)); 9 | if (!istr) { 10 | return NULL; 11 | } 12 | 13 | istr->len = strlen(s); 14 | istr->cap = istr->len + 1; 15 | istr->buf = malloc(istr->cap); 16 | if (!istr->buf) { 17 | free(istr); 18 | return NULL; 19 | } 20 | 21 | memcpy(istr->buf, s, istr->len); 22 | istr->buf[istr->len] = '\0'; 23 | return istr; 24 | } 25 | 26 | void iota_str_destroy(iota_str_t *istr) { 27 | if (istr) { 28 | if (istr->buf) { 29 | free(istr->buf); 30 | } 31 | free(istr); 32 | } 33 | } 34 | 35 | int iota_str_appendn(iota_str_t *istr, char const s[], size_t len) { 36 | // needed capacity 37 | size_t needed_cap = istr->len + len + 1; 38 | 39 | if (needed_cap > istr->cap) { 40 | // request more buffer 41 | istr->buf = realloc(istr->buf, needed_cap); 42 | if (istr->buf == NULL) { 43 | return -1; 44 | } 45 | istr->cap = needed_cap; 46 | } 47 | 48 | // copy c_string to buffer 49 | memcpy(istr->buf + istr->len, s, len); 50 | istr->len += len; 51 | // append terminator 52 | istr->buf[istr->len] = '\0'; 53 | return 0; 54 | } 55 | 56 | iota_str_t *iota_str_clonen(iota_str_t *istr, size_t len) { 57 | iota_str_t *clone = malloc(sizeof(iota_str_t)); 58 | if (!clone) { 59 | return NULL; 60 | } 61 | 62 | clone->len = len; 63 | clone->cap = len + 1; 64 | clone->buf = malloc(istr->cap); 65 | if (!clone->buf) { 66 | free(clone); 67 | return NULL; 68 | } 69 | 70 | memcpy(clone->buf, istr->buf, len); 71 | clone->buf[clone->len] = '\0'; 72 | return clone; 73 | } 74 | 75 | iota_str_t *iota_str_reserve(size_t len) { 76 | iota_str_t *istr = malloc(sizeof(iota_str_t)); 77 | if (!istr) { 78 | return NULL; 79 | } 80 | 81 | istr->len = 0; 82 | istr->cap = len; 83 | istr->buf = malloc(istr->cap); 84 | if (!istr->buf) { 85 | free(istr); 86 | return NULL; 87 | } 88 | 89 | return istr; 90 | } -------------------------------------------------------------------------------- /src/core/utils/iota_str.h: -------------------------------------------------------------------------------- 1 | // Copyright 2021 IOTA Stiftung 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | #ifndef __CORE_UTILS_IOTA_STR_H__ 5 | #define __CORE_UTILS_IOTA_STR_H__ 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | /** 12 | * @brief A mutable string buffer. 13 | * 14 | */ 15 | typedef struct { 16 | char *buf; /**< string pointer */ 17 | size_t cap; /**< allocated capacity */ 18 | size_t len; /**< string length */ 19 | } iota_str_t; 20 | 21 | #ifdef __cplusplus 22 | extern "C" { 23 | #endif 24 | 25 | /** 26 | * @brief New a string object from c_string. 27 | * 28 | * @param[in] s A c_string 29 | * @return iota_str_t* The pointer to string object, NULL on failed. 30 | */ 31 | iota_str_t *iota_str_new(char const *s); 32 | 33 | /** 34 | * @brief Appends a sized c_string 35 | * 36 | * @param[out] istr A pointer to a string object 37 | * @param[in] s A c_string 38 | * @param[in] len the size of characters 39 | * @return int 0 on success 40 | */ 41 | int iota_str_appendn(iota_str_t *istr, char const s[], size_t len); 42 | 43 | /** 44 | * @brief Appends a c_string 45 | * 46 | * @param[out] istr A pointer to a string object 47 | * @param[in] s A c_string 48 | * @return int 0 on success 49 | */ 50 | static inline int iota_str_append(iota_str_t *istr, char const s[]) { return iota_str_appendn(istr, s, strlen(s)); } 51 | 52 | /** 53 | * @brief Appends a char 54 | * 55 | * @param[out] istr A pointer to a string object 56 | * @param[in] c A character 57 | * @return int 0 on success 58 | */ 59 | static inline int iota_str_append_char(iota_str_t *istr, char c) { return iota_str_appendn(istr, &c, 1); } 60 | 61 | /** 62 | * @brief Deallocates the string object 63 | * 64 | * @param[in] istr the string object 65 | */ 66 | void iota_str_destroy(iota_str_t *istr); 67 | 68 | /** 69 | * @brief Clones a string with a length 70 | * 71 | * @param[in] istr A pointer to a string object 72 | * @param[in] len the length for clone 73 | * @return iota_str_t* A cloned string object 74 | */ 75 | iota_str_t *iota_str_clonen(iota_str_t *istr, size_t len); 76 | 77 | /** 78 | * @brief Clones a string object 79 | * 80 | * @param[in] istr A pointer to a string object 81 | * @return iota_str_t* A cloned string object 82 | */ 83 | static inline iota_str_t *iota_str_clone(iota_str_t *istr) { return iota_str_clonen(istr, istr->len); } 84 | 85 | /** 86 | * @brief Compare two strings 87 | * 88 | * Comparing NULL string or string without null terminator are undefined behaviours. 89 | * 90 | * @param[in] a string A 91 | * @param[in] b string B 92 | * @return int 93 | */ 94 | static inline int iota_str_cmp(iota_str_t const *a, iota_str_t const *b) { return strcmp(a->buf, b->buf); }; 95 | 96 | /** 97 | * @brief New a string object and reserves a specific length 98 | * 99 | * @param[in] len the length to reserve 100 | * @return iota_str_t* 101 | */ 102 | iota_str_t *iota_str_reserve(size_t len); 103 | 104 | #ifdef __cplusplus 105 | } 106 | #endif 107 | 108 | #endif 109 | -------------------------------------------------------------------------------- /src/core/utils/macros.h: -------------------------------------------------------------------------------- 1 | // Copyright 2022 IOTA Stiftung 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | #ifndef __CORE_UTILS_MACROS_H__ 5 | #define __CORE_UTILS_MACROS_H__ 6 | 7 | #include 8 | #include 9 | 10 | // Macro for unused function arguments 11 | #ifndef UNUSED 12 | #define UNUSED(x) (void)(x) 13 | #endif 14 | 15 | // Get the hex bytes of the given binary 16 | #define BIN_TO_HEX_BYTES(x) (x * 2) 17 | // Get the hex string bytes of the given binary 18 | #define BIN_TO_HEX_STR_BYTES(x) (BIN_TO_HEX_BYTES(x) + 1) 19 | // Get the string bytes of the given binary 20 | #define BIN_TO_STR_BYTES(x) (x + 1) 21 | 22 | /* clang-format off */ 23 | /** 24 | * @brief Returns string representing tabulator indentation 25 | * 26 | * @param[in] i Indentation level. The range of i is between 0 and 5. 27 | */ 28 | #define PRINT_INDENTATION(i) \ 29 | ((i) == 0 ? "\0" \ 30 | : (i) == 1 ? "\t\0" \ 31 | : (i) == 2 ? "\t\t\0" \ 32 | : (i) == 3 ? "\t\t\t\0" \ 33 | : (i) == 4 ? "\t\t\t\t\0" \ 34 | : (i) == 5 ? "\t\t\t\t\t\0" \ 35 | : "\0") 36 | /* clang-format on */ 37 | 38 | #endif 39 | -------------------------------------------------------------------------------- /src/core/utils/slip10.h: -------------------------------------------------------------------------------- 1 | // Copyright 2020 IOTA Stiftung 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | #ifndef __CORE_UTILS_SLIP10_H__ 5 | #define __CORE_UTILS_SLIP10_H__ 6 | 7 | #include 8 | 9 | #include "core/utils/byte_buffer.h" 10 | 11 | #define BIP32_HARDENED (1UL << 31) 12 | #define MAX_BIP32_PATH 32 13 | #define SLIP10_PUBLIC_KEY_BYTES 33 14 | #define SLIP10_PRIVATE_KEY_BYTES 32 15 | #define SLIP10_CHAIN_CODE_BYTES 32 16 | 17 | typedef enum { SECP256K1_CURVE, NIST_P256_CURVE, ED25519_CURVE } slip10_curve_t; 18 | 19 | /** 20 | * @brief Slip10 key structure 21 | * 22 | */ 23 | typedef struct { 24 | byte_t key[SLIP10_PRIVATE_KEY_BYTES]; ///< private key, 32 bytes 25 | byte_t chain_code[SLIP10_CHAIN_CODE_BYTES]; ///< chain code, 32 bytes 26 | } slip10_key_t; 27 | 28 | /** 29 | * @brief BIP32 path structure 30 | * 31 | */ 32 | typedef struct { 33 | uint32_t path[MAX_BIP32_PATH]; ///< the string of path, 32 bytes 34 | int len; ///< the length of the path 35 | } bip32_path_t; 36 | 37 | #ifdef __cplusplus 38 | extern "C" { 39 | #endif 40 | 41 | /** 42 | * @brief Gets bip32 path from string 43 | * 44 | * @param[in] str A bip32 path string 45 | * @param[out] path The output path 46 | * @return int 0 on successful 47 | */ 48 | int slip10_parse_path(char str[], bip32_path_t* path); 49 | 50 | /** 51 | * @brief Derives key from given seed and path 52 | * 53 | * @param[in] seed A seed in byte array 54 | * @param[in] seed_len The length of seed 55 | * @param[in] path The string of path 56 | * @param[in] curve The type of curve, only support ed25519 57 | * @param[out] key The derived key 58 | * @return int 0 on successful 59 | */ 60 | int slip10_key_from_path(byte_t seed[], size_t seed_len, char path[], slip10_curve_t curve, slip10_key_t* key); 61 | 62 | /** 63 | * @brief Get public key from the derived key 64 | * 65 | * @param[in] curve The type of curve, only support ed25519 66 | * @param[in] key A slip-10 key 67 | * @param[out] pub_key The public key 68 | * @return int 0 on successful 69 | */ 70 | int slip10_public_key(slip10_curve_t curve, slip10_key_t* key, byte_t pub_key[]); 71 | 72 | #ifdef __cplusplus 73 | } 74 | #endif 75 | 76 | #endif 77 | -------------------------------------------------------------------------------- /src/core/utils/uint256.h: -------------------------------------------------------------------------------- 1 | // Copyright 2021 IOTA Stiftung 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | #ifndef __CORE_UTILS_UINT256_H__ 5 | #define __CORE_UTILS_UINT256_H__ 6 | 7 | #include 8 | #include 9 | 10 | // Maximum possible length of a string representing 256-bit number. 78 characters + string termination character 11 | #define STRING_NUMBER_MAX_CHARACTERS 79 12 | 13 | /** 14 | * @brief A 256 bit number object. 15 | * 16 | * Custom implementation for 256 bit number representation. 17 | * Only a little endian format is supported at the moment. 18 | * 19 | */ 20 | typedef struct { 21 | uint64_t bits[4]; ///< 256 bit number represented in a little endian format 22 | } uint256_t; 23 | 24 | #ifdef __cplusplus 25 | extern "C" { 26 | #endif 27 | 28 | /** 29 | * @brief New uint256 object from c_string representing a 256 bit number. 30 | * 31 | * @param[in] str A c_string representing a 256 bit number. 32 | * @return uint256_t* Pointer to uint256 object, NULL on failed. 33 | */ 34 | uint256_t *uint256_from_str(char const *str); 35 | 36 | /** 37 | * @brief New uint256 object from hex c_string representing a 256 bit number. 38 | * 39 | * @param[in] str A hex c_string representing a 256 bit number. 40 | * @return uint256_t* Pointer to uint256 object, NULL on failed. 41 | */ 42 | uint256_t *uint256_from_hex_str(char const *str); 43 | 44 | /** 45 | * @brief Perform addition on two uint256 numbers. 46 | * 47 | * @param[out] sum The sum of two numbers. 48 | * @param[in] a The summand A. 49 | * @param[in] b The summand B. 50 | * @return true On success 51 | * @return false On failed 52 | */ 53 | bool uint256_add(uint256_t *sum, uint256_t *a, uint256_t *b); 54 | 55 | /** 56 | * @brief Perform subtraction on two uint256 numbers. 57 | * 58 | * @param[out] diff The difference of two numbers. 59 | * @param[in] min The minuend. 60 | * @param[in] sub The subtrahend. 61 | * @return true On success 62 | * @return false On failed 63 | */ 64 | bool uint256_sub(uint256_t *diff, uint256_t *min, uint256_t *sub); 65 | 66 | /** 67 | * @brief Compare two uint256 objects (numbers) 68 | * 69 | * @param[in] a A pointer to uint256 object 70 | * @param[in] b A pointer to uint256 object 71 | * @return int < 0 if a is smaller then b 72 | * @return int > 0 if a is greater than b 73 | * @return int 0 if a is equal to b 74 | */ 75 | int uint256_equal(uint256_t const *a, uint256_t const *b); 76 | 77 | /** 78 | * @brief Converts uint256 number to a string 79 | * 80 | * @param[in] num A pointer to uint256 object 81 | * @return Pointer to string object, NULL on failed. 82 | */ 83 | char *uint256_to_str(uint256_t *num); 84 | 85 | /** 86 | * @brief Converts uint256 number to a hex string 87 | * 88 | * @param[in] num A pointer to uint256 object 89 | * @return Pointer to string object, NULL on failed. 90 | */ 91 | char *uint256_to_hex_str(uint256_t *num); 92 | 93 | /** 94 | * @brief Clone uint256 object, it should be freed after use. 95 | * 96 | * @param[in] num A pointer to uint256 object for clone 97 | * @return uint256_t* New uint256 object 98 | */ 99 | uint256_t *uint256_clone(uint256_t const *const num); 100 | 101 | /** 102 | * @brief Free a unit256_t object 103 | * 104 | * @param[in] num A pointer to uint256 object 105 | */ 106 | void uint256_free(uint256_t *num); 107 | 108 | #ifdef __cplusplus 109 | } 110 | #endif 111 | 112 | #endif 113 | -------------------------------------------------------------------------------- /src/crypto/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | #[[ 2 | // Copyright 2020 IOTA Stiftung 3 | // SPDX-License-Identifier: Apache-2.0 4 | ]] 5 | 6 | add_library(iota_crypto STATIC) 7 | # the required minimum C standard 8 | set_target_properties(iota_crypto PROPERTIES C_STANDARD_REQUIRED NO C_STANDARD 99) 9 | 10 | target_sources( 11 | iota_crypto 12 | PRIVATE "iota_crypto.c" 13 | PUBLIC "iota_crypto.h" "constants.h") 14 | 15 | target_include_directories(iota_crypto PUBLIC "${PROJECT_SOURCE_DIR}/src" "${CMAKE_INSTALL_PREFIX}/include") 16 | 17 | target_compile_options(iota_crypto PRIVATE -Wall -Wextra) 18 | 19 | if(__ED25519_INCLUDE) 20 | target_compile_definitions(iota_crypto PUBLIC CRYPTO_USE_ED25519_DONNA) 21 | target_link_libraries(iota_crypto INTERFACE ed25519_donna) 22 | add_dependencies(iota_crypto ext_ed25519) 23 | endif() 24 | 25 | if(__BLAKE2_INCLUDE) 26 | target_compile_definitions(iota_crypto PUBLIC CRYPTO_USE_BLAKE2B_REF) 27 | target_link_libraries(iota_crypto INTERFACE blake2) 28 | add_dependencies(iota_crypto ext_blake2) 29 | endif() 30 | 31 | if(CryptoUse STREQUAL "openssl") 32 | target_compile_definitions(iota_crypto PUBLIC CRYPTO_USE_OPENSSL) 33 | target_include_directories(iota_crypto PUBLIC "${OPENSSL_INCLUDE_DIR}") 34 | target_link_libraries(iota_crypto INTERFACE ${OPENSSL_LIBRARIES}) 35 | elseif(CryptoUse STREQUAL "libsodium") 36 | target_compile_definitions(iota_crypto PUBLIC CRYPTO_USE_SODIUM) 37 | add_dependencies(iota_crypto sodium) 38 | target_link_libraries(iota_crypto INTERFACE sodium) 39 | elseif(CryptoUse STREQUAL "mbedtls") 40 | target_compile_definitions(iota_crypto PUBLIC CRYPTO_USE_MBEDTLS) 41 | add_dependencies(iota_crypto ext_mbedtls) 42 | target_link_libraries(iota_crypto INTERFACE mbedcrypto mbedtls mbedx509) 43 | endif() 44 | 45 | if(__JEMALLOC_INCLUDED) 46 | add_dependencies(iota_crypto jemalloc) 47 | target_link_libraries(iota_crypto PUBLIC jemalloc${CMAKE_STATIC_LIBRARY_SUFFIX} Threads::Threads) 48 | target_compile_definitions(iota_crypto PUBLIC USE_JEMALLOC) 49 | target_link_options(iota_crypto PUBLIC -Wl,--no-as-needed -ldl) 50 | endif() 51 | 52 | # install headers 53 | install(TARGETS iota_crypto DESTINATION "${CMAKE_INSTALL_PREFIX}/lib") 54 | install(FILES "${PROJECT_SOURCE_DIR}/src/crypto/iota_crypto.h" DESTINATION "${CMAKE_INSTALL_PREFIX}/include/crypto") 55 | -------------------------------------------------------------------------------- /src/crypto/constants.h: -------------------------------------------------------------------------------- 1 | // Copyright 2022 IOTA Stiftung 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | #ifndef __CRYPTO_CONSTANTS_H__ 5 | #define __CRYPTO_CONSTANTS_H__ 6 | 7 | #define ED_SEED_BYTES 32 // ed25519 seed bytes 8 | #define ED_PUBLIC_KEY_BYTES 32 // ed2519 public key bytes 9 | #define ED_PRIVATE_KEY_BYTES 64 // ed25519 secret/private key bytes 10 | #define ED_SIGNATURE_BYTES 64 // ed25519 signature bytes 11 | 12 | #define CRYPTO_SHA512_KEY_BYTES 32 // crypto_auth_hmacsha512_KEYBYTES 13 | #define CRYPTO_SHA512_HASH_BYTES 64 // crypto_auth_hmacsha512_BYTES 14 | #define CRYPTO_SHA256_KEY_BYTES 32 // crypto_auth_hmacsha256_KEYBYTES 15 | #define CRYPTO_SHA256_HASH_BYTES 32 // crypto_auth_hmacsha256_BYTES 16 | #define CRYPTO_BLAKE2B_256_HASH_BYTES 32 // crypto_generichash_blake2b_BYTES 17 | #define CRYPTO_BLAKE2B_160_HASH_BYTES 20 // crypto_generichash_blake2b-160_BYTES 18 | 19 | #endif 20 | -------------------------------------------------------------------------------- /src/iota_client.h: -------------------------------------------------------------------------------- 1 | // Copyright 2022 IOTA Stiftung 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | #ifndef __IOTA_CLIENT_H__ 5 | #define __IOTA_CLIENT_H__ 6 | 7 | #include "client/api/restful/get_block.h" 8 | #include "client/api/restful/get_block_metadata.h" 9 | #include "client/api/restful/get_milestone.h" 10 | #include "client/api/restful/get_node_info.h" 11 | #include "client/api/restful/get_output.h" 12 | #include "client/api/restful/get_outputs_id.h" 13 | #include "client/api/restful/get_tips.h" 14 | #include "client/api/restful/get_transaction_included_block.h" 15 | #include "client/api/restful/response_error.h" 16 | #include "client/api/restful/send_block.h" 17 | #include "client/api/restful/send_tagged_data.h" 18 | #include "core/address.h" 19 | #include "core/utils/bech32.h" 20 | #include "core/utils/byte_buffer.h" 21 | #include "core/utils/iota_str.h" 22 | #include "core/utils/macros.h" 23 | #include "core/utils/uint256.h" 24 | #include "crypto/iota_crypto.h" 25 | #include "wallet/output_alias.h" 26 | #include "wallet/output_basic.h" 27 | #include "wallet/output_foundry.h" 28 | #include "wallet/wallet.h" 29 | 30 | #endif 31 | -------------------------------------------------------------------------------- /src/wallet/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | #[[ 2 | // Copyright 2020 IOTA Stiftung 3 | // SPDX-License-Identifier: Apache-2.0 4 | ]] 5 | 6 | add_library(iota_wallet STATIC) 7 | 8 | # the required minimum C standard 9 | set_target_properties(iota_wallet PROPERTIES C_STANDARD_REQUIRED NO C_STANDARD 99) 10 | 11 | target_sources( 12 | iota_wallet 13 | PRIVATE "wallet.c" 14 | "output_basic.c" 15 | "output_alias.c" 16 | "output_foundry.c" 17 | "bip39.c" 18 | PUBLIC "wallet.h" "output_basic.h" "output_alias.h" "output_foundry.h") 19 | 20 | target_include_directories( 21 | iota_wallet PUBLIC "${PROJECT_SOURCE_DIR}/src" "${CURL_INCLUDE_DIRS}" 22 | "${CMAKE_INSTALL_PREFIX}/include/cjson" # for esp32 compatibility 23 | ) 24 | 25 | add_dependencies(iota_wallet iota_client) 26 | 27 | target_compile_options(iota_wallet PRIVATE -Wall -Wextra) 28 | 29 | if(BIP39_ENGLISH_ONLY) 30 | target_compile_definitions(iota_wallet PUBLIC BIP39_ENGLISH_ONLY) 31 | endif() 32 | 33 | target_link_libraries(iota_wallet PUBLIC iota_client) 34 | 35 | # install client lib and headers 36 | install(TARGETS iota_wallet DESTINATION "${CMAKE_INSTALL_PREFIX}/lib") 37 | install( 38 | DIRECTORY "${PROJECT_SOURCE_DIR}/src/wallet/" 39 | DESTINATION "${CMAKE_INSTALL_PREFIX}/include/wallet" 40 | FILES_MATCHING 41 | PATTERN "*.h") 42 | -------------------------------------------------------------------------------- /src/wallet/output_alias.h: -------------------------------------------------------------------------------- 1 | // Copyright 2022 IOTA Stiftung 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | #ifndef __WALLET_OUTPUT_ALIAS_H__ 5 | #define __WALLET_OUTPUT_ALIAS_H__ 6 | 7 | #include 8 | 9 | #include "wallet/wallet.h" 10 | 11 | #ifdef __cplusplus 12 | extern "C" { 13 | #endif 14 | 15 | /** 16 | * @brief Send transaction which creates a new alias output 17 | * 18 | * @param[in] w A wallet instance 19 | * @param[in] sender_change A sender change index which is {0, 1}, also known as a wallet chain 20 | * @param[in] sender_index A sender address index 21 | * @param[in] send_amount An amount to transfer 22 | * @param[in] state_ctrl_addr A state controller address 23 | * @param[in] govern_addr A governor address 24 | * @param[in] foundry_counter A foundry counter 25 | * @param[out] alias_addr A newly created alias address 26 | * @param[out] blk_res A response of a transfer 27 | * 28 | * @return int 0 on success 29 | */ 30 | int wallet_alias_output_create(iota_wallet_t* w, bool sender_change, uint32_t sender_index, uint64_t const send_amount, 31 | address_t* state_ctrl_addr, address_t* govern_addr, uint32_t foundry_counter, 32 | address_t* alias_addr, res_send_block_t* blk_res); 33 | 34 | /** 35 | * @brief Send alias state transition transaction 36 | * 37 | * @param[in] w A wallet instance 38 | * @param[in] alias_id An alias identifier 39 | * @param[in] state_ctrl_change A state controller change index which is {0, 1}, also known as a wallet chain 40 | * @param[in] state_ctrl_index A state controller address index 41 | * @param[in] govern_addr A governor address 42 | * @param[in] foundry_counter A foundry counter number 43 | * @param[in] send_amount An amount to transfer 44 | * @param[in] outputs An outputs which will be created in a transaction in addition of possible remainder output 45 | * @param[in] minted_native_tokens A list of minted native tokens which will be created in a transaction 46 | * @param[out] blk_res A response of a transfer 47 | * 48 | * @return int 0 on success 49 | */ 50 | int wallet_alias_output_state_transition(iota_wallet_t* w, byte_t alias_id[], bool state_ctrl_change, 51 | uint32_t state_ctrl_index, address_t* govern_addr, uint32_t foundry_counter, 52 | uint64_t send_amount, utxo_outputs_list_t* outputs, 53 | native_tokens_list_t* minted_native_tokens, res_send_block_t* blk_res); 54 | 55 | /** 56 | * @brief Send transaction which destroys alias output 57 | * 58 | * @param[in] w A wallet instance 59 | * @param[in] alias_id An alias identifier 60 | * @param[in] govern_change A governor change index which is {0, 1}, also known as a wallet chain 61 | * @param[in] govern_index A governor address index 62 | * @param[in] recv_addr A receiver address 63 | * @param[out] blk_res A response of a transfer 64 | * 65 | * @return int 0 on success 66 | */ 67 | int wallet_alias_output_destroy(iota_wallet_t* w, byte_t alias_id[], bool govern_change, uint32_t govern_index, 68 | address_t* recv_addr, res_send_block_t* blk_res); 69 | 70 | #ifdef __cplusplus 71 | } 72 | #endif 73 | 74 | #endif // __WALLET_OUTPUT_ALIAS_H__ 75 | -------------------------------------------------------------------------------- /src/wallet/output_basic.h: -------------------------------------------------------------------------------- 1 | // Copyright 2022 IOTA Stiftung 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | #ifndef __WALLET_OUTPUT_BASIC_H__ 5 | #define __WALLET_OUTPUT_BASIC_H__ 6 | 7 | #include 8 | 9 | #include "client/api/restful/get_outputs_id.h" 10 | #include "core/models/outputs/output_basic.h" 11 | #include "core/models/signing.h" 12 | #include "wallet/wallet.h" 13 | 14 | #ifdef __cplusplus 15 | extern "C" { 16 | #endif 17 | 18 | /** 19 | * @brief Create and return a basic output 20 | * 21 | * @param[in] recv_addr A receiver address 22 | * @param[in] amount An amount to sent 23 | * @param[in] native_tokens A native tokens to sent 24 | * 25 | * @return output_basic_t* or NULL on failure 26 | */ 27 | output_basic_t* wallet_basic_output_create(address_t* recv_addr, uint64_t amount, native_tokens_list_t* native_tokens); 28 | 29 | /** 30 | * @brief Get all senders unspent basic output IDs from a network 31 | * 32 | * @param[in] w A wallet instance 33 | * @param[in] send_addr A sender address 34 | * 35 | * @return res_outputs_id_t* or NULL on failure 36 | */ 37 | res_outputs_id_t* wallet_get_unspent_basic_output_ids(iota_wallet_t* w, address_t* send_addr); 38 | 39 | /** 40 | * @brief Send basic transaction which transfers IOTA tokens to an address 41 | * 42 | * @param[in] w A wallet instance 43 | * @param[in] sender_change A sender change index which is {0, 1}, also known as a wallet chain 44 | * @param[in] sender_index A sender address index 45 | * @param[in] send_amount An amount to sent 46 | * @param[in] send_native_tokens A native tokens to sent 47 | * @param[in] recv_addr A receiver address 48 | * @param[out] blk_res A response of a block transfer 49 | * 50 | * @return int 0 on success 51 | */ 52 | int wallet_basic_output_send(iota_wallet_t* w, bool sender_change, uint32_t sender_index, uint64_t send_amount, 53 | native_tokens_list_t* send_native_tokens, address_t* recv_addr, res_send_block_t* blk_res); 54 | 55 | #ifdef __cplusplus 56 | } 57 | #endif 58 | 59 | #endif // __WALLET_OUTPUT_BASIC_H__ 60 | -------------------------------------------------------------------------------- /src/wallet/output_foundry.h: -------------------------------------------------------------------------------- 1 | // Copyright 2022 IOTA Stiftung 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | #ifndef __WALLET_OUTPUT_FOUNDRY_H__ 5 | #define __WALLET_OUTPUT_FOUNDRY_H__ 6 | 7 | #include "core/utils/uint256.h" 8 | #include "wallet/wallet.h" 9 | 10 | #ifdef __cplusplus 11 | extern "C" { 12 | #endif 13 | 14 | /** 15 | * @brief Send mint native token transaction 16 | * 17 | * @param[in] w A wallet instance 18 | * @param[in] alias_addr The alias address 19 | * @param[in] state_ctrl_change The state controller change index which is {0, 1}, also known as wallet chain 20 | * @param[in] state_ctrl_index The state controller address index 21 | * @param[in] govern_addr The governor address 22 | * @param[in] receiver_addr The receiver address to which newly minted native tokens will be transferred 23 | * @param[in] max_supply The maximum supply of newly minted native tokens 24 | * @param[in] minted_tokens The number of newly minted native tokens 25 | * @param[in] serial_number The serial number of new foundry 26 | * @param[in] foundry_counter The foundry counter number 27 | * @param[out] blk_res The response of the transfer 28 | * 29 | * @return int 0 on success 30 | */ 31 | int wallet_foundry_output_mint_native_tokens(iota_wallet_t* w, address_t* alias_addr, bool state_ctrl_change, 32 | uint32_t state_ctrl_index, address_t* govern_addr, 33 | address_t* receiver_addr, uint256_t* max_supply, uint256_t* minted_tokens, 34 | uint32_t serial_number, uint32_t foundry_counter, 35 | res_send_block_t* blk_res); 36 | 37 | #ifdef __cplusplus 38 | } 39 | #endif 40 | 41 | #endif // __WALLET_OUTPUT_FOUNDRY_H__ 42 | -------------------------------------------------------------------------------- /src/wallet/wordlists/README.md: -------------------------------------------------------------------------------- 1 | Wordlists are from [bips/bd943663/bip-0039](https://github.com/bitcoin/bips/tree/bd943663d6908679ca4f94276589ef402f865739/bip-0039) 2 | 3 | Support Languages: 4 | 5 | | Language | ISO 639-1 | 6 | |:--------:|:---------:| 7 | | English | en | 8 | | Japanese | ja | 9 | | Korean | ko | 10 | | Spanish | es | 11 | | Chinese Traditional | zh_hant | 12 | | Chinese Simplified | zh_hans | 13 | | French | fr | 14 | | Italian | it | 15 | | Czech | cs | 16 | | Portuguese | pt | 17 | 18 | 19 | Language header files are auto-generated by wordlists_header.py script 20 | 21 | ``` 22 | ./wordlist_header.py english.txt en > english.h 23 | ./wordlist_header.py japanese.txt ja > japanese.h 24 | ./wordlist_header.py korean.txt ko > korean.h 25 | ./wordlist_header.py spanish.txt es > spanish.h 26 | ./wordlist_header.py chinese_traditional.txt zh_hant > chinese_traditional.h 27 | ./wordlist_header.py chinese_simplified.txt zh_hans > chinese_simplified.h 28 | ./wordlist_header.py french.txt fr > french.h 29 | ./wordlist_header.py italian.txt it > italian.h 30 | ./wordlist_header.py czech.txt cs > czech.h 31 | ./wordlist_header.py portuguese.txt pt > portuguese.h 32 | ``` 33 | -------------------------------------------------------------------------------- /src/wallet/wordlists/word.h: -------------------------------------------------------------------------------- 1 | // Copyright 2021 IOTA Stiftung 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | #ifndef __WALLE__WORDLISTS_WORD_H__ 5 | #define __WALLE__WORDLISTS_WORD_H__ 6 | 7 | #include 8 | 9 | /** 10 | * @brief The word object for wordlist tables. 11 | * 12 | */ 13 | typedef struct word { 14 | char *p; ///< a pointer to the string 15 | size_t len; ///< the length of string, null terminator is excluded 16 | } word_t; 17 | 18 | #endif -------------------------------------------------------------------------------- /src/wallet/wordlists/wordlist_header.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env python3 2 | 3 | # Copyright 2021 IOTA Stiftung 4 | # SPDX-License-Identifier: Apache-2.0 5 | 6 | import sys 7 | import os.path 8 | import datetime 9 | 10 | 11 | def main(): 12 | w_file = sys.argv[1] 13 | lan_prefix = sys.argv[2] 14 | with open(w_file, mode='r', encoding="utf-8") as wf: 15 | word_list = [l.strip() for l in wf.readlines()] 16 | 17 | if len(word_list) != 2048: 18 | print("must have 2048 words in the wordlist") 19 | sys.exit() 20 | 21 | # print(word_list) 22 | print("/* ===Auto Generated via " + 23 | os.path.basename(sys.argv[0]) + " do not modify!!=== */\n") 24 | print("// Copyright " + str(datetime.datetime.now().year) + " IOTA Stiftung") 25 | print("// SPDX-License-Identifier: Apache-2.0\n") 26 | print("#ifndef __WALLE__WORDLISTS_" + lan_prefix.upper() + "_H__") 27 | print("#define __WALLE__WORDLISTS_" + lan_prefix.upper() + "_H__\n") 28 | print('#include "wallet/wordlists/word.h"\n') 29 | print('static word_t ' + lan_prefix + '_word[] = {') 30 | for w in word_list: 31 | print(' {"'+w+'", ' + str(len(w.encode('utf-8'))) + '},') 32 | print('};\n') 33 | print("#endif\n") 34 | 35 | 36 | if __name__ == "__main__": 37 | main() 38 | -------------------------------------------------------------------------------- /tests/client/api_json_parser/test_common.c: -------------------------------------------------------------------------------- 1 | // Copyright 2022 IOTA Stiftung 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | #include 5 | 6 | #include "client/api/json_parser/common.h" 7 | #include "client/constants.h" 8 | #include "core/utils/macros.h" 9 | #include "unity/unity.h" 10 | 11 | void setUp(void) {} 12 | 13 | void tearDown(void) {} 14 | 15 | void test_parse_ed25519_address() { 16 | char const* const json_res = 17 | "{\"address\":{\"type\":0,\"pubKeyHash\":" 18 | "\"0x194eb32b9b6c61207192c7073562a0b3adf50a7c1f268182b552ec8999380acb\"}}"; 19 | cJSON* json_obj = cJSON_Parse(json_res); 20 | TEST_ASSERT_NOT_NULL(json_obj); 21 | 22 | address_t address; 23 | int result = json_parser_common_address_deserialize(json_obj, JSON_KEY_ADDR, &address); 24 | TEST_ASSERT_EQUAL_INT(0, result); 25 | 26 | address_t test_addr; 27 | test_addr.type = ADDRESS_TYPE_ED25519; 28 | hex_2_bin("194eb32b9b6c61207192c7073562a0b3adf50a7c1f268182b552ec8999380acb", BIN_TO_HEX_BYTES(ED25519_PUBKEY_BYTES), 29 | NULL, test_addr.address, ED25519_PUBKEY_BYTES); 30 | TEST_ASSERT_TRUE(address_equal(&test_addr, &address)); 31 | 32 | cJSON_Delete(json_obj); 33 | } 34 | 35 | void test_parse_alias_address() { 36 | char const* const json_res = 37 | "{\"address\":{\"type\":8,\"aliasId\":" 38 | "\"0x01aa8d202a51b575eb9248b2d580dc6149508ff094fc0ed79c25486935597248\"}}"; 39 | cJSON* json_obj = cJSON_Parse(json_res); 40 | TEST_ASSERT_NOT_NULL(json_obj); 41 | 42 | address_t address; 43 | int result = json_parser_common_address_deserialize(json_obj, JSON_KEY_ADDR, &address); 44 | TEST_ASSERT_EQUAL_INT(0, result); 45 | 46 | address_t test_addr; 47 | test_addr.type = ADDRESS_TYPE_ALIAS; 48 | hex_2_bin("01aa8d202a51b575eb9248b2d580dc6149508ff094fc0ed79c25486935597248", BIN_TO_HEX_BYTES(ALIAS_ID_BYTES), NULL, 49 | test_addr.address, ALIAS_ID_BYTES); 50 | TEST_ASSERT_TRUE(address_equal(&test_addr, &address)); 51 | 52 | cJSON_Delete(json_obj); 53 | } 54 | 55 | void test_parse_nft_address() { 56 | char const* const json_res = 57 | "{\"address\":{\"type\":16,\"nftId\":" 58 | "\"0x19c82b32761fd8729a1a6c77f7c17597e4b9b01759794e52381f6a0050b0c11f\"}}"; 59 | cJSON* json_obj = cJSON_Parse(json_res); 60 | TEST_ASSERT_NOT_NULL(json_obj); 61 | 62 | address_t address; 63 | int result = json_parser_common_address_deserialize(json_obj, JSON_KEY_ADDR, &address); 64 | TEST_ASSERT_EQUAL_INT(0, result); 65 | 66 | address_t test_addr; 67 | test_addr.type = ADDRESS_TYPE_NFT; 68 | hex_2_bin("19c82b32761fd8729a1a6c77f7c17597e4b9b01759794e52381f6a0050b0c11f", BIN_TO_HEX_BYTES(NFT_ID_BYTES), NULL, 69 | test_addr.address, NFT_ID_BYTES); 70 | TEST_ASSERT_TRUE(address_equal(&test_addr, &address)); 71 | 72 | cJSON_Delete(json_obj); 73 | } 74 | 75 | void test_parse_unsupported_address_type() { 76 | char const* const json_res = 77 | "{\"address\":{\"type\":10,\"address\":" 78 | "\"0x19c82b32761fd8729a1a6c77f7c17597e4b9b01759794e52381f6a0050b0c11f\"}}"; 79 | cJSON* json_obj = cJSON_Parse(json_res); 80 | TEST_ASSERT_NOT_NULL(json_obj); 81 | 82 | address_t address; 83 | int result = json_parser_common_address_deserialize(json_obj, JSON_KEY_ADDR, &address); 84 | TEST_ASSERT_EQUAL_INT(-1, result); 85 | 86 | cJSON_Delete(json_obj); 87 | } 88 | 89 | int main() { 90 | UNITY_BEGIN(); 91 | 92 | RUN_TEST(test_parse_ed25519_address); 93 | RUN_TEST(test_parse_alias_address); 94 | RUN_TEST(test_parse_nft_address); 95 | RUN_TEST(test_parse_unsupported_address_type); 96 | 97 | return UNITY_END(); 98 | } 99 | -------------------------------------------------------------------------------- /tests/client/api_restful/test_faucet_enqueue.c: -------------------------------------------------------------------------------- 1 | // Copyright 2022 IOTA Stiftung 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | #include 5 | #include 6 | 7 | #include "client/api/restful/faucet_enqueue.h" 8 | #include "test_config.h" 9 | #include "unity/unity.h" 10 | 11 | void setUp(void) {} 12 | 13 | void tearDown(void) {} 14 | 15 | void test_faucet_enqueue(void) { 16 | const char *const address_bech32 = "atoi1qqs7y6ec5vcg6cnz46vjrar2epc52lhksyar3a4zua7fg7ca08y5ymep8aa"; 17 | const char *const address_bech32_invalid = "pqoi1qqs7y6ec5vcg6cnz46vjrar2epc52lhksyar3a4zua7fg7ca08y5ymep8ab"; 18 | const char *const address_bech32_invalid_len = "atoi1qqs7y6ec5vcg6cnz46vjrar2epc52lhksyar3a4zua7fg7ca08y5"; 19 | 20 | iota_client_conf_t ctx = {.host = TEST_FAUCET_HOST, .port = TEST_FAUCET_PORT, .use_tls = TEST_IS_HTTPS}; 21 | 22 | res_faucet_enqueue_t res = {}; 23 | 24 | // Test NULL inputs 25 | TEST_ASSERT_EQUAL_INT(-1, req_tokens_to_addr_from_faucet(NULL, address_bech32, &res)); 26 | TEST_ASSERT_EQUAL_INT(-1, req_tokens_to_addr_from_faucet(&ctx, NULL, &res)); 27 | TEST_ASSERT_EQUAL_INT(-1, req_tokens_to_addr_from_faucet(&ctx, address_bech32, NULL)); 28 | 29 | // Test bech32 address with invalid len 30 | TEST_ASSERT_EQUAL_INT(0, req_tokens_to_addr_from_faucet(&ctx, address_bech32_invalid_len, &res)); 31 | TEST_ASSERT(res.is_error == true); 32 | res_err_free(res.u.error); 33 | 34 | // Test for invalid bech32 address 35 | res.is_error = false; 36 | TEST_ASSERT_EQUAL_INT(0, req_tokens_to_addr_from_faucet(&ctx, address_bech32_invalid, &res)); 37 | TEST_ASSERT(res.is_error == true); 38 | res_err_free(res.u.error); 39 | 40 | // Test for valid bech32 41 | res.is_error = false; 42 | TEST_ASSERT_EQUAL_INT(0, req_tokens_to_addr_from_faucet(&ctx, address_bech32, &res)); 43 | TEST_ASSERT(res.is_error == false); 44 | printf("Address : %s\n", res.u.req_res.bech32_address); 45 | printf("Waiting Requests : %d\n", res.u.req_res.waiting_reqs_count); 46 | } 47 | 48 | int main() { 49 | UNITY_BEGIN(); 50 | #if TEST_TANGLE_ENABLE 51 | RUN_TEST(test_faucet_enqueue); 52 | #endif 53 | return UNITY_END(); 54 | } 55 | -------------------------------------------------------------------------------- /tests/client/api_restful/test_get_health.c: -------------------------------------------------------------------------------- 1 | // Copyright 2020 IOTA Stiftung 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | #include 5 | #include 6 | 7 | #include "test_config.h" 8 | 9 | #include "client/api/restful/get_health.h" 10 | 11 | void setUp(void) {} 12 | 13 | void tearDown(void) {} 14 | 15 | void test_get_health() { 16 | iota_client_conf_t ctx = {.host = TEST_NODE_HOST, .port = TEST_NODE_PORT, .use_tls = TEST_IS_HTTPS}; 17 | bool health = false; 18 | TEST_ASSERT(get_health(&ctx, &health) == 0); 19 | } 20 | 21 | int main() { 22 | UNITY_BEGIN(); 23 | 24 | #if TEST_TANGLE_ENABLE 25 | RUN_TEST(test_get_health); 26 | #endif 27 | 28 | return UNITY_END(); 29 | } -------------------------------------------------------------------------------- /tests/client/api_restful/test_get_tips.c: -------------------------------------------------------------------------------- 1 | // Copyright 2020 IOTA Stiftung 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | #include 5 | 6 | #include "client/api/restful/get_tips.h" 7 | #include "test_config.h" 8 | #include "unity/unity.h" 9 | 10 | void setUp(void) {} 11 | 12 | void tearDown(void) {} 13 | 14 | void test_get_tips() { 15 | iota_client_conf_t ctx = {.host = TEST_NODE_HOST, .port = TEST_NODE_PORT, .use_tls = TEST_IS_HTTPS}; 16 | 17 | res_tips_t* res_tips = res_tips_new(); 18 | TEST_ASSERT_NOT_NULL(res_tips); 19 | 20 | TEST_ASSERT(get_tips(&ctx, res_tips) == 0); 21 | if (res_tips->is_error == true) { 22 | printf("Error: %s\n", res_tips->u.error->msg); 23 | } else { 24 | TEST_ASSERT(get_tips_id_count(res_tips) > 0); 25 | } 26 | 27 | res_tips_free(res_tips); 28 | } 29 | 30 | void test_deser_get_tips() { 31 | char const* const json_tips = 32 | "{\"tips\":[\"0x0a7c22aa43620d938146bcfc94a40804b26a5aaf3913bdc51b2836c47650de5c\"," 33 | "\"0x3a3ca52a4c7d96fed4eef037db4421231f09e63a817bcf913f33c0806e565de9\"," 34 | "\"0xa714ca72bb21d1e69b49a272713b9a1edc4d5679695680b5f36b907c0ed0d445\"," 35 | "\"0xea878b98a3eb38154993ea27d597e6cbb8fda0cd7b71cc2eb345b6c62140a6bf\"]}"; 36 | 37 | res_tips_t* res_tips = res_tips_new(); 38 | TEST_ASSERT_NOT_NULL(res_tips); 39 | 40 | TEST_ASSERT(get_tips_deserialize(json_tips, res_tips) == 0); 41 | TEST_ASSERT(res_tips->is_error == false); 42 | TEST_ASSERT_EQUAL_INT(4, get_tips_id_count(res_tips)); 43 | TEST_ASSERT_EQUAL_STRING("0a7c22aa43620d938146bcfc94a40804b26a5aaf3913bdc51b2836c47650de5c", 44 | get_tips_id(res_tips, 0)); 45 | TEST_ASSERT_EQUAL_STRING("3a3ca52a4c7d96fed4eef037db4421231f09e63a817bcf913f33c0806e565de9", 46 | get_tips_id(res_tips, 1)); 47 | TEST_ASSERT_EQUAL_STRING("a714ca72bb21d1e69b49a272713b9a1edc4d5679695680b5f36b907c0ed0d445", 48 | get_tips_id(res_tips, 2)); 49 | TEST_ASSERT_EQUAL_STRING("ea878b98a3eb38154993ea27d597e6cbb8fda0cd7b71cc2eb345b6c62140a6bf", 50 | get_tips_id(res_tips, 3)); 51 | 52 | res_tips_free(res_tips); 53 | } 54 | 55 | void test_deser_tips_err() { 56 | char const* const json_err = 57 | "{\"error\":{\"code\":\"service_unavailable\",\"message\":\"unable to handle the request\"}}"; 58 | 59 | res_tips_t* res_tips = res_tips_new(); 60 | TEST_ASSERT_NOT_NULL(res_tips); 61 | 62 | TEST_ASSERT(get_tips_deserialize(json_err, res_tips) == 0); 63 | TEST_ASSERT(res_tips->is_error == true); 64 | TEST_ASSERT_EQUAL_STRING(res_tips->u.error->code, "service_unavailable"); 65 | TEST_ASSERT_EQUAL_STRING(res_tips->u.error->msg, "unable to handle the request"); 66 | 67 | res_tips_free(res_tips); 68 | } 69 | 70 | int main() { 71 | UNITY_BEGIN(); 72 | 73 | #if TEST_TANGLE_ENABLE 74 | RUN_TEST(test_get_tips); 75 | #endif 76 | RUN_TEST(test_deser_get_tips); 77 | RUN_TEST(test_deser_tips_err); 78 | 79 | return UNITY_END(); 80 | } 81 | -------------------------------------------------------------------------------- /tests/client/api_restful/test_get_transaction_included_block.c: -------------------------------------------------------------------------------- 1 | // Copyright 2020 IOTA Stiftung 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | #include 5 | 6 | #include "client/api/restful/get_transaction_included_block.h" 7 | #include "core/models/payloads/transaction.h" 8 | #include "test_config.h" 9 | #include "unity/unity.h" 10 | 11 | /** 12 | * @brief This API has no deserialization tests because the response object is a block object which is tested in 13 | * test_get_block.c 14 | * 15 | */ 16 | 17 | void setUp(void) {} 18 | 19 | void tearDown(void) {} 20 | 21 | void test_get_transaction_included_block() { 22 | char const* const tx_id = "5e753f69b44870aa6a90adf2c366dccac00097c41d5c884dd81ef7cf29eefdd7"; 23 | iota_client_conf_t ctx = {.host = TEST_NODE_HOST, .port = TEST_NODE_PORT, .use_tls = TEST_IS_HTTPS}; 24 | 25 | res_block_t* msg = res_block_new(); 26 | TEST_ASSERT_NOT_NULL(msg); 27 | TEST_ASSERT(get_transaction_included_block_by_id(&ctx, tx_id, msg) == 0); 28 | if (msg->is_error) { 29 | printf("API response: %s\n", msg->u.error->msg); 30 | } else { 31 | // It must be a transaction block 32 | TEST_ASSERT(core_block_get_payload_type(msg->u.blk) == CORE_BLOCK_PAYLOAD_TRANSACTION); 33 | // Print transaction block 34 | core_block_print((msg->u.blk), 0); 35 | } 36 | res_block_free(msg); 37 | } 38 | 39 | int main() { 40 | UNITY_BEGIN(); 41 | #if TEST_TANGLE_ENABLE 42 | RUN_TEST(test_get_transaction_included_block); 43 | #endif 44 | return UNITY_END(); 45 | } 46 | -------------------------------------------------------------------------------- /tests/client/api_restful/test_response_error.c: -------------------------------------------------------------------------------- 1 | // Copyright 2020 IOTA Stiftung 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | #include 5 | #include 6 | 7 | #include "client/api/restful/response_error.h" 8 | 9 | void setUp(void) {} 10 | 11 | void tearDown(void) {} 12 | 13 | void test_deser_res_err() { 14 | char const* const json_err = 15 | "{\"error\":{\"code\":\"service_unavailable\",\"message\":\"unable to handle the request\"}}"; 16 | 17 | cJSON* json_obj = cJSON_Parse(json_err); 18 | TEST_ASSERT_NOT_NULL(json_obj); 19 | res_err_t* r = deser_error(json_obj); 20 | TEST_ASSERT_NOT_NULL(r); 21 | 22 | TEST_ASSERT_EQUAL_STRING("service_unavailable", r->code); 23 | TEST_ASSERT_EQUAL_STRING("unable to handle the request", r->msg); 24 | 25 | res_err_free(r); 26 | cJSON_Delete(json_obj); 27 | } 28 | 29 | void test_deser_err_msg_not_str() { 30 | char const* const json_err = "{ \"error\": { \"code\": 400, \"message\": 1234 } }"; 31 | 32 | cJSON* json_obj = cJSON_Parse(json_err); 33 | TEST_ASSERT_NOT_NULL(json_obj); 34 | res_err_t* r = deser_error(json_obj); 35 | TEST_ASSERT_NULL(r); 36 | 37 | cJSON_Delete(json_obj); 38 | } 39 | 40 | void test_deser_err_not_obj() { 41 | char const* const json_err = "{ \"error\": \"invalid data provided\" }"; 42 | 43 | cJSON* json_obj = cJSON_Parse(json_err); 44 | TEST_ASSERT_NOT_NULL(json_obj); 45 | res_err_t* r = deser_error(json_obj); 46 | TEST_ASSERT_NULL(r); 47 | 48 | cJSON_Delete(json_obj); 49 | } 50 | 51 | int main() { 52 | UNITY_BEGIN(); 53 | 54 | // correct json format 55 | RUN_TEST(test_deser_res_err); 56 | // error message is not a string 57 | RUN_TEST(test_deser_err_msg_not_str); 58 | // error element not a json object 59 | RUN_TEST(test_deser_err_not_obj); 60 | 61 | return UNITY_END(); 62 | } 63 | -------------------------------------------------------------------------------- /tests/core/test_allocator.c: -------------------------------------------------------------------------------- 1 | // Copyright 2021 IOTA Stiftung 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #include "core/utils/allocator.h" 9 | 10 | void setUp(void) {} 11 | 12 | void tearDown(void) {} 13 | 14 | void test_allocator() { 15 | char *str = "Hello"; 16 | char *m = malloc(strlen(str) + 1); 17 | strcpy(m, str); 18 | printf("%s: %s\n", JEMALLOC_VERSION, m); 19 | free(m); 20 | } 21 | 22 | int main() { 23 | UNITY_BEGIN(); 24 | 25 | RUN_TEST(test_allocator); 26 | 27 | return UNITY_END(); 28 | } -------------------------------------------------------------------------------- /tests/core/test_byte_buffer.c: -------------------------------------------------------------------------------- 1 | // Copyright 2021 IOTA Stiftung 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | #include 5 | #include 6 | 7 | #include "core/utils/byte_buffer.h" 8 | #include "unity/unity.h" 9 | 10 | void setUp(void) {} 11 | 12 | void tearDown(void) {} 13 | 14 | void test_byte_buf() { 15 | // create a byte buffer 16 | byte_buf_t *buf = byte_buf_new(); 17 | TEST_ASSERT_NOT_NULL(buf); 18 | TEST_ASSERT_NULL(buf->data); 19 | TEST_ASSERT(buf->cap == 0); 20 | TEST_ASSERT(buf->len == 0); 21 | 22 | // append two data sets to the buffer 23 | TEST_ASSERT_TRUE(byte_buf_append(buf, (byte_t *)"ABCDE", 5)); 24 | TEST_ASSERT(buf->cap == 5); 25 | TEST_ASSERT(buf->len == 5); 26 | TEST_ASSERT_TRUE(byte_buf_append(buf, (byte_t *)"FGHIJ", 5)); 27 | TEST_ASSERT(buf->cap == 10); 28 | TEST_ASSERT(buf->len == 10); 29 | // set data to the buffer 30 | TEST_ASSERT_TRUE(byte_buf_set(buf, (byte_t *)"VWXZY", 5)); 31 | TEST_ASSERT(buf->cap == 10); 32 | TEST_ASSERT(buf->len == 5); 33 | // byte_buf_print(buf); 34 | 35 | // append an null terminator to buffer data 36 | byte_buf2str(buf); 37 | TEST_ASSERT(buf->cap == 10); 38 | TEST_ASSERT(buf->len == 6); 39 | // should not append the null terminator again 40 | byte_buf2str(buf); 41 | TEST_ASSERT(buf->cap == 10); 42 | TEST_ASSERT(buf->len == 6); 43 | // printf("%s\n", buf->data); 44 | 45 | // reserve size smaller than capacity 46 | TEST_ASSERT_TRUE(byte_buf_reserve(buf, 5)); 47 | TEST_ASSERT(buf->cap == 10); 48 | TEST_ASSERT(buf->len == 6); 49 | 50 | // reserve size bigger than capacity 51 | TEST_ASSERT_TRUE(byte_buf_reserve(buf, 100)); 52 | TEST_ASSERT(buf->cap == 100); 53 | TEST_ASSERT(buf->len == 6); 54 | 55 | // byte_buf_print(buf); 56 | 57 | // duplicates a byte buffer 58 | byte_buf_t *c = byte_buf_clone(buf); 59 | TEST_ASSERT(c->cap == 6); 60 | TEST_ASSERT(c->len == 6); 61 | TEST_ASSERT(c != buf); 62 | TEST_ASSERT(c->data != buf->data); 63 | TEST_ASSERT_EQUAL_MEMORY(c->data, buf->data, buf->len); 64 | 65 | byte_buf_free(buf); 66 | byte_buf_free(c); 67 | } 68 | 69 | void test_hex_convertor() { 70 | char const *exp_str = "Hello world!"; 71 | char const *exp_hex = "48656c6c6f20776f726c6421"; 72 | 73 | byte_buf_t *buf = byte_buf_new_with_data((byte_t *)exp_str, strlen(exp_str)); 74 | byte_buf_t *hex = byte_buf_str2hex(buf); 75 | TEST_ASSERT_EQUAL_STRING(exp_hex, hex->data); 76 | byte_buf_free(buf); 77 | buf = NULL; 78 | byte_buf_free(hex); 79 | 80 | buf = byte_buf_new_with_data((byte_t *)exp_hex, strlen(exp_hex)); 81 | byte_buf_t *str = byte_buf_hex2str(buf); 82 | TEST_ASSERT_EQUAL_STRING(exp_str, str->data); 83 | byte_buf_free(buf); 84 | byte_buf_free(str); 85 | } 86 | 87 | void test_hex_bin() { 88 | char const *exp_hex = "48656c6c6f20776f726c6421"; 89 | byte_t exp_bin[12] = {0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x20, 0x77, 0x6F, 0x72, 0x6C, 0x64, 0x21}; 90 | byte_t bin[12] = {}; 91 | 92 | // hex2bin 93 | TEST_ASSERT(hex_2_bin(exp_hex, strlen(exp_hex), NULL, bin, 12) == 0); 94 | TEST_ASSERT_EQUAL_MEMORY(exp_bin, bin, 12); 95 | 96 | // bin2hex 97 | char hex_str[(12 * 2) + 1] = {}; 98 | TEST_ASSERT(bin_2_hex(bin, 12, NULL, hex_str, sizeof(hex_str)) == 0); 99 | TEST_ASSERT_EQUAL_STRING(exp_hex, hex_str); 100 | } 101 | 102 | int main() { 103 | UNITY_BEGIN(); 104 | 105 | RUN_TEST(test_byte_buf); 106 | RUN_TEST(test_hex_convertor); 107 | RUN_TEST(test_hex_bin); 108 | 109 | return UNITY_END(); 110 | } 111 | -------------------------------------------------------------------------------- /tests/core/test_byte_cost_config.c: -------------------------------------------------------------------------------- 1 | // Copyright 2022 IOTA Stiftung 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | #include "core/models/inputs/utxo_input.h" 5 | #include "core/models/outputs/byte_cost_config.h" 6 | #include "unity/unity.h" 7 | 8 | void setUp(void) {} 9 | 10 | void tearDown(void) {} 11 | 12 | void test_byte_cost_config_create_new_config() { 13 | uint16_t byte_cost = (uint16_t)123456; 14 | uint8_t byte_factor_data = 111; 15 | uint8_t byte_factor_key = 222; 16 | uint16_t byte_offset = (IOTA_OUTPUT_ID_BYTES * byte_factor_key) + (IOTA_BLOCK_ID_BYTES * byte_factor_data) + 17 | (sizeof(uint32_t) * byte_factor_data) + (sizeof(uint32_t) * byte_factor_data); 18 | 19 | byte_cost_config_t* config = byte_cost_config_new(byte_cost, byte_factor_data, byte_factor_key); 20 | 21 | TEST_ASSERT_EQUAL_UINT16(byte_cost, config->v_byte_cost); 22 | TEST_ASSERT_EQUAL_UINT8(byte_factor_data, config->v_byte_factor_data); 23 | TEST_ASSERT_EQUAL_UINT8(byte_factor_key, config->v_byte_factor_key); 24 | TEST_ASSERT_EQUAL_UINT16(byte_offset, config->v_byte_offset); 25 | 26 | byte_cost_config_free(config); 27 | } 28 | 29 | void test_byte_cost_config_create_new_default_config() { 30 | byte_cost_config_t* config = byte_cost_config_default_new(); 31 | 32 | TEST_ASSERT_EQUAL_UINT16(500, config->v_byte_cost); 33 | TEST_ASSERT_EQUAL_UINT8(1, config->v_byte_factor_data); 34 | TEST_ASSERT_EQUAL_UINT8(10, config->v_byte_factor_key); 35 | TEST_ASSERT_EQUAL_UINT16(380, config->v_byte_offset); 36 | 37 | byte_cost_config_free(config); 38 | } 39 | 40 | int main() { 41 | UNITY_BEGIN(); 42 | 43 | RUN_TEST(test_byte_cost_config_create_new_config); 44 | RUN_TEST(test_byte_cost_config_create_new_default_config); 45 | 46 | return UNITY_END(); 47 | } 48 | -------------------------------------------------------------------------------- /tests/core/test_iota_str.c: -------------------------------------------------------------------------------- 1 | // Copyright 2021 IOTA Stiftung 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | #include 5 | 6 | #include "core/utils/iota_str.h" 7 | #include "unity/unity.h" 8 | 9 | void setUp(void) {} 10 | 11 | void tearDown(void) {} 12 | 13 | void test_iota_str() { 14 | char* c_str1 = "hello"; 15 | // test new 16 | iota_str_t* str1 = iota_str_new(c_str1); 17 | TEST_ASSERT_NOT_NULL(str1); 18 | TEST_ASSERT_NOT_NULL(str1->buf); 19 | TEST_ASSERT_EQUAL_INT(strlen(c_str1), str1->len); 20 | TEST_ASSERT_EQUAL_INT(strlen(c_str1) + 1, str1->cap); 21 | TEST_ASSERT(strcmp(str1->buf, c_str1) == 0); 22 | 23 | // test append 24 | int ret = iota_str_append(str1, " world!"); 25 | TEST_ASSERT(ret == 0); 26 | TEST_ASSERT(strcmp(str1->buf, "hello world!") == 0); 27 | 28 | ret = iota_str_appendn(str1, " world!", 3); 29 | TEST_ASSERT(ret == 0); 30 | TEST_ASSERT(strcmp(str1->buf, "hello world! wo") == 0); 31 | 32 | ret = iota_str_append_char(str1, 'W'); 33 | TEST_ASSERT(ret == 0); 34 | TEST_ASSERT(strcmp(str1->buf, "hello world! woW") == 0); 35 | 36 | // test clone 37 | iota_str_t* str2 = iota_str_clone(str1); 38 | TEST_ASSERT_NOT_NULL(str2); 39 | TEST_ASSERT_NOT_NULL(str2->buf); 40 | TEST_ASSERT(strcmp(str1->buf, str2->buf) == 0); 41 | TEST_ASSERT_EQUAL_INT32(str1->len, str2->len); 42 | // test cmp 43 | TEST_ASSERT(iota_str_cmp(str1, str2) == 0); 44 | 45 | // test n clone 46 | iota_str_t* str3 = iota_str_clonen(str1, strlen(c_str1)); 47 | TEST_ASSERT_NOT_NULL(str3); 48 | TEST_ASSERT_NOT_NULL(str3->buf); 49 | TEST_ASSERT_EQUAL_INT(strlen(c_str1), str3->len); 50 | TEST_ASSERT_EQUAL_INT(strlen(c_str1) + 1, str3->cap); 51 | TEST_ASSERT(strcmp(str3->buf, c_str1) == 0); 52 | 53 | iota_str_destroy(str1); 54 | iota_str_destroy(str2); 55 | iota_str_destroy(str3); 56 | } 57 | 58 | int main() { 59 | UNITY_BEGIN(); 60 | 61 | RUN_TEST(test_iota_str); 62 | 63 | return UNITY_END(); 64 | } -------------------------------------------------------------------------------- /tests/core/test_slip10.c: -------------------------------------------------------------------------------- 1 | // Copyright 2020 IOTA Stiftung 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #include "core/utils/byte_buffer.h" 9 | #include "core/utils/slip10.h" 10 | #include "crypto/iota_crypto.h" 11 | #include "slip10_vector.h" 12 | 13 | void setUp(void) {} 14 | 15 | void tearDown(void) {} 16 | 17 | void test_bip32path() { 18 | bip32_path_t path = {}; 19 | size_t test_cases = sizeof(bip32path_set) / sizeof(test_bip32path_t); 20 | for (size_t i = 0; i < test_cases; i++) { 21 | printf("bip32 path: %s\n", bip32path_set[i].str); 22 | int ret = slip10_parse_path(bip32path_set[i].str, &path); 23 | TEST_ASSERT(ret == bip32path_set[i].err); 24 | if (ret == 0) { 25 | TEST_ASSERT(bip32path_set[i].path_len == (size_t)path.len); 26 | TEST_ASSERT_EQUAL_MEMORY(bip32path_set[i].exp_path, path.path, path.len); 27 | } 28 | } 29 | } 30 | 31 | void test_derive_key_from_path() { 32 | byte_t tmp_seed[64] = {}; 33 | slip10_key_t key = {}; 34 | byte_t tmp_pub[SLIP10_PUBLIC_KEY_BYTES] = {}; 35 | 36 | for (size_t i = 0; i < sizeof(slip10_set) / sizeof(test_slip10_t); i++) { 37 | printf("slip10: %s, %s\n", slip10_set[i].seed, slip10_set[i].path); 38 | size_t seed_len = strlen(slip10_set[i].seed) / 2; 39 | // hex seed to bin seed 40 | TEST_ASSERT(hex_2_bin(slip10_set[i].seed, strlen(slip10_set[i].seed), NULL, tmp_seed, seed_len) == 0); 41 | 42 | // key derivation 43 | int ret = slip10_key_from_path(tmp_seed, seed_len, slip10_set[i].path, ED25519_CURVE, &key); 44 | TEST_ASSERT(ret == slip10_set[i].err); 45 | 46 | if (ret == 0) { 47 | // validating chain code 48 | TEST_ASSERT_EQUAL_MEMORY(slip10_set[i].chain_code, key.chain_code, SLIP10_CHAIN_CODE_BYTES); 49 | // validating private key 50 | TEST_ASSERT_EQUAL_MEMORY(slip10_set[i].private, key.key, SLIP10_PRIVATE_KEY_BYTES); 51 | // validating public key 52 | TEST_ASSERT(slip10_public_key(ED25519_CURVE, &key, tmp_pub) == 0); 53 | TEST_ASSERT_EQUAL_MEMORY(slip10_set[i].public, tmp_pub, SLIP10_PUBLIC_KEY_BYTES); 54 | } 55 | } 56 | } 57 | 58 | int main() { 59 | UNITY_BEGIN(); 60 | 61 | RUN_TEST(test_bip32path); 62 | RUN_TEST(test_derive_key_from_path); 63 | 64 | return UNITY_END(); 65 | } 66 | -------------------------------------------------------------------------------- /tests/core/test_utils_bech32.c: -------------------------------------------------------------------------------- 1 | // Copyright 2020 IOTA Stiftung 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | #include 5 | 6 | #include "core/utils/bech32.h" 7 | #include "unity/unity.h" 8 | 9 | static const char *valid_checksum[] = { 10 | "A12UEL5L", 11 | "an83characterlonghumanreadablepartthatcontainsthenumber1andtheexcludedcharactersbio1tt5tgs", 12 | "abcdef1qpzry9x8gf2tvdw0s3jn54khce6mua7lmqqqxw", 13 | "11qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqc8247j", 14 | "split1checkupstagehandshakeupstreamerranterredcaperred2y9e3w", 15 | }; 16 | 17 | static const char *invalid_checksum[] = { 18 | " 1nwldj5", ("\x7f"), 19 | "1axkwrx", "an84characterslonghumanreadablepartthatcontainsthenumber1andtheexcludedcharactersbio1569pvx", 20 | "pzry9x0s0muk", "1pzry9x0s0muk", 21 | "x1b4n0q5v", "li1dgmt3", 22 | "de1lg7wt\xff", 23 | }; 24 | 25 | static int my_strncasecmp(const char *s1, const char *s2, size_t n) { 26 | size_t i = 0; 27 | while (i < n) { 28 | char c1 = s1[i]; 29 | char c2 = s2[i]; 30 | if (c1 >= 'A' && c1 <= 'Z') c1 = (c1 - 'A') + 'a'; 31 | if (c2 >= 'A' && c2 <= 'Z') c2 = (c2 - 'A') + 'a'; 32 | if (c1 < c2) return -1; 33 | if (c1 > c2) return 1; 34 | if (c1 == 0) return 0; 35 | ++i; 36 | } 37 | return 0; 38 | } 39 | 40 | void setUp(void) {} 41 | 42 | void tearDown(void) {} 43 | 44 | void test_bech32_decode_encode() { 45 | for (size_t i = 0; i < sizeof(valid_checksum) / sizeof(valid_checksum[0]); ++i) { 46 | uint8_t data[82] = {}; 47 | char rebuild[92] = {}; 48 | char hrp[84] = {}; 49 | size_t data_len = 0; 50 | TEST_ASSERT(bech32_decode(hrp, data, &data_len, valid_checksum[i]) == 1); 51 | TEST_ASSERT(bech32_encode(rebuild, hrp, data, data_len) == 1); 52 | TEST_ASSERT(my_strncasecmp(rebuild, valid_checksum[i], 92) == 0); 53 | } 54 | 55 | for (size_t i = 0; i < sizeof(invalid_checksum) / sizeof(invalid_checksum[0]); ++i) { 56 | uint8_t data[82] = {}; 57 | char hrp[84] = {}; 58 | size_t data_len = 0; 59 | TEST_ASSERT(bech32_decode(hrp, data, &data_len, invalid_checksum[i]) == 0); 60 | } 61 | } 62 | 63 | int main() { 64 | UNITY_BEGIN(); 65 | 66 | RUN_TEST(test_bech32_decode_encode); 67 | 68 | return UNITY_END(); 69 | } 70 | -------------------------------------------------------------------------------- /tests/crypto/pbkdf2_vectors.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env python3 2 | 3 | """ 4 | Script to auto-generate PBKDF2 test vectors 5 | Usage: ./pbkdf2_vectors.py > pbkdf2_vectors.h 6 | 7 | Vectors from https://datatracker.ietf.org/doc/html/rfc6070 8 | """ 9 | 10 | import sys 11 | import os.path 12 | import datetime 13 | import hashlib 14 | 15 | 16 | def print_vector(pwd, salt, iteration, dkLen): 17 | # key calculation 18 | vecSHA1 = hashlib.pbkdf2_hmac("sha1", pwd, salt, iteration, dkLen) 19 | vecSHA256 = hashlib.pbkdf2_hmac("sha256", pwd, salt, iteration, dkLen) 20 | vecSHA512 = hashlib.pbkdf2_hmac("sha512", pwd, salt, iteration, dkLen) 21 | 22 | # add as a struct element 23 | elm = ' {' + str(iteration) + ', ' + str(dkLen) + ',\n' 24 | elm = elm + ' "' + pwd.hex() + '",\n' 25 | elm = elm + ' "' + salt.hex() + '",\n' 26 | elm = elm + ' "' + vecSHA1.hex() + '",\n' 27 | elm = elm + ' "' + vecSHA256.hex() + '",\n' 28 | elm = elm + ' "' + vecSHA512.hex() + '"},' 29 | print(elm) 30 | 31 | 32 | def pbkdf2_vectors(): 33 | print("/* ===auto-generated by " + 34 | os.path.basename(sys.argv[0]) + " DO NOT EDIT!!=== */\n") 35 | print("// Copyright " + str(datetime.datetime.now().year) + " IOTA Stiftung") 36 | print("// SPDX-License-Identifier: Apache-2.0\n") 37 | print("#ifndef __TEST_CRYPTO_PBKDF2_H__") 38 | print("#define __TEST_CRYPTO_PBKDF2_H__\n") 39 | print("#include \n") 40 | print("// PBKDF2 test vectors from https://datatracker.ietf.org/doc/html/rfc6070") 41 | 42 | vector_struct = """typedef struct { 43 | size_t iter; ///< iteration 44 | size_t dk_len; ///< length of derived key 45 | char *pwd; ///< point to the password 46 | char *salt; ///< point to the salt 47 | char *sha1; ///< derived key from sha1 48 | char *sha256; ///< derived key from sha256 49 | char *sha512; ///< derived key from sha512 50 | } pbkdf2_vector_t; 51 | """ 52 | print(vector_struct) 53 | 54 | print('// clang-format off') 55 | print('static pbkdf2_vector_t pbkdf2[] = {') 56 | # test vectors 57 | print_vector(b"password", b"salt", 1, 20) 58 | print_vector(b"password", b"salt", 2, 20) 59 | print_vector(b"password", b"salt", 2, 16) 60 | print_vector(b"password", b"salt", 2, 32) 61 | print_vector(b"password", b"salt", 2, 64) 62 | print_vector(b"password", b"salt", 2, 127) 63 | print_vector(b"password", b"salt", 2, 128) 64 | print_vector(b"password", b"salt", 2, 129) 65 | print_vector(b"password", b"salt", 2, 256) 66 | print_vector(b"password", b"salt", 4096, 20) 67 | print_vector(b"passwordPASSWORDpassword", 68 | b"saltSALTsaltSALTsaltSALTsaltSALTsalt", 4096, 25) 69 | print_vector(b"pass\0word", b"sa\0lt", 4096, 16) 70 | print('};') 71 | print('// clang-format on\n') 72 | print("#endif\n") 73 | 74 | 75 | if __name__ == "__main__": 76 | pbkdf2_vectors() 77 | -------------------------------------------------------------------------------- /tests/test_config.h: -------------------------------------------------------------------------------- 1 | // Copyright 2021 IOTA Stiftung 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | #ifndef __TEST_CLIENT_API_CONFIG_H__ 5 | #define __TEST_CLIENT_API_CONFIG_H__ 6 | 7 | // Test with private tangle or not 8 | // Set to 1 for debugging individual test cases only 9 | #define TEST_TANGLE_ENABLE 0 10 | 11 | #define TEST_IS_HTTPS 0 12 | // Node 13 | #define TEST_NODE_HOST "localhost" 14 | #define TEST_NODE_PORT 14265 15 | 16 | // Faucet 17 | #define TEST_FAUCET_HOST "localhost" 18 | #define TEST_FAUCET_PORT 14265 19 | 20 | // MQTT 21 | #define TEST_EVENTS_HOST "localhost" 22 | #define TEST_EVENTS_PORT 1883 23 | #define TEST_EVENTS_CLIENT_ID "iota_test_2" 24 | #define TEST_EVENTS_KEEP_ALIVE 60 25 | 26 | #define TEST_TIMEOUT_SECONDS 30 27 | 28 | // Wallet 29 | 30 | // using SLIP44_COIN_TYPE_TEST as default coin type 31 | // uncomment one to choose another coin type 32 | // #define NETWORK_TYPE_SHIMMER 33 | // #define NETWORK_TYPE_MAINNET 34 | 35 | // predefined coin types 36 | #if defined(NETWORK_TYPE_SHIMMER) 37 | #define SLIP44_COIN_TYPE SLIP44_COIN_TYPE_SHIMMER 38 | #elif defined(NETWORK_TYPE_MAINNET) 39 | #define SLIP44_COIN_TYPE SLIP44_COIN_TYPE_IOTA 40 | #else 41 | #define SLIP44_COIN_TYPE SLIP44_COIN_TYPE_TEST 42 | #endif 43 | 44 | #endif 45 | -------------------------------------------------------------------------------- /tests/wallet/test_bip39.c: -------------------------------------------------------------------------------- 1 | // Copyright 2022 IOTA Stiftung 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #include "core/utils/byte_buffer.h" 9 | #include "unity/unity.h" 10 | #include "wallet/bip39.h" 11 | 12 | #include "mnemonic_vectors.h" 13 | 14 | // max entropy input size is 32 15 | #define ENT_BUF_LEN 32 16 | // depends on the chosen language 17 | #define MS_BUF_SIZE 1024 18 | // wrt bip39 spec, should be bigger than 33 bytes 19 | #define ENT_OUT_BUF_LEN 64 20 | 21 | // buffers used by test_bip39_en and test_bip39_languages 22 | byte_t entropy[ENT_BUF_LEN] = {}; 23 | char ms_out[MS_BUF_SIZE] = {}; 24 | char ms_zh_out[MS_BUF_SIZE] = {}; 25 | byte_t out_ent[ENT_OUT_BUF_LEN] = {}; 26 | 27 | void setUp(void) {} 28 | 29 | void tearDown(void) {} 30 | 31 | // validate encode/decode/ms with English 32 | void test_bip39_vectors() { 33 | for (size_t i = 0; i < sizeof(vectors) / sizeof(ms_vectors_t); i++) { 34 | printf("validating BIP39 vector[%zu]: %s\n", i, vectors[i].ent); 35 | // encode 36 | size_t entropy_str_len = strlen(vectors[i].ent); 37 | size_t entropy_bin_len = entropy_str_len / 2; 38 | hex_2_bin(vectors[i].ent, entropy_str_len, NULL, entropy, sizeof(entropy)); 39 | mnemonic_encode(entropy, entropy_bin_len, MS_LAN_EN, ms_out, MS_BUF_SIZE); 40 | TEST_ASSERT_EQUAL_MEMORY(vectors[i].ms, ms_out, strlen(vectors[i].ms)); 41 | printf("%s\n", ms_out); 42 | 43 | // decode 44 | size_t len = mnemonic_decode(ms_out, MS_LAN_EN, out_ent, sizeof(out_ent)); 45 | TEST_ASSERT(len != 0); 46 | TEST_ASSERT_EQUAL_MEMORY(entropy, out_ent, entropy_bin_len); 47 | // dump_hex_str(out_ent, len); 48 | } 49 | } 50 | 51 | // validate encode/decode with other languages 52 | void test_bip39_languages() { 53 | #ifndef BIP39_ENGLISH_ONLY 54 | for (ms_lan_t lan = MS_LAN_KO; lan <= MS_LAN_PT; lan++) { 55 | printf("validating BIP39 language ID %d...\n", lan); 56 | for (size_t i = 0; i < sizeof(vectors) / sizeof(ms_vectors_t); i++) { 57 | printf("\tBIP39 vector[%zu]: %s\n", i, vectors[i].ent); 58 | // encode 59 | size_t entropy_str_len = strlen(vectors[i].ent); 60 | size_t entropy_bin_len = entropy_str_len / 2; 61 | TEST_ASSERT(hex_2_bin(vectors[i].ent, entropy_str_len, NULL, entropy, sizeof(entropy)) == 0); 62 | TEST_ASSERT(mnemonic_encode(entropy, entropy_bin_len, lan, ms_out, MS_BUF_SIZE) == 0); 63 | printf("\t%s\n", ms_out); 64 | // decode 65 | size_t len = mnemonic_decode(ms_out, lan, out_ent, sizeof(out_ent)); 66 | TEST_ASSERT(len != 0); 67 | // we don't check the ms but validate encode/decode entropy 68 | TEST_ASSERT_EQUAL_MEMORY(entropy, out_ent, entropy_bin_len); 69 | } 70 | } 71 | #endif 72 | } 73 | 74 | void test_bip39_seed() { 75 | byte_t seed[64] = {}; 76 | byte_t exp_seed[64] = {}; 77 | for (size_t i = 0; i < sizeof(vectors) / sizeof(ms_vectors_t); i++) { 78 | TEST_ASSERT(mnemonic_to_seed(vectors[i].ms, "TREZOR", seed, sizeof(seed)) == 0); 79 | hex_2_bin(vectors[i].seed, strlen(vectors[i].seed), NULL, exp_seed, sizeof(exp_seed)); 80 | TEST_ASSERT_EQUAL_MEMORY(exp_seed, seed, sizeof(exp_seed)); 81 | } 82 | } 83 | 84 | int main() { 85 | UNITY_BEGIN(); 86 | 87 | RUN_TEST(test_bip39_vectors); 88 | RUN_TEST(test_bip39_languages); 89 | RUN_TEST(test_bip39_seed); 90 | 91 | return UNITY_END(); 92 | } 93 | -------------------------------------------------------------------------------- /tools/ci_format_check: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | root=$(git rev-parse --show-toplevel) 4 | status=0 5 | 6 | # dump tool versions 7 | clang_fmt_version=$(clang-format-12 --version) 8 | echo -e "\e[32m${clang_fmt_version} \e[39m" 9 | cmake_fmt_version=$(cmake-format --version) 10 | echo -e "\e[32mcmake-format version ${cmake_fmt_version} \e[39m" 11 | 12 | # check source files 13 | for file in $(find "${@}" -type f | grep -E "\.(c|cc|cpp|h|hh|hpp)\$") 14 | do 15 | filepath="$root/$file" 16 | output=$(diff <(cat $filepath) <(clang-format-12 -style=file -fallback-style=none $filepath)) 17 | if [ $? -ne 0 ] 18 | then 19 | echo -e "\nFile \e[31m\""$file"\"\e[39m is not compliant with the coding style" 20 | echo "$output" 21 | status=1 22 | fi 23 | done 24 | 25 | # checking CMake scripts 26 | for file in $(find ${root} ! -path "*/build/*"| grep -E "CMakeLists.txt") 27 | do 28 | cmake-format -c ${root}/.cmake_format.yaml --check ${file} 2> /dev/null 29 | if [ $? -ne 0 ] 30 | then 31 | echo -e "\nFile \e[31m\""$file"\"\e[39m is not compliant with cmake-format" 32 | echo "$output" 33 | status=2 34 | fi 35 | done 36 | 37 | exit $status 38 | -------------------------------------------------------------------------------- /tools/formatter: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | project_root=$(git rev-parse --show-toplevel) 3 | for file in $(find ${project_root} ! -path "*/build/*" | grep -E "\.(c|cc|cpp|h|hh|hpp|m|mm)\$") 4 | do 5 | clang-format -style=file -fallback-style=none -i ${file} 6 | done 7 | 8 | for file in $(find ${project_root} ! -path "*/build/*"| grep -E "CMakeLists.txt") 9 | do 10 | cmake-format -c ${project_root}/.cmake_format.yaml -i ${file} 11 | done 12 | -------------------------------------------------------------------------------- /tools/hooks/pre-commit/01-format-check: -------------------------------------------------------------------------------- 1 | ../scripts/format_check -------------------------------------------------------------------------------- /tools/hooks/scripts/format_check: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | root=$(git rev-parse --show-toplevel) 4 | status=0 5 | for file in $(git diff --staged --name-only | grep -E "^(src|tests|examples)" | grep -E "\.(c|cc|cpp|h|hh|hpp)\$") 6 | do 7 | filepath="$root/$file" 8 | output=$(diff <(cat $filepath) <(clang-format -style=file -fallback-style=none $filepath)) 9 | if [ $? -ne 0 ] 10 | then 11 | echo -e "\nFile \""$file"\" is not compliant with the coding style" 12 | echo "$output" 13 | status=1 14 | fi 15 | done 16 | exit $status 17 | --------------------------------------------------------------------------------