diff --git a/.github/workflows/ci-workflow.yml b/.github/workflows/ci-workflow.yml index 4893ad2e..686ee4bb 100644 --- a/.github/workflows/ci-workflow.yml +++ b/.github/workflows/ci-workflow.yml @@ -7,69 +7,86 @@ on: - master - develop pull_request: - branches: - - master - - develop jobs: - job_nanoS_build_debug: - name: Build debug app for NanoS - runs-on: ubuntu-latest - container: - image: ghcr.io/ledgerhq/ledger-app-builder/ledger-app-builder:latest - steps: - - name: Clone - uses: actions/checkout@v2 - - name: Build - run: | - make DEBUG=1 - - name: Upload app binary - uses: actions/upload-artifact@v2 - with: - name: app-nanoS-debug - path: bin + build_application: + strategy: + matrix: + sdk: + - path: $NANOS_SDK + name: nanos + - path: $NANOX_SDK + name: nanox + - path: $NANOSP_SDK + name: nanosp - job_nanoX_build_debug: - name: Build debug app for NanoX runs-on: ubuntu-latest + container: image: ghcr.io/ledgerhq/ledger-app-builder/ledger-app-builder:latest + steps: - name: Clone - uses: actions/checkout@v2 - - name: Build + uses: actions/checkout@v3 + + - name: Build application run: | - make DEBUG=1 BOLOS_SDK=$NANOX_SDK - - name: Upload app binary - uses: actions/upload-artifact@v2 + make BOLOS_SDK=${{ matrix.sdk.path }} DEBUG=1 + cp bin/app.elf bin/solana_${{ matrix.sdk.name }}.elf + + - name: Upload application binaries + uses: actions/upload-artifact@v3 with: - name: app-nanoX-debug - path: bin + name: solana_binaries + path: ./bin/solana_${{ matrix.sdk.name }}.elf + if-no-files-found: error job_scan_build: name: Clang Static Analyzer + needs: build_application runs-on: ubuntu-latest container: image: ghcr.io/ledgerhq/ledger-app-builder/ledger-app-builder:latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Build with Clang Static Analyzer run: | make clean scan-build --use-cc=clang -analyze-headers -enable-checker security -enable-checker unix -enable-checker valist -o scan-build --status-bugs make default - - uses: actions/upload-artifact@v2 + - uses: actions/upload-artifact@v3 if: failure() with: name: scan-build path: scan-build + python_tests_nano: + name: NanoS Ragger tests + needs: build_application + runs-on: ubuntu-latest + steps: + - name: Clone + uses: actions/checkout@v3 + - name: Download all binaries + uses: actions/download-artifact@v3 + - name: Gather artifacts + run: | + mkdir tests/elfs + mv *_binaries/*.elf tests/elfs + - name: Install APT dependencies + run: sudo apt-get update && sudo apt-get install -y qemu-user-static + - name: Install Ragger + run: | + pip install --extra-index-url https://test.pypi.org/simple/ -r tests/python/requirements.txt + - name: Run tests + run: pytest tests/python/ -v --tb=short --device all + job_C_test: name: C tests runs-on: ubuntu-latest container: - image: ghcr.io/ledgerhq/ledger-app-builder/ledger-app-builder:latest + image: ghcr.io/ledgerhq/ledger-app-builder/ledger-app-builder-legacy:latest steps: - name: Clone - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Build unit tests run: make -C libsol diff --git a/.github/workflows/lint-workflow.yml b/.github/workflows/lint-workflow.yml new file mode 100644 index 00000000..6c1efb98 --- /dev/null +++ b/.github/workflows/lint-workflow.yml @@ -0,0 +1,48 @@ +name: Code style check + +on: + workflow_dispatch: + push: + branches: + - master + - develop + pull_request: + +jobs: + job_lint: + name: Lint + runs-on: ubuntu-latest + + steps: + - name: Clone + uses: actions/checkout@v3 + + - name: Lint src + uses: DoozyX/clang-format-lint-action@v0.13 + with: + source: './src' + extensions: 'h,c' + clangFormatVersion: 12.0.0 + + - name: Lint libsol + uses: DoozyX/clang-format-lint-action@v0.13 + with: + source: './libsol' + extensions: 'h,c' + clangFormatVersion: 12.0.0 + + misspell: + name: Check misspellings + runs-on: ubuntu-latest + steps: + - name: Clone + uses: actions/checkout@v3 + with: + fetch-depth: 0 + - name: Check misspellings + uses: codespell-project/actions-codespell@2391250ab05295bddd51e36a8c6295edb6343b0e + with: + # Use Config file when the github action supports it + builtin: clear,rare + check_filenames: true + skip: ./libsol,./tests diff --git a/.github/workflows/sonarcloud.yml b/.github/workflows/sonarcloud.yml index 8b8f887c..bc8fe835 100644 --- a/.github/workflows/sonarcloud.yml +++ b/.github/workflows/sonarcloud.yml @@ -6,23 +6,19 @@ on: - master - develop pull_request: - branches: - - master - - develop - types: [opened, synchronize, reopened] jobs: build: name: SonarQube analyze runs-on: ubuntu-latest container: - image: ghcr.io/ledgerhq/ledger-app-builder/ledger-app-builder:latest + image: ghcr.io/ledgerhq/ledger-app-builder/ledger-app-builder-legacy:latest env: SONAR_SCANNER_VERSION: 4.7.0.2747 SONAR_SERVER_URL: "https://sonarcloud.io" BUILD_WRAPPER_OUT_DIR: build_wrapper_output_directory # Directory where build-wrapper output will be placed steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 with: fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis - name: Set up JDK 11 @@ -35,8 +31,9 @@ jobs: run: | apt-get update -y apt-get upgrade -y + DEBIAN_FRONTEND=noninteractive apt-get install -y tzdata curl -sL https://deb.nodesource.com/setup_16.x | bash - - apt-get install -y gcovr nodejs unzip + apt-get install -y gcovr nodejs unzip lcov mkdir -p $HOME/.sonar curl -sSLo $HOME/.sonar/sonar-scanner.zip ${{ env.SONAR_SCANNER_DOWNLOAD_URL }} unzip -o $HOME/.sonar/sonar-scanner.zip -d $HOME/.sonar/ diff --git a/.gitignore b/.gitignore index 799d1efa..09fd410b 100644 --- a/.gitignore +++ b/.gitignore @@ -10,3 +10,12 @@ src/glyphs.h gitignore .vagrant libsol/target + +# Python +__pycache__ +.egg +.pyc +*~ + +tests/elfs/ +tests/python/snapshots-tmp/ diff --git a/Makefile b/Makefile index d4f6d843..5f443df2 100644 --- a/Makefile +++ b/Makefile @@ -1,39 +1,52 @@ -#******************************************************************************* -# Ledger App -# (c) 2017 Ledger +# **************************************************************************** +# Ledger App Solana +# (c) 2020 Ledger SAS. # -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# http://www.apache.org/licenses/LICENSE-2.0 # -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -#******************************************************************************* +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# **************************************************************************** + +ifeq ($(BOLOS_SDK),) + # `THIS_DIR` must be resolved BEFORE any `include` directives + THIS_DIR := $(abspath $(dir $(lastword $(MAKEFILE_LIST)))) + TARGET_SDK := $(shell ./util/read-last-sdk) + BOLOS_SDK := ${$(TARGET_SDK)} +endif ifeq ($(BOLOS_SDK),) $(error Environment variable BOLOS_SDK is not set) endif -include $(BOLOS_SDK)/Makefile.defines -APPVERSION_M=1 -APPVERSION_N=2 -APPVERSION_P=0 -APPVERSION=$(APPVERSION_M).$(APPVERSION_N).$(APPVERSION_P) -APPNAME = "Solana" +include $(BOLOS_SDK)/Makefile.defines -APP_LOAD_PARAMS = --curve ed25519 --path "44'/501'" --appFlags 0x240 $(COMMON_LOAD_PARAMS) +APP_LOAD_PARAMS = --curve ed25519 +ifeq ($(TARGET_NAME), TARGET_NANOX) + APP_LOAD_PARAMS += --appFlags 0x200 # APPLICATION_FLAG_BOLOS_SETTINGS +else + APP_LOAD_PARAMS += --appFlags 0x000 +endif +APP_LOAD_PARAMS += --path "44'/501'" +APP_LOAD_PARAMS += $(COMMON_LOAD_PARAMS) -DEFINES += $(DEFINES_LIB) +APPNAME = "Solana" +APPVERSION_M = 1 +APPVERSION_N = 3 +APPVERSION_P = 1 +APPVERSION = "$(APPVERSION_M).$(APPVERSION_N).$(APPVERSION_P)" ifeq ($(TARGET_NAME),TARGET_NANOS) - ICONNAME=icons/nanos_app_solana.gif + ICONNAME=icons/nanos_app_solana.gif else - ICONNAME=icons/nanox_app_solana.gif + ICONNAME=icons/nanox_app_solana.gif endif ################ @@ -41,117 +54,92 @@ endif ################ all: default -############ -# Platform # -############ - -DEFINES += OS_IO_SEPROXYHAL -DEFINES += HAVE_BAGL HAVE_SPRINTF -DEFINES += HAVE_SNPRINTF_FORMAT_U -DEFINES += HAVE_IO_USB HAVE_L4_USBLIB IO_USB_MAX_ENDPOINTS=6 IO_HID_EP_LENGTH=64 HAVE_USB_APDU -DEFINES += LEDGER_MAJOR_VERSION=$(APPVERSION_M) LEDGER_MINOR_VERSION=$(APPVERSION_N) LEDGER_PATCH_VERSION=$(APPVERSION_P) - -# no assert by default -DEFINES += NDEBUG - -# U2F -DEFINES += HAVE_U2F HAVE_IO_U2F -DEFINES += U2F_PROXY_MAGIC=\"~SOL\" -DEFINES += USB_SEGMENT_SIZE=64 -DEFINES += BLE_SEGMENT_SIZE=32 #max MTU, min 20 - -#WEBUSB_URL = www.ledgerwallet.com -#DEFINES += HAVE_WEBUSB WEBUSB_URL_SIZE_B=$(shell echo -n $(WEBUSB_URL) | wc -c) WEBUSB_URL=$(shell echo -n $(WEBUSB_URL) | sed -e "s/./\\\'\0\\\',/g") - -DEFINES += HAVE_WEBUSB WEBUSB_URL_SIZE_B=0 WEBUSB_URL="" - -DEFINES += UNUSED\(x\)=\(void\)x -DEFINES += APPVERSION=\"$(APPVERSION)\" - +DEFINES += $(DEFINES_LIB) +DEFINES += APPNAME=\"$(APPNAME)\" +DEFINES += APPVERSION=\"$(APPVERSION)\" +DEFINES += MAJOR_VERSION=$(APPVERSION_M) MINOR_VERSION=$(APPVERSION_N) PATCH_VERSION=$(APPVERSION_P) +DEFINES += OS_IO_SEPROXYHAL +DEFINES += HAVE_BAGL HAVE_UX_FLOW HAVE_SPRINTF +DEFINES += HAVE_IO_USB HAVE_L4_USBLIB IO_USB_MAX_ENDPOINTS=6 IO_HID_EP_LENGTH=64 HAVE_USB_APDU +DEFINES += USB_SEGMENT_SIZE=64 +DEFINES += BLE_SEGMENT_SIZE=32 +DEFINES += HAVE_WEBUSB WEBUSB_URL_SIZE_B=0 WEBUSB_URL="" +DEFINES += UNUSED\(x\)=\(void\)x ifeq ($(TARGET_NAME),TARGET_NANOX) -DEFINES += HAVE_BLE BLE_COMMAND_TIMEOUT_MS=2000 -DEFINES += HAVE_BLE_APDU # basic ledger apdu transport over BLE + DEFINES += HAVE_BLE BLE_COMMAND_TIMEOUT_MS=2000 HAVE_BLE_APDU endif ifeq ($(TARGET_NAME),TARGET_NANOS) -DEFINES += IO_SEPROXYHAL_BUFFER_SIZE_B=128 + DEFINES += IO_SEPROXYHAL_BUFFER_SIZE_B=128 else -DEFINES += IO_SEPROXYHAL_BUFFER_SIZE_B=300 -DEFINES += HAVE_GLO096 -DEFINES += HAVE_BAGL BAGL_WIDTH=128 BAGL_HEIGHT=64 -DEFINES += HAVE_BAGL_ELLIPSIS # long label truncation feature -DEFINES += HAVE_BAGL_FONT_OPEN_SANS_REGULAR_11PX -DEFINES += HAVE_BAGL_FONT_OPEN_SANS_EXTRABOLD_11PX -DEFINES += HAVE_BAGL_FONT_OPEN_SANS_LIGHT_16PX + DEFINES += IO_SEPROXYHAL_BUFFER_SIZE_B=300 + DEFINES += HAVE_GLO096 + DEFINES += BAGL_WIDTH=128 BAGL_HEIGHT=64 + DEFINES += HAVE_BAGL_ELLIPSIS + DEFINES += HAVE_BAGL_FONT_OPEN_SANS_REGULAR_11PX + DEFINES += HAVE_BAGL_FONT_OPEN_SANS_EXTRABOLD_11PX + DEFINES += HAVE_BAGL_FONT_OPEN_SANS_LIGHT_16PX endif -# Both nano S and X benefit from the flow. -DEFINES += HAVE_UX_FLOW - -# Enabling debug PRINTF DEBUG = 0 ifneq ($(DEBUG),0) - - ifeq ($(TARGET_NAME),TARGET_NANOS) - DEFINES += HAVE_PRINTF PRINTF=screen_printf - else - DEFINES += HAVE_PRINTF PRINTF=mcu_usb_printf - endif + DEFINES += HAVE_PRINTF + ifeq ($(TARGET_NAME),TARGET_NANOS) + DEFINES += PRINTF=screen_printf + else + DEFINES += PRINTF=mcu_usb_printf + endif else - DEFINES += PRINTF\(...\)= + DEFINES += PRINTF\(...\)= endif -############## -# Compiler # -############## ifneq ($(BOLOS_ENV),) $(info BOLOS_ENV=$(BOLOS_ENV)) CLANGPATH := $(BOLOS_ENV)/clang-arm-fropi/bin/ -GCCPATH := $(BOLOS_ENV)/gcc-arm-none-eabi-5_3-2016q1/bin/ +GCCPATH := $(BOLOS_ENV)/gcc-arm-none-eabi-5_3-2016q1/bin/ else $(info BOLOS_ENV is not set: falling back to CLANGPATH and GCCPATH) endif - ifeq ($(CLANGPATH),) $(info CLANGPATH is not set: clang will be used from PATH) endif - ifeq ($(GCCPATH),) $(info GCCPATH is not set: arm-none-eabi-* will be used from PATH) endif -CC := $(CLANGPATH)clang +CC := $(CLANGPATH)clang +CFLAGS += -O3 -Os +AS := $(GCCPATH)arm-none-eabi-gcc +LD := $(GCCPATH)arm-none-eabi-gcc +LDFLAGS += -O3 -Os +LDLIBS += -lm -lgcc -lc -CFLAGS += -O3 -Os - -AS := $(GCCPATH)arm-none-eabi-gcc - -LD := $(GCCPATH)arm-none-eabi-gcc -LDFLAGS += -O3 -Os -LDLIBS += -lm -lgcc -lc - -# import rules to compile glyphs(/pone) include $(BOLOS_SDK)/Makefile.glyphs -### variables processed by the common makefile.rules of the SDK to grab source files and include dirs -APP_SOURCE_PATH += src -SOURCE_FILES += $(filter-out %_test.c,$(wildcard libsol/*.c)) -SDK_SOURCE_PATH += lib_stusb lib_stusb_impl lib_u2f -SDK_SOURCE_PATH += lib_ux -CFLAGS += -Ilibsol/include +APP_SOURCE_PATH += src +SDK_SOURCE_PATH += lib_stusb lib_stusb_impl lib_ux ifeq ($(TARGET_NAME),TARGET_NANOX) -SDK_SOURCE_PATH += lib_blewbxx lib_blewbxx_impl + SDK_SOURCE_PATH += lib_blewbxx lib_blewbxx_impl endif -# import generic rules from the sdk -include $(BOLOS_SDK)/Makefile.rules +WITH_U2F=0 +ifneq ($(WITH_U2F),0) + DEFINES += HAVE_U2F HAVE_IO_U2F + DEFINES += U2F_PROXY_MAGIC=\"~SOL\" + SDK_SOURCE_PATH += lib_u2f +endif -#add dependency on custom makefile filename -dep/%.d: %.c Makefile +WITH_LIBSOL=1 +ifneq ($(WITH_LIBSOL),0) + SOURCE_FILES += $(filter-out %_test.c,$(wildcard libsol/*.c)) + CFLAGS += -Ilibsol/include + DEFINES += HAVE_SNPRINTF_FORMAT_U + DEFINES += NDEBUG +endif -load: all +load: all load-only load-only: python3 -m ledgerblue.loadApp $(APP_LOAD_PARAMS) @@ -161,20 +149,9 @@ load-offline: all delete: python3 -m ledgerblue.deleteApp $(COMMON_DELETE_PARAMS) -release: install.sh - -install.sh: all requirements.txt bin/app.hex - echo > install.sh - - export APP_CODE="$$(cat bin/app.hex)"; \ - export APP_REQUIREMENTS="$$(cat requirements.txt)"; \ - export APP_LOAD_PARAMS_EVALUATED="$(shell printf '\\"%s\\" ' $(APP_LOAD_PARAMS:bin/%=%))"; \ - cat install-template.sh | envsubst '$$APP_LOAD_PARAMS_EVALUATED $$APP_CODE $$APP_REQUIREMENTS' >> install.sh - - chmod +x install.sh +include $(BOLOS_SDK)/Makefile.rules -deps: - python3 -mpip install -r requirements.txt --require-hashes +dep/%.d: %.c Makefile listvariants: @echo VARIANTS COIN solana diff --git a/README.md b/README.md index df5f47c6..9f617419 100644 --- a/README.md +++ b/README.md @@ -20,23 +20,23 @@ Current Features: ``` git clone https://github.com/LedgerHQ/ledger-app-builder.git ``` -1. Change directories +2. Change directories ``` cd ledger-app-builder ``` -1. Checkout the target commit +3. Checkout the target commit ``` -git checkout 0bdab1e +git checkout 73c9e07 ``` -1. Build the image +4. Build the image ``` -docker build -t ledger-app-builder:0bdab1e . +docker build -t ledger-app-builder:73c9e07 . ``` * If permissions errors are encountered, ensure that your user is in the `docker` group and that the session has been restarted ### For working with the device -* Install Python3 PIP +#### Install Python3 PIP Ubuntu Linux: ``` sudo apt install pip3 @@ -45,10 +45,36 @@ MacOS ``` brew install python3 ``` -* Install ledgerblue python module +#### Install ledgerblue python module ``` pip3 install ledgerblue ``` +#### Locally clone SDK repos corresponding to those included in the Docker image +* Setup environment +```bash +cat >>"${HOME}"/.profile < ``` + ### Clean ```bash ./docker-make clean ``` ## Working with the device -Requires that the `BOLOS_SDK` envvar [be set](https://developers.ledger.com/docs/nano-app/load/) +Requires that the `BOLOS_SDK` envvar [be set](https://developers.ledger.com/docs/nano-app/load/). +This can be achieved by first [building](#build) for the desired target device. ### Load ```bash make load-only diff --git a/doc/api.md b/doc/api.md index 1e734514..4a4c2089 100644 --- a/doc/api.md +++ b/doc/api.md @@ -1,5 +1,12 @@ -Solana application : Common Technical Specifications -======================================================= +# Solana application : Common Technical Specifications + +## 1.3.1 + +- Add support for versioned messages + +## 1.3.0 + +- Add SIGN SOLANA OFF-CHAIN MESSAGE ## About @@ -7,7 +14,9 @@ This application describes the APDU messages interface to communicate with the S The application covers the following functionalities : - - Retrieve an address given an account number +- Retrieve an address given an account number +- Sign Solana transaction +- Sign off-chain message The application interface can be accessed over HID or BLE @@ -21,9 +30,9 @@ _This command returns specific application configuration_ ##### Command -| *CLA* | *INS* | *P1* | *P2* | *Lc* | *Le* | -| ------------- |:-------------:| -----:| ------------- |:-------------:| -----: | -| E0 | 04 | 00 | 00 | 00 | 04 | +| _CLA_ | _INS_ | _P1_ | _P2_ | _Lc_ | _Le_ | +| ----- | :---: | ---: | ---- | :--: | ---: | +| E0 | 04 | 00 | 00 | 00 | 04 | ##### Input data @@ -31,15 +40,13 @@ _None_ ##### Output data - -| *Description* | *Length* -| ------------- |:-------------:| -| Dummy setting n°1 value | 01 -| Dummy setting n°2 value | 01 -| Application major version | 01 -| Application minor version | 01 -| Application patch version | 01 - +| _Description_ | _Length_ | +| ------------------------- | :------: | +| Dummy setting n°1 value | 01 | +| Dummy setting n°2 value | 01 | +| Application major version | 01 | +| Application minor version | 01 | +| Application patch version | 01 | ### GET PUBKEY @@ -49,29 +56,24 @@ _This command returns a Solana pubkey for the given BIP 32 path_ ##### Command -| *CLA* | *INS* | *P1* | *P2* | *Lc* | *Le* | -| ------------- |:-------------:| -----:| ------------- |:-------------:| -----: | -| E0 | 05 | 00 | 00 | variable | variable | - - +| _CLA_ | _INS_ | _P1_ | _P2_ | _Lc_ | _Le_ | +| ----- | :---: | ---: | ---- | :------: | -------: | +| E0 | 05 | 00 | 00 | variable | variable | ##### Input data - -| *Description* | *Length* -| ------------- |:-------------:| -| Number of BIP 32 derivations to perform (3 or 4) | 1 -| First derivation index (big endian) | 4 -| ... | 4 -| Last derivation index (big endian) | 4 +| _Description_ | _Length_ | +| ------------------------------------------------ | :------: | +| Number of BIP 32 derivations to perform (3 or 4) | 1 | +| First derivation index (big endian) | 4 | +| ... | 4 | +| Last derivation index (big endian) | 4 | ##### Output data - -| *Description* | *Length* -| ------------- |:-------------:| -| Pubkey | 32 - +| _Description_ | _Length_ | +| ------------- | :------: | +| Pubkey | 32 | ### SIGN SOLANA TRANSACTION @@ -81,31 +83,55 @@ _This command signs a Solana Transaction after having the user validate the tran ##### Command +| _CLA_ | _INS_ | _P1_ | _P2_ | _Lc_ | _Le_ | +| ----- | :---: | ---: | ---- | :------: | -------: | +| E0 | 06 | 01 | 00 | variable | variable | -| *CLA* | *INS* | *P1* | *P2* | *Lc* | *Le* -| ------------- |:-------------:| -----:| ------------- |:-------------:| -----: | -| E0 | 06 | 01 | 00 | variable | variable +##### Input data +| _Description_ | _Length_ | +| --------------------------------------------------- | :------: | +| Number of signers (derivation paths) (always 1) | 1 | +| Number of BIP 32 derivations to perform (2, 3 or 4) | 1 | +| First derivation index (big endian) | 4 | +| ... | 4 | +| Last derivation index (big endian) | 4 | +| Serialized transaction | variable | -##### Input data +##### Output data +| _Description_ | _Length_ | +| ------------- | :------: | +| Signature | 64 | -| *Description* | *Length* -| ------------- |:-------------:| -| Number of signers (derivation paths) (always 1) | 1 -| Number of BIP 32 derivations to perform (2, 3 or 4) | 1 -| First derivation index (big endian) | 4 -| ... | 4 -| Last derivation index (big endian) | 4 -| Serialized transaction | variable +### SIGN SOLANA OFF-CHAIN MESSAGE -##### Output data +#### Description + +_This command signs a Solana Off-Chain Message after having the user validate the text of ASCII encoded messages, or hash of UTF-8 encoded messages:_ + +##### Command + +| _CLA_ | _INS_ | _P1_ | _P2_ | _Lc_ | _Le_ | +| ----- | :---: | ---: | ---- | :------: | -------: | +| E0 | 07 | 01 | 00 | variable | variable | + +##### Input data +| _Description_ | _Length_ | +| --------------------------------------------------- | :------: | +| Number of signers (derivation paths) (always 1) | 1 | +| Number of BIP 32 derivations to perform (2, 3 or 4) | 1 | +| First derivation index (big endian) | 4 | +| ... | 4 | +| Last derivation index (big endian) | 4 | +| Serialized off-chain message | variable | -| *Description* | *Length* -| ------------- |:-------------:| -| Signature | 64 +##### Output data +| _Description_ | _Length_ | +| ------------- | :------: | +| Signature | 64 | ## Transport protocol @@ -115,14 +141,12 @@ _Ledger APDUs requests and responses are encapsulated using a flexible protocol The common transport header is defined as follows: - -| *Description* | *Length* -| ------------- |:-------------:| -| Communication channel ID (big endian) | 2 -| Command tag | 1 -| Packet sequence index (big endian) | 2 -| Payload | var - +| _Description_ | _Length_ | +| ------------------------------------- | :------: | +| Communication channel ID (big endian) | 2 | +| Command tag | 1 | +| Packet sequence index (big endian) | 2 | +| Payload | var | The Communication channel ID allows commands multiplexing over the same physical link. It is not used for the time being, and should be set to 0101 to avoid compatibility issues with implementations ignoring a leading 00 byte. @@ -134,26 +158,24 @@ The Packet sequence index describes the current sequence for fragmented payloads APDU Command payloads are encoded as follows : - -| *Description* | *Length* -| ------------- |:-------------:| -| APDU length (big endian) | 2 -| APDU CLA | 1 -| APDU INS | 1 -| APDU P1 | 1 -| APDU P2 | 1 -| APDU data length | 1 -| Optional APDU data | var +| _Description_ | _Length_ | +| ------------------------ | :------: | +| APDU length (big endian) | 2 | +| APDU CLA | 1 | +| APDU INS | 1 | +| APDU P1 | 1 | +| APDU P2 | 1 | +| APDU data length | 1 | +| Optional APDU data | var | APDU payload is encoded according to the APDU case - -| Case Number | *Lc* | *Le* | Case description -| ----------- | ---- | ---- | ---------------- -| 1 | 0 | 0 | No data in either direction - L is set to 00 -| 2 | 0 | !0 | Input Data present, no Output Data - L is set to Lc -| 3 | !0 | 0 | Output Data present, no Input Data - L is set to Le -| 4 | !0 | !0 | Both Input and Output Data are present - L is set to Lc +| Case Number | _Lc_ | _Le_ | Case description | +| ----------- | ---- | ---- | ------------------------------------------------------- | +| 1 | 0 | 0 | No data in either direction - L is set to 00 | +| 2 | 0 | !0 | Input Data present, no Output Data - L is set to Lc | +| 3 | !0 | 0 | Output Data present, no Input Data - L is set to Le | +| 4 | !0 | !0 | Both Input and Output Data are present - L is set to Lc | #### Deprecation notice @@ -167,12 +189,10 @@ The `ADPU data length` field was formerly serialized as a 16bit unsigned big end APDU Response payloads are encoded as follows : - -| *Description* | *Length* -| ------------- |:-------------:| -| APDU response length (big endian) | 2 -| APDU response data and Status Word | var - +| _Description_ | _Length_ | +| ---------------------------------- | :------: | +| APDU response length (big endian) | 2 | +| APDU response data and Status Word | var | ### USB mapping @@ -194,11 +214,13 @@ The following standard Status Words are returned for all APDUs - some specific S ##### Status Words -| *SW* | *Description* -| ------------- |:-------------:| -| 6700 | Incorrect length -| 6982 | Security status not satisfied (Canceled by user) -| 6A80 | Invalid data -| 6B00 | Incorrect parameter P1 or P2 -| 6Fxx | Technical problem (Internal error, please report) -| 9000 | Normal ending of the command +| _SW_ | _Description_ | +| ---- | :-----------------------------------------------: | +| 6700 | Incorrect length | +| 6982 | Security status not satisfied (Canceled by user) | +| 6A80 | Invalid data | +| 6A81 | Invalid off-chain message header | +| 6A82 | Invalid off-chain message format | +| 6B00 | Incorrect parameter P1 or P2 | +| 6Fxx | Technical problem (Internal error, please report) | +| 9000 | Normal ending of the command | diff --git a/docker-make b/docker-make index d3d77a3e..26605154 100755 --- a/docker-make +++ b/docker-make @@ -1,7 +1,43 @@ #!/usr/bin/env bash -docker_tag=0bdab1e +docker_tag=73c9e07 +docker_image_base=ledger-app-builder +docker_image="${docker_image_base}:${docker_tag}" + +if ! docker image inspect "$docker_image" &>/dev/null; then + echo "docker image \`$docker_image\` not found. please see README.md" 1>&2 + exit 1 +fi + here="$(readlink -f "$(dirname "$0")")" +source "$here"/util/active-target.sh + +last_target_sdk="$(read_last_target_sdk_mnemonic "$here")" +maybe_target_sdk="$(normalize_mnemonic "${1:-''}" false)" +if [[ -n "$maybe_target_sdk" ]]; then + shift +fi +target_sdk="${maybe_target_sdk:-"$last_target_sdk"}" + +if [[ -z "$target_sdk" ]]; then + echo 'cannot resolve target sdk. please pass `s`, `x` or `sp` as the first argument' 1>&2 + exit 1 +elif [[ -z "$last_target_sdk" ]]; then + write_last_target_sdk_mnemonic "$here" "$target_sdk" +elif [[ "$target_sdk" != "$last_target_sdk" ]]; then + echo "target_sdk change requested. please run \`$0 clean\` first" 1>&2 + exit 1 +fi + +bolos_sdk_var="$(sdk_mnemonic_to_bolos_variable "$target_sdk")" + user=$(id -u) group=$(id -g) owner="$user:$group" -docker run --rm -t -v "$here:/app" "ledger-app-builder:$docker_tag" /bin/bash -c "make ${*}; chown -fR $owner /app/{bin,debug,dep,libsol/target,obj,src/glyphs.{c,h}}" + +IFS='' read -r -d '' container_script < { + return element >= 0x20 && element <= 0x7e; + }) + ); + } + + static isUTF8(buffer) { + return buffer && isValidUTF8(buffer); + } + + isValid() { + if (this.version !== 0) { + return false; + } + let format = OffchainMessage.guessMessageFormat(this.message); + return format != null && format === this.messageFormat; + } + + isLedgerSupported(allowBlindSigning) { + return ( + this.isValid() && + (this.messageFormat === 0 || + (this.messageFormat === 1 && allowBlindSigning)) + ); + } + + serialize() { + if (!this.isValid()) { + throw new Error(`Invalid OffchainMessage: ${JSON.stringify(this)}`); + } + let buffer = Buffer.alloc(4); + let offset = buffer.writeUInt8(this.version); + offset = buffer.writeUInt8(this.messageFormat, offset); + offset = buffer.writeUInt16LE(this.message.length, offset); + return Buffer.concat([ + Buffer.from([255]), + Buffer.from("solana offchain"), + buffer, + this.message, + ]); + } + + verifySignature(signature, publicKey) { + return nacl.sign.detached.verify( + this.serialize(), + signature, + publicKey.toBuffer() + ); + } +} + /* * Helper for chunked send of large payloads */ -async function solana_send(transport, instruction, p1, payload) { +async function solanaSend(transport, instruction, p1, payload) { var p2 = 0; var payload_offset = 0; if (payload.length > MAX_PAYLOAD) { - while ((payload.length - payload_offset) > MAX_PAYLOAD) { + while (payload.length - payload_offset > MAX_PAYLOAD) { const buf = payload.slice(payload_offset, payload_offset + MAX_PAYLOAD); payload_offset += MAX_PAYLOAD; - console.log("send", (p2 | P2_MORE).toString(16), buf.length.toString(16), buf); - const reply = await transport.send(LEDGER_CLA, instruction, p1, (p2 | P2_MORE), buf); + console.log( + "send", + (p2 | P2_MORE).toString(16), + buf.length.toString(16), + buf + ); + const reply = await transport.send( + LEDGER_CLA, + instruction, + p1, + p2 | P2_MORE, + buf + ); if (reply.length != 2) { throw new TransportError( - "solana_send: Received unexpected reply payload", + "solanaSend: Received unexpected reply payload", "UnexpectedReplyPayload" ); } @@ -70,15 +191,15 @@ async function solana_send(transport, instruction, p1, payload) { return reply.slice(0, reply.length - 2); } -const BIP32_HARDENED_BIT = ((1 << 31) >>> 0); +const BIP32_HARDENED_BIT = (1 << 31) >>> 0; function _harden(n) { return (n | BIP32_HARDENED_BIT) >>> 0; } -function solana_derivation_path(account, change) { +function solanaDerivationPath(account, change) { var length; - if (typeof(account) === 'number') { - if (typeof(change) === 'number') { + if (typeof account === "number") { + if (typeof change === "number") { length = 4; } else { length = 3; @@ -87,10 +208,10 @@ function solana_derivation_path(account, change) { length = 2; } - var derivation_path = Buffer.alloc(1 + (length * 4)); + var derivation_path = Buffer.alloc(1 + length * 4); var offset = 0; offset = derivation_path.writeUInt8(length, offset); - offset = derivation_path.writeUInt32BE(_harden(44), offset); // Using BIP44 + offset = derivation_path.writeUInt32BE(_harden(44), offset); // Using BIP44 offset = derivation_path.writeUInt32BE(_harden(501), offset); // Solana's BIP44 path if (length > 2) { @@ -103,12 +224,28 @@ function solana_derivation_path(account, change) { return derivation_path; } -async function solana_ledger_get_pubkey(transport, derivation_path) { - return solana_send(transport, INS_GET_PUBKEY, P1_NON_CONFIRM, derivation_path); +async function solanaLedgerGetAppConfig(transport) { + const reply = await transport.send( + LEDGER_CLA, + INS_GET_APP_CONFIG, + P1_NON_CONFIRM, + 0, + Buffer.alloc(0) + ); + + return reply.slice(0, reply.length - 2); } -async function solana_ledger_sign_transaction(transport, derivation_path, transaction) { - const msg_bytes = transaction.compileMessage().serialize(); +async function solanaLedgerGetPubkey(transport, derivation_path) { + return solanaSend(transport, INS_GET_PUBKEY, P1_NON_CONFIRM, derivation_path); +} + +async function solanaLedgerSignTransaction( + transport, + derivation_path, + message +) { + const msg_bytes = message.serialize(); // XXX: Ledger app only supports a single derivation_path per call ATM var num_paths = Buffer.alloc(1); @@ -116,22 +253,51 @@ async function solana_ledger_sign_transaction(transport, derivation_path, transa const payload = Buffer.concat([num_paths, derivation_path, msg_bytes]); - return solana_send(transport, INS_SIGN_MESSAGE, P1_CONFIRM, payload); + return solanaSend(transport, INS_SIGN_MESSAGE, P1_CONFIRM, payload); +} + +async function solanaLedgerSignOffchainMessage( + transport, + derivation_path, + message +) { + if (!message.isLedgerSupported(true)) { + throw new Error("Provided message is not supported by Ledger"); + } + const payload = Buffer.concat([ + Buffer.from([1]), + derivation_path, + message.serialize(), + ]); + + return solanaSend(transport, INS_SIGN_OFFCHAIN_MESSAGE, P1_CONFIRM, payload); } -( async () => { - var transport = await Transport.create(); +(async () => { + var transport = await Transport.open(); + + const app_config = await solanaLedgerGetAppConfig(transport); + console.log("App config:", app_config); - const from_derivation_path = solana_derivation_path(); - const from_pubkey_bytes = await solana_ledger_get_pubkey(transport, from_derivation_path); + // get "from" pubkey for transfer instruction + const from_derivation_path = solanaDerivationPath(); + const from_pubkey_bytes = await solanaLedgerGetPubkey( + transport, + from_derivation_path + ); const from_pubkey_string = bs58.encode(from_pubkey_bytes); - console.log("---", from_pubkey_string); + console.log("From pubkey:", from_pubkey_string); - const to_derivation_path = solana_derivation_path(1); - const to_pubkey_bytes = await solana_ledger_get_pubkey(transport, to_derivation_path); + // get "to" pubkey for transfer instruction + const to_derivation_path = solanaDerivationPath(1); + const to_pubkey_bytes = await solanaLedgerGetPubkey( + transport, + to_derivation_path + ); const to_pubkey_string = bs58.encode(to_pubkey_bytes); - console.log("---", to_pubkey_string); + console.log("To pubkey:", to_pubkey_string); + // create SOL transfer instruction const from_pubkey = new solana.PublicKey(from_pubkey_string); const to_pubkey = new solana.PublicKey(to_pubkey_string); const ix = solana.SystemProgram.transfer({ @@ -143,23 +309,91 @@ async function solana_ledger_sign_transaction(transport, derivation_path, transa // XXX: Fake blockhash so this example doesn't need a // network connection. It should be queried from the // cluster in normal use. - const recentBlockhash = bs58.encode(Buffer.from([ - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - ])); + const recentBlockhash = bs58.encode( + Buffer.from([ + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, + ]) + ); + // create and sign transfer transaction var tx = new solana.Transaction({ - recentBlockhash, + recentBlockhash: recentBlockhash, feePayer: from_pubkey, - }) - .add(ix); + }).add(ix); - const sig_bytes = await solana_ledger_sign_transaction(transport, from_derivation_path, tx); + let sig_bytes = await solanaLedgerSignTransaction( + transport, + from_derivation_path, + tx.compileMessage() + ); - const sig_string = bs58.encode(sig_bytes); - console.log("--- len:", sig_bytes.length, "sig:", sig_string); + let sig_string = bs58.encode(sig_bytes); + console.log("Sig len:", sig_bytes.length, "sig:", sig_string); + // verify transfer signature tx.addSignature(from_pubkey, sig_bytes); - console.log("--- verifies:", tx.verifySignatures()); -})().catch(e => console.log(e) ); + console.log("Sig verifies:", tx.verifySignatures()); + + // create and sign versioned transfer transaction + const messageV0 = solana.MessageV0.compile({ + addressLookupTableAccounts: [], + instructions: [ix], + payerKey: from_pubkey, + recentBlockhash, + }); + + sig_bytes = await solanaLedgerSignTransaction( + transport, + from_derivation_path, + messageV0 + ); + sig_string = bs58.encode(sig_bytes); + console.log("Sig len:", sig_bytes.length, "sig:", sig_string); + + let verifies = nacl.sign.detached.verify( + messageV0.serialize(), + sig_bytes, + from_pubkey.toBuffer() + ); + console.log("Sig verifies:", verifies); + + // create and sign off-chain message in ascii + // TIP: enable expert mode in Ledger to see message details + let message = new OffchainMessage({ + message: "Long Off-Chain Test Message.", + }); + console.log("Off-chain message:", message); + + sig_bytes = await solanaLedgerSignOffchainMessage( + transport, + from_derivation_path, + message + ); + sig_string = bs58.encode(sig_bytes); + console.log("Sig len:", sig_bytes.length, "sig:", sig_string); + + // verify off-chain message signature + console.log("Sig verifies:", message.verifySignature(sig_bytes, from_pubkey)); + + // create and sign off-chain message in UTF8 + // NOTE: enable blind signing in Ledger for this to work + message = new OffchainMessage({ + message: Buffer.from("Тестовое сообщение в формате UTF-8", "utf-8"), + }); + console.log("Off-chain message:", message); + const hash = crypto.createHash("sha256"); + hash.update(message.serialize()); + console.log("Expected hash:", bs58.encode(hash.digest())); + + sig_bytes = await solanaLedgerSignOffchainMessage( + transport, + from_derivation_path, + message + ); + sig_string = bs58.encode(sig_bytes); + console.log("Sig len:", sig_bytes.length, "sig:", sig_string); + // verify off-chain message signature + console.log("Sig verifies:", message.verifySignature(sig_bytes, from_pubkey)); +})().catch((e) => console.log(e)); diff --git a/fuzzing/fuzz_message.c b/fuzzing/fuzz_message.c index fcbd92ca..9fe0d8b0 100644 --- a/fuzzing/fuzz_message.c +++ b/fuzzing/fuzz_message.c @@ -2,7 +2,6 @@ #include "sol/parser.h" #include "sol/transaction_summary.h" - int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { Parser parser = {Data, Size}; PrintConfig print_config; @@ -22,10 +21,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { enum SummaryItemKind summary_step_kinds[MAX_TRANSACTION_SUMMARY_ITEMS]; size_t num_summary_steps = 0; - transaction_summary_finalize( - summary_step_kinds, - &num_summary_steps - ); + transaction_summary_finalize(summary_step_kinds, &num_summary_steps); for (size_t i = 0; i < num_summary_steps; i++) { transaction_summary_display_item(i, DisplayFlagLongPubkeys); diff --git a/libsol/common_byte_strings.h b/libsol/common_byte_strings.h index 5ef306d0..7afeeda1 100644 --- a/libsol/common_byte_strings.h +++ b/libsol/common_byte_strings.h @@ -2,84 +2,84 @@ // Visually distinguishable 32-byte arrays. Good for test hashes and pubkeys -#define BYTES32_BS58_1 /* "11111111111111111111111111111111" */ \ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +#define BYTES32_BS58_1 /* "11111111111111111111111111111111" */ \ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ + 0x00, 0x00 -#define BYTES32_BS58_2 /* "22222222222222222222222222222222222222222222"*/ \ - 0x0f, 0x1e, 0x6b, 0x14, 0x21, 0xc0, 0x4a, 0x07, 0x04, 0x31, 0x26, 0x5c, \ - 0x19, 0xc5, 0xbb, 0xee, 0x19, 0x92, 0xba, 0xe8, 0xaf, 0xd1, 0xcd, 0x07, \ - 0x8e, 0xf8, 0xaf, 0x70, 0x47, 0xdc, 0x11, 0xf7 +#define BYTES32_BS58_2 /* "22222222222222222222222222222222222222222222"*/ \ + 0x0f, 0x1e, 0x6b, 0x14, 0x21, 0xc0, 0x4a, 0x07, 0x04, 0x31, 0x26, 0x5c, 0x19, 0xc5, 0xbb, \ + 0xee, 0x19, 0x92, 0xba, 0xe8, 0xaf, 0xd1, 0xcd, 0x07, 0x8e, 0xf8, 0xaf, 0x70, 0x47, 0xdc, \ + 0x11, 0xf7 -#define BYTES32_BS58_3 /* "33333333333333333333333333333333333333333333"*/ \ - 0x1e, 0x3c, 0xd6, 0x28, 0x43, 0x80, 0x94, 0x0e, 0x08, 0x62, 0x4c, 0xb8, \ - 0x33, 0x8b, 0x77, 0xdc, 0x33, 0x25, 0x75, 0xd1, 0x5f, 0xa3, 0x9a, 0x0f, \ - 0x1d, 0xf1, 0x5e, 0xe0, 0x8f, 0xb8, 0x23, 0xee +#define BYTES32_BS58_3 /* "33333333333333333333333333333333333333333333"*/ \ + 0x1e, 0x3c, 0xd6, 0x28, 0x43, 0x80, 0x94, 0x0e, 0x08, 0x62, 0x4c, 0xb8, 0x33, 0x8b, 0x77, \ + 0xdc, 0x33, 0x25, 0x75, 0xd1, 0x5f, 0xa3, 0x9a, 0x0f, 0x1d, 0xf1, 0x5e, 0xe0, 0x8f, 0xb8, \ + 0x23, 0xee -#define BYTES32_BS58_4 /* "44444444444444444444444444444444444444444444"*/ \ - 0x2d, 0x5b, 0x41, 0x3c, 0x65, 0x40, 0xde, 0x15, 0x0c, 0x93, 0x73, 0x14, \ - 0x4d, 0x51, 0x33, 0xca, 0x4c, 0xb8, 0x30, 0xba, 0x0f, 0x75, 0x67, 0x16, \ - 0xac, 0xea, 0x0e, 0x50, 0xd7, 0x94, 0x35, 0xe5 +#define BYTES32_BS58_4 /* "44444444444444444444444444444444444444444444"*/ \ + 0x2d, 0x5b, 0x41, 0x3c, 0x65, 0x40, 0xde, 0x15, 0x0c, 0x93, 0x73, 0x14, 0x4d, 0x51, 0x33, \ + 0xca, 0x4c, 0xb8, 0x30, 0xba, 0x0f, 0x75, 0x67, 0x16, 0xac, 0xea, 0x0e, 0x50, 0xd7, 0x94, \ + 0x35, 0xe5 -#define BYTES32_BS58_5 /* "55555555555555555555555555555555555555555555"*/ \ - 0x3c, 0x79, 0xac, 0x50, 0x87, 0x01, 0x28, 0x1c, 0x10, 0xc4, 0x99, 0x70, \ - 0x67, 0x16, 0xef, 0xb8, 0x66, 0x4a, 0xeb, 0xa2, 0xbf, 0x47, 0x34, 0x1e, \ - 0x3b, 0xe2, 0xbd, 0xc1, 0x1f, 0x70, 0x47, 0xdc +#define BYTES32_BS58_5 /* "55555555555555555555555555555555555555555555"*/ \ + 0x3c, 0x79, 0xac, 0x50, 0x87, 0x01, 0x28, 0x1c, 0x10, 0xc4, 0x99, 0x70, 0x67, 0x16, 0xef, \ + 0xb8, 0x66, 0x4a, 0xeb, 0xa2, 0xbf, 0x47, 0x34, 0x1e, 0x3b, 0xe2, 0xbd, 0xc1, 0x1f, 0x70, \ + 0x47, 0xdc -#define BYTES32_BS58_6 /* "66666666666666666666666666666666666666666666"*/ \ - 0x4b, 0x98, 0x17, 0x64, 0xa8, 0xc1, 0x72, 0x23, 0x14, 0xf5, 0xbf, 0xcc, \ - 0x80, 0xdc, 0xab, 0xa6, 0x7f, 0xdd, 0xa6, 0x8b, 0x6f, 0x19, 0x01, 0x25, \ - 0xca, 0xdb, 0x6d, 0x31, 0x67, 0x4c, 0x59, 0xd3 +#define BYTES32_BS58_6 /* "66666666666666666666666666666666666666666666"*/ \ + 0x4b, 0x98, 0x17, 0x64, 0xa8, 0xc1, 0x72, 0x23, 0x14, 0xf5, 0xbf, 0xcc, 0x80, 0xdc, 0xab, \ + 0xa6, 0x7f, 0xdd, 0xa6, 0x8b, 0x6f, 0x19, 0x01, 0x25, 0xca, 0xdb, 0x6d, 0x31, 0x67, 0x4c, \ + 0x59, 0xd3 -#define BYTES32_BS58_7 /* "77777777777777777777777777777777777777777777"*/ \ - 0x5a, 0xb6, 0x82, 0x78, 0xca, 0x81, 0xbc, 0x2a, 0x19, 0x26, 0xe6, 0x28, \ - 0x9a, 0xa2, 0x67, 0x94, 0x99, 0x70, 0x61, 0x74, 0x1e, 0xea, 0xce, 0x2d, \ - 0x59, 0xd4, 0x1c, 0xa1, 0xaf, 0x28, 0x6b, 0xca +#define BYTES32_BS58_7 /* "77777777777777777777777777777777777777777777"*/ \ + 0x5a, 0xb6, 0x82, 0x78, 0xca, 0x81, 0xbc, 0x2a, 0x19, 0x26, 0xe6, 0x28, 0x9a, 0xa2, 0x67, \ + 0x94, 0x99, 0x70, 0x61, 0x74, 0x1e, 0xea, 0xce, 0x2d, 0x59, 0xd4, 0x1c, 0xa1, 0xaf, 0x28, \ + 0x6b, 0xca -#define BYTES32_BS58_8 /* "88888888888888888888888888888888888888888888"*/ \ - 0x69, 0xd4, 0xed, 0x8c, 0xec, 0x42, 0x06, 0x31, 0x1d, 0x58, 0x0c, 0x84, \ - 0xb4, 0x68, 0x23, 0x82, 0xb3, 0x03, 0x1c, 0x5c, 0xce, 0xbc, 0x9b, 0x34, \ - 0xe8, 0xcc, 0xcc, 0x11, 0xf7, 0x04, 0x7d, 0xc1 +#define BYTES32_BS58_8 /* "88888888888888888888888888888888888888888888"*/ \ + 0x69, 0xd4, 0xed, 0x8c, 0xec, 0x42, 0x06, 0x31, 0x1d, 0x58, 0x0c, 0x84, 0xb4, 0x68, 0x23, \ + 0x82, 0xb3, 0x03, 0x1c, 0x5c, 0xce, 0xbc, 0x9b, 0x34, 0xe8, 0xcc, 0xcc, 0x11, 0xf7, 0x04, \ + 0x7d, 0xc1 // Program IDs -#define PROGRAM_ID_SPL_TOKEN /* "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" */\ - 0x06, 0xdd, 0xf6, 0xe1, 0xd7, 0x65, 0xa1, 0x93, 0xd9, 0xcb, 0xe1, 0x46, \ - 0xce, 0xeb, 0x79, 0xac, 0x1c, 0xb4, 0x85, 0xed, 0x5f, 0x5b, 0x37, 0x91, \ - 0x3a, 0x8c, 0xf5, 0x85, 0x7e, 0xff, 0x00, 0xa9 +#define PROGRAM_ID_SPL_TOKEN /* "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" */ \ + 0x06, 0xdd, 0xf6, 0xe1, 0xd7, 0x65, 0xa1, 0x93, 0xd9, 0xcb, 0xe1, 0x46, 0xce, 0xeb, 0x79, \ + 0xac, 0x1c, 0xb4, 0x85, 0xed, 0x5f, 0x5b, 0x37, 0x91, 0x3a, 0x8c, 0xf5, 0x85, 0x7e, 0xff, \ + 0x00, 0xa9 #define PROGRAM_ID_SYSTEM BYTES32_BS58_1 -#define PROGRAM_ID_STAKE /* "Stake11111111111111111111111111111111111111" */\ - 0x06, 0xa1, 0xd8, 0x17, 0x91, 0x37, 0x54, 0x2a, 0x98, 0x34, 0x37, 0xbd, \ - 0xfe, 0x2a, 0x7a, 0xb2, 0x55, 0x7f, 0x53, 0x5c, 0x8a, 0x78, 0x72, 0x2b, \ - 0x68, 0xa4, 0x9d, 0xc0, 0x00, 0x00, 0x00, 0x00 -#define PROGRAM_ID_VOTE /* "Vote111111111111111111111111111111111111111" */ \ - 0x07, 0x61, 0x48, 0x1d, 0x35, 0x74, 0x74, 0xbb, 0x7c, 0x4d, 0x76, 0x24, \ - 0xeb, 0xd3, 0xbd, 0xb3, 0xd8, 0x35, 0x5e, 0x73, 0xd1, 0x10, 0x43, 0xfc, \ - 0x0d, 0xa3, 0x53, 0x80, 0x00, 0x00, 0x00, 0x00 -#define PROGRAM_ID_SPL_ASSOCIATED_TOKEN_ACCOUNT \ - /* "ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL" */ \ - 0x8c, 0x97, 0x25, 0x8f, 0x4e, 0x24, 0x89, 0xf1, 0xbb, 0x3d, 0x10, 0x29, \ - 0x14, 0x8e, 0x0d, 0x83, 0x0b, 0x5a, 0x13, 0x99, 0xda, 0xff, 0x10, 0x84, \ - 0x04, 0x8e, 0x7b, 0xd8, 0xdb, 0xe9, 0xf8, 0x59 -#define PROGRAM_ID_SERUM_ASSERT_OWNER \ - /* "4MNPdKu9wFMvEeZBMt3Eipfs5ovVWTJb31pEXDJAAxX5" */ \ - 0x31, 0xca, 0xdc, 0xe2, 0xaa, 0x36, 0xec, 0x04, 0x60, 0x46, 0x83, 0xea, \ - 0xa6, 0xf1, 0x36, 0x2c, 0x32, 0x9e, 0x11, 0x91, 0x04, 0x28, 0x42, 0xa0, \ - 0x4e, 0x09, 0xb8, 0x2b, 0x75, 0x9f, 0xb3, 0x24 -#define PROGRAM_ID_SERUM_ASSERT_OWNER_PHANTOM \ - /* "DeJBGdMFa1uynnnKiwrVioatTuHmNLpyFKnmB5kaFdzQ" */ \ - 0xbb, 0xda, 0x27, 0xbc, 0x25, 0x19, 0xcb, 0xbe, 0xd7, 0xd4, 0x6f, 0x6b, \ - 0x19, 0x77, 0x2f, 0xe7, 0x1d, 0x72, 0xf3, 0x79, 0x94, 0x6c, 0x56, 0x9e, \ - 0x7d, 0x85, 0x0e, 0xca, 0x3c, 0x71, 0x1d, 0x31 -#define PROGRAM_ID_SPL_MEMO /* "MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr" */ \ - 0x05, 0x4a, 0x53, 0x5a, 0x99, 0x29, 0x21, 0x06, 0x4d, 0x24, 0xe8, 0x71, \ - 0x60, 0xda, 0x38, 0x7c, 0x7c, 0x35, 0xb5, 0xdd, 0xbc, 0x92, 0xbb, 0x81, \ - 0xe4, 0x1f, 0xa8, 0x40, 0x41, 0x05, 0x44, 0x8d +#define PROGRAM_ID_STAKE /* "Stake11111111111111111111111111111111111111" */ \ + 0x06, 0xa1, 0xd8, 0x17, 0x91, 0x37, 0x54, 0x2a, 0x98, 0x34, 0x37, 0xbd, 0xfe, 0x2a, 0x7a, \ + 0xb2, 0x55, 0x7f, 0x53, 0x5c, 0x8a, 0x78, 0x72, 0x2b, 0x68, 0xa4, 0x9d, 0xc0, 0x00, 0x00, \ + 0x00, 0x00 +#define PROGRAM_ID_VOTE /* "Vote111111111111111111111111111111111111111" */ \ + 0x07, 0x61, 0x48, 0x1d, 0x35, 0x74, 0x74, 0xbb, 0x7c, 0x4d, 0x76, 0x24, 0xeb, 0xd3, 0xbd, \ + 0xb3, 0xd8, 0x35, 0x5e, 0x73, 0xd1, 0x10, 0x43, 0xfc, 0x0d, 0xa3, 0x53, 0x80, 0x00, 0x00, \ + 0x00, 0x00 +#define PROGRAM_ID_SPL_ASSOCIATED_TOKEN_ACCOUNT \ + /* "ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL" */ \ + 0x8c, 0x97, 0x25, 0x8f, 0x4e, 0x24, 0x89, 0xf1, 0xbb, 0x3d, 0x10, 0x29, 0x14, 0x8e, 0x0d, \ + 0x83, 0x0b, 0x5a, 0x13, 0x99, 0xda, 0xff, 0x10, 0x84, 0x04, 0x8e, 0x7b, 0xd8, 0xdb, 0xe9, \ + 0xf8, 0x59 +#define PROGRAM_ID_SERUM_ASSERT_OWNER \ + /* "4MNPdKu9wFMvEeZBMt3Eipfs5ovVWTJb31pEXDJAAxX5" */ \ + 0x31, 0xca, 0xdc, 0xe2, 0xaa, 0x36, 0xec, 0x04, 0x60, 0x46, 0x83, 0xea, 0xa6, 0xf1, 0x36, \ + 0x2c, 0x32, 0x9e, 0x11, 0x91, 0x04, 0x28, 0x42, 0xa0, 0x4e, 0x09, 0xb8, 0x2b, 0x75, 0x9f, \ + 0xb3, 0x24 +#define PROGRAM_ID_SERUM_ASSERT_OWNER_PHANTOM \ + /* "DeJBGdMFa1uynnnKiwrVioatTuHmNLpyFKnmB5kaFdzQ" */ \ + 0xbb, 0xda, 0x27, 0xbc, 0x25, 0x19, 0xcb, 0xbe, 0xd7, 0xd4, 0x6f, 0x6b, 0x19, 0x77, 0x2f, \ + 0xe7, 0x1d, 0x72, 0xf3, 0x79, 0x94, 0x6c, 0x56, 0x9e, 0x7d, 0x85, 0x0e, 0xca, 0x3c, 0x71, \ + 0x1d, 0x31 +#define PROGRAM_ID_SPL_MEMO /* "MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr" */ \ + 0x05, 0x4a, 0x53, 0x5a, 0x99, 0x29, 0x21, 0x06, 0x4d, 0x24, 0xe8, 0x71, 0x60, 0xda, 0x38, \ + 0x7c, 0x7c, 0x35, 0xb5, 0xdd, 0xbc, 0x92, 0xbb, 0x81, 0xe4, 0x1f, 0xa8, 0x40, 0x41, 0x05, \ + 0x44, 0x8d // Sysvars -#define SYSVAR_RENT /* "SysvarRent111111111111111111111111111111111" */ \ - 0x06, 0xa7, 0xd5, 0x17, 0x19, 0x2c, 0x5c, 0x51, 0x21, 0x8c, 0xc9, 0x4c, \ - 0x3d, 0x4a, 0xf1, 0x7f, 0x58, 0xda, 0xee, 0x08, 0x9b, 0xa1, 0xfd, 0x44, \ - 0xe3, 0xdb, 0xd9, 0x8a, 0x00, 0x00, 0x00, 0x00 +#define SYSVAR_RENT /* "SysvarRent111111111111111111111111111111111" */ \ + 0x06, 0xa7, 0xd5, 0x17, 0x19, 0x2c, 0x5c, 0x51, 0x21, 0x8c, 0xc9, 0x4c, 0x3d, 0x4a, 0xf1, \ + 0x7f, 0x58, 0xda, 0xee, 0x08, 0x9b, 0xa1, 0xfd, 0x44, 0xe3, 0xdb, 0xd9, 0x8a, 0x00, 0x00, \ + 0x00, 0x00 diff --git a/libsol/include/sol/message.h b/libsol/include/sol/message.h index 433306e3..0cd67eee 100644 --- a/libsol/include/sol/message.h +++ b/libsol/include/sol/message.h @@ -3,8 +3,6 @@ #include "parser.h" #include "print_config.h" -int process_message_body( - const uint8_t* message_body, - int message_body_length, - const PrintConfig* print_config -); +int process_message_body(const uint8_t* message_body, + int message_body_length, + const PrintConfig* print_config); diff --git a/libsol/include/sol/parser.h b/libsol/include/sol/parser.h index 7f0f211c..f5b2b1ef 100644 --- a/libsol/include/sol/parser.h +++ b/libsol/include/sol/parser.h @@ -5,8 +5,8 @@ #include #include -#define PUBKEY_SIZE 32 -#define HASH_SIZE 32 +#define PUBKEY_SIZE 32 +#define HASH_SIZE 32 #define BLOCKHASH_SIZE HASH_SIZE typedef struct Parser { @@ -51,12 +51,20 @@ typedef struct PubkeysHeader { } PubkeysHeader; typedef struct MessageHeader { + bool versioned; + uint8_t version; PubkeysHeader pubkeys_header; const Pubkey* pubkeys; const Blockhash* blockhash; size_t instructions_length; } MessageHeader; +typedef struct OffchainMessageHeader { + uint8_t version; + uint8_t format; + uint16_t length; +} OffchainMessageHeader; + static inline int parser_is_empty(Parser* parser) { return parser->buffer_length == 0; } @@ -79,17 +87,15 @@ int parse_pubkey(Parser* parser, const Pubkey** pubkey); int parse_pubkeys_header(Parser* parser, PubkeysHeader* header); -int parse_pubkeys( - Parser* parser, - PubkeysHeader* header, - const Pubkey** pubkeys -); +int parse_pubkeys(Parser* parser, PubkeysHeader* header, const Pubkey** pubkeys); int parse_blockhash(Parser* parser, const Hash** hash); #define parse_blockhash parse_hash int parse_message_header(Parser* parser, MessageHeader* header); +int parse_offchain_message_header(Parser* parser, OffchainMessageHeader* header); + int parse_instruction(Parser* parser, Instruction* instruction); // FIXME: I don't belong here diff --git a/libsol/include/sol/print_config.h b/libsol/include/sol/print_config.h index be8159c4..3e4b09b4 100644 --- a/libsol/include/sol/print_config.h +++ b/libsol/include/sol/print_config.h @@ -9,7 +9,4 @@ typedef struct PrintConfig { const Pubkey* signer_pubkey; } PrintConfig; -bool print_config_show_authority( - const PrintConfig* print_config, - const Pubkey* authority -); +bool print_config_show_authority(const PrintConfig* print_config, const Pubkey* authority); diff --git a/libsol/include/sol/printer.h b/libsol/include/sol/printer.h index bbf29e0b..0f694f7f 100644 --- a/libsol/include/sol/printer.h +++ b/libsol/include/sol/printer.h @@ -4,45 +4,33 @@ #include #include -#define SUMMARY_LENGTH 7 -#define TITLE_SIZE 32 +#define SUMMARY_LENGTH 7 +#define TITLE_SIZE 32 #define BASE58_PUBKEY_LENGTH 45 -#define BASE58_PUBKEY_SHORT (SUMMARY_LENGTH + 2 + SUMMARY_LENGTH + 1) +#define BASE58_PUBKEY_SHORT (SUMMARY_LENGTH + 2 + SUMMARY_LENGTH + 1) -int print_token_amount( - uint64_t amount, - const char *asset, - uint8_t decimals, - char *out, - size_t out_length -); +int print_token_amount(uint64_t amount, + const char *asset, + uint8_t decimals, + char *out, + size_t out_length); -int print_amount( - uint64_t amount, - char *out, - size_t out_length -); +int print_amount(uint64_t amount, char *out, size_t out_length); -int print_i64(int64_t i64, char* out, size_t out_length); +int print_i64(int64_t i64, char *out, size_t out_length); -int print_u64(uint64_t u64, char* out, size_t out_length); +int print_u64(uint64_t u64, char *out, size_t out_length); -int print_sized_string( - const SizedString* string, - char* out, - size_t out_length -); +int print_sized_string(const SizedString *string, char *out, size_t out_length); int print_string(const char *in, char *out, size_t out_length); -int print_summary( - const char *in, - char *out, - size_t out_length, - size_t left_length, - size_t right_length -); +int print_summary(const char *in, + char *out, + size_t out_length, + size_t left_length, + size_t right_length); -int print_timestamp(int64_t, char* out, size_t out_length); +int print_timestamp(int64_t, char *out, size_t out_length); int encode_base58(const void *in, size_t length, char *out, size_t maxoutlen); diff --git a/libsol/include/sol/transaction_summary.h b/libsol/include/sol/transaction_summary.h index 4168ecf1..b087210c 100644 --- a/libsol/include/sol/transaction_summary.h +++ b/libsol/include/sol/transaction_summary.h @@ -20,13 +20,12 @@ // If all _Required_ `SummaryItem`s have not been set, finalization will fail. #define NUM_GENERAL_ITEMS 11 -#define MAX_TRANSACTION_SUMMARY_ITEMS ( \ - 1 /* primary */ \ - + NUM_GENERAL_ITEMS \ - + 1 /* nonce_account */ \ - + 1 /* nonce_authority */ \ - + 1 /* fee_payer */ \ -) +#define MAX_TRANSACTION_SUMMARY_ITEMS \ + (1 /* primary */ \ + + NUM_GENERAL_ITEMS + 1 /* nonce_account */ \ + + 1 /* nonce_authority */ \ + + 1 /* fee_payer */ \ + ) typedef struct TokenAmount { uint64_t value; @@ -35,7 +34,7 @@ typedef struct TokenAmount { } TokenAmount; enum SummaryItemKind { - SummaryItemNone = 0, // SummaryItemNone always zero + SummaryItemNone = 0, // SummaryItemNone always zero SummaryItemAmount, SummaryItemTokenAmount, SummaryItemI64, @@ -46,6 +45,7 @@ enum SummaryItemKind { SummaryItemString, SummaryItemTimestamp, }; +typedef enum SummaryItemKind SummaryItemKind_t; typedef struct SummaryItem SummaryItem; @@ -55,17 +55,12 @@ extern char G_transaction_summary_text[TEXT_BUFFER_LENGTH]; void transaction_summary_reset(); enum DisplayFlags { - DisplayFlagNone = 0, - DisplayFlagLongPubkeys = 1 << 0, - DisplayFlagAll = ( - DisplayFlagLongPubkeys - ), + DisplayFlagNone = 0, + DisplayFlagLongPubkeys = 1 << 0, + DisplayFlagAll = DisplayFlagLongPubkeys, }; int transaction_summary_display_item(size_t item_index, enum DisplayFlags flags); -int transaction_summary_finalize( - enum SummaryItemKind* item_kinds, - size_t* item_kinds_len -); +int transaction_summary_finalize(enum SummaryItemKind* item_kinds, size_t* item_kinds_len); // Get a pointer to the requested SummaryItem. NULL if it has already been set SummaryItem* transaction_summary_primary_item(); @@ -77,50 +72,16 @@ SummaryItem* transaction_summary_general_item(); int transaction_summary_set_fee_payer_pubkey(const Pubkey* pubkey); // Assign type/title/value to a SummaryItem -void summary_item_set_amount( - SummaryItem* item, - const char* title, - uint64_t value -); -void summary_item_set_token_amount( - SummaryItem* item, - const char* title, - uint64_t value, - const char* symbol, - uint8_t decimals -); -void summary_item_set_i64( - SummaryItem* item, - const char* title, - int64_t value -); -void summary_item_set_u64( - SummaryItem* item, - const char* title, - uint64_t value -); -void summary_item_set_pubkey( - SummaryItem* item, - const char* title, - const Pubkey* value -); -void summary_item_set_hash( - SummaryItem* item, - const char* title, - const Hash* value -); -void summary_item_set_sized_string( - SummaryItem* item, - const char* title, - const SizedString* value -); -void summary_item_set_string( - SummaryItem* item, - const char* title, - const char* value -); -void summary_item_set_timestamp( - SummaryItem* item, - const char* title, - int64_t value -); +void summary_item_set_amount(SummaryItem* item, const char* title, uint64_t value); +void summary_item_set_token_amount(SummaryItem* item, + const char* title, + uint64_t value, + const char* symbol, + uint8_t decimals); +void summary_item_set_i64(SummaryItem* item, const char* title, int64_t value); +void summary_item_set_u64(SummaryItem* item, const char* title, uint64_t value); +void summary_item_set_pubkey(SummaryItem* item, const char* title, const Pubkey* value); +void summary_item_set_hash(SummaryItem* item, const char* title, const Hash* value); +void summary_item_set_sized_string(SummaryItem* item, const char* title, const SizedString* value); +void summary_item_set_string(SummaryItem* item, const char* title, const char* value); +void summary_item_set_timestamp(SummaryItem* item, const char* title, int64_t value); diff --git a/libsol/include/spl/token.h b/libsol/include/spl/token.h index 145c0c5e..857ceff0 100644 --- a/libsol/include/spl/token.h +++ b/libsol/include/spl/token.h @@ -22,9 +22,9 @@ */ enum Token_AccountState #ifdef __cplusplus - : uint8_t -#endif // __cplusplus - { + : uint8_t +#endif // __cplusplus +{ /** * Account is not yet initialized */ @@ -42,16 +42,16 @@ enum Token_AccountState }; #ifndef __cplusplus typedef uint8_t Token_AccountState; -#endif // __cplusplus +#endif // __cplusplus /** * Specifies the authority type for SetAuthority instructions */ enum Token_AuthorityType #ifdef __cplusplus - : uint8_t -#endif // __cplusplus - { + : uint8_t +#endif // __cplusplus +{ /** * Authority to mint new tokens */ @@ -71,7 +71,7 @@ enum Token_AuthorityType }; #ifndef __cplusplus typedef uint8_t Token_AuthorityType; -#endif // __cplusplus +#endif // __cplusplus typedef uint8_t Token_Pubkey[32]; diff --git a/libsol/instruction.c b/libsol/instruction.c index 14cf8671..1ea7a84e 100644 --- a/libsol/instruction.c +++ b/libsol/instruction.c @@ -7,10 +7,7 @@ #include "util.h" #include -enum ProgramId instruction_program_id( - const Instruction* instruction, - const MessageHeader* header -) { +enum ProgramId instruction_program_id(const Instruction* instruction, const MessageHeader* header) { const Pubkey* program_id = &header->pubkeys[instruction->program_id_index]; if (memcmp(program_id, &system_program_id, PUBKEY_SIZE) == 0) { return ProgramIdSystem; @@ -20,11 +17,7 @@ enum ProgramId instruction_program_id( return ProgramIdVote; } else if (memcmp(program_id, &spl_token_program_id, PUBKEY_SIZE) == 0) { return ProgramIdSplToken; - } else if (memcmp( - program_id, - &spl_associated_token_account_program_id, - PUBKEY_SIZE - ) == 0) { + } else if (memcmp(program_id, &spl_associated_token_account_program_id, PUBKEY_SIZE) == 0) { return ProgramIdSplAssociatedTokenAccount; } else if (is_serum_assert_owner_program_id(program_id)) { return ProgramIdSerumAssertOwner; @@ -35,45 +28,41 @@ enum ProgramId instruction_program_id( return ProgramIdUnknown; } -int instruction_validate( - const Instruction* instruction, - const MessageHeader* header -) { - BAIL_IF( - instruction->program_id_index >= header->pubkeys_header.pubkeys_length - ); +int instruction_validate(const Instruction* instruction, const MessageHeader* header) { + BAIL_IF(instruction->program_id_index >= header->pubkeys_header.pubkeys_length); for (size_t i = 0; i < instruction->accounts_length; i++) { - BAIL_IF( - instruction->accounts[i] >= header->pubkeys_header.pubkeys_length - ); + BAIL_IF(instruction->accounts[i] >= header->pubkeys_header.pubkeys_length); } return 0; } -bool instruction_info_matches_brief( - const InstructionInfo* info, - const InstructionBrief* brief -) { +bool instruction_info_matches_brief(const InstructionInfo* info, const InstructionBrief* brief) { if (brief->program_id == info->kind) { switch (brief->program_id) { - case ProgramIdSerumAssertOwner: return true; - case ProgramIdSplAssociatedTokenAccount: return true; - case ProgramIdSplMemo: return true; - case ProgramIdSplToken: return (brief->spl_token == info->spl_token.kind); - case ProgramIdStake: return (brief->stake == info->stake.kind); - case ProgramIdSystem: return (brief->system == info->system.kind); - case ProgramIdVote: return (brief->vote == info->vote.kind); - case ProgramIdUnknown: break; + case ProgramIdSerumAssertOwner: + return true; + case ProgramIdSplAssociatedTokenAccount: + return true; + case ProgramIdSplMemo: + return true; + case ProgramIdSplToken: + return (brief->spl_token == info->spl_token.kind); + case ProgramIdStake: + return (brief->stake == info->stake.kind); + case ProgramIdSystem: + return (brief->system == info->system.kind); + case ProgramIdVote: + return (brief->vote == info->vote.kind); + case ProgramIdUnknown: + break; } } return false; } -bool instruction_infos_match_briefs( - InstructionInfo* const * infos, - const InstructionBrief* briefs, - size_t len -) { +bool instruction_infos_match_briefs(InstructionInfo* const* infos, + const InstructionBrief* briefs, + size_t len) { size_t i; for (i = 0; i < len; i++) { if (!instruction_info_matches_brief(infos[i], &briefs[i])) { @@ -83,24 +72,19 @@ bool instruction_infos_match_briefs( return (i == len); } -void instruction_accounts_iterator_init( - InstructionAccountsIterator* it, - const MessageHeader* header, - const Instruction* instruction -) { +void instruction_accounts_iterator_init(InstructionAccountsIterator* it, + const MessageHeader* header, + const Instruction* instruction) { it->message_header_pubkeys = header->pubkeys; it->instruction_accounts_length = instruction->accounts_length; it->instruction_accounts = instruction->accounts; it->current_instruction_account = 0; } -int instruction_accounts_iterator_next( - InstructionAccountsIterator* it, - const Pubkey** next_account -) { +int instruction_accounts_iterator_next(InstructionAccountsIterator* it, + const Pubkey** next_account) { if (it->current_instruction_account < it->instruction_accounts_length) { - size_t pubkeys_index = - it->instruction_accounts[it->current_instruction_account++]; + size_t pubkeys_index = it->instruction_accounts[it->current_instruction_account++]; if (next_account) { *next_account = &it->message_header_pubkeys[pubkeys_index]; } @@ -109,9 +93,7 @@ int instruction_accounts_iterator_next( return 1; } -size_t instruction_accounts_iterator_remaining( - const InstructionAccountsIterator* it -) { +size_t instruction_accounts_iterator_remaining(const InstructionAccountsIterator* it) { if (it->current_instruction_account < it->instruction_accounts_length) { return it->instruction_accounts_length - it->current_instruction_account; } diff --git a/libsol/instruction.h b/libsol/instruction.h index 700ce48e..b0d4fe40 100644 --- a/libsol/instruction.h +++ b/libsol/instruction.h @@ -30,15 +30,8 @@ typedef struct InstructionInfo { }; } InstructionInfo; -enum ProgramId instruction_program_id( - const Instruction* instruction, - const MessageHeader* header -); -int instruction_validate( - const Instruction* instruction, - const MessageHeader* header -); - +enum ProgramId instruction_program_id(const Instruction* instruction, const MessageHeader* header); +int instruction_validate(const Instruction* instruction, const MessageHeader* header); typedef struct InstructionBrief { enum ProgramId program_id; @@ -51,22 +44,21 @@ typedef struct InstructionBrief { }; } InstructionBrief; -#define SPL_ASSOCIATED_TOKEN_ACCOUNT_IX_BRIEF { ProgramIdSplAssociatedTokenAccount, .none = 0 } -#define SPL_TOKEN_IX_BRIEF(spl_token_ix) { ProgramIdSplToken, .spl_token = (spl_token_ix) } -#define SYSTEM_IX_BRIEF(system_ix) { ProgramIdSystem, .system = (system_ix) } -#define STAKE_IX_BRIEF(stake_ix) { ProgramIdStake, .stake = (stake_ix) } -#define VOTE_IX_BRIEF(vote_ix) { ProgramIdVote, .vote = (vote_ix) } - -bool instruction_info_matches_brief( - const InstructionInfo* info, - const InstructionBrief* brief -); -bool instruction_infos_match_briefs( - InstructionInfo* const *infos, - const InstructionBrief* briefs, - size_t len -); +#define SPL_ASSOCIATED_TOKEN_ACCOUNT_IX_BRIEF \ + { ProgramIdSplAssociatedTokenAccount, .none = 0 } +#define SPL_TOKEN_IX_BRIEF(spl_token_ix) \ + { ProgramIdSplToken, .spl_token = (spl_token_ix) } +#define SYSTEM_IX_BRIEF(system_ix) \ + { ProgramIdSystem, .system = (system_ix) } +#define STAKE_IX_BRIEF(stake_ix) \ + { ProgramIdStake, .stake = (stake_ix) } +#define VOTE_IX_BRIEF(vote_ix) \ + { ProgramIdVote, .vote = (vote_ix) } +bool instruction_info_matches_brief(const InstructionInfo* info, const InstructionBrief* brief); +bool instruction_infos_match_briefs(InstructionInfo* const* infos, + const InstructionBrief* briefs, + size_t len); typedef struct InstructionAccountsIterator { const Pubkey* message_header_pubkeys; @@ -75,17 +67,11 @@ typedef struct InstructionAccountsIterator { size_t current_instruction_account; } InstructionAccountsIterator; -void instruction_accounts_iterator_init( - InstructionAccountsIterator* it, - const MessageHeader* header, - const Instruction* instruction -); +void instruction_accounts_iterator_init(InstructionAccountsIterator* it, + const MessageHeader* header, + const Instruction* instruction); -int instruction_accounts_iterator_next( - InstructionAccountsIterator* it, - const Pubkey** next_account -); +int instruction_accounts_iterator_next(InstructionAccountsIterator* it, + const Pubkey** next_account); -size_t instruction_accounts_iterator_remaining( - const InstructionAccountsIterator* it -); +size_t instruction_accounts_iterator_remaining(const InstructionAccountsIterator* it); diff --git a/libsol/instruction_test.c b/libsol/instruction_test.c index ead1fb48..5ab0b128 100644 --- a/libsol/instruction_test.c +++ b/libsol/instruction_test.c @@ -11,75 +11,113 @@ void test_instruction_program_id_system() { Pubkey program_id; memcpy(&program_id, &system_program_id, PUBKEY_SIZE); - Instruction instruction = { 0, NULL, 0, NULL, 0 }; - MessageHeader header = {{0, 0, 0, 1}, &program_id, NULL, 1}; - assert(instruction_program_id(&instruction, &header) == ProgramIdSystem); + Instruction instruction = {0, NULL, 0, NULL, 0}; + { + MessageHeader header = {false, 0, {0, 0, 0, 1}, &program_id, NULL, 1}; + assert(instruction_program_id(&instruction, &header) == ProgramIdSystem); + } + { + MessageHeader header = {true, 0, {0, 0, 0, 1}, &program_id, NULL, 1}; + assert(instruction_program_id(&instruction, &header) == ProgramIdSystem); + } } void test_instruction_program_id_stake() { Pubkey program_id; memcpy(&program_id, &stake_program_id, PUBKEY_SIZE); - Instruction instruction = { 0, NULL, 0, NULL, 0 }; - MessageHeader header = {{0, 0, 0, 1}, &program_id, NULL, 1}; - assert(instruction_program_id(&instruction, &header) == ProgramIdStake); + Instruction instruction = {0, NULL, 0, NULL, 0}; + { + MessageHeader header = {false, 0, {0, 0, 0, 1}, &program_id, NULL, 1}; + assert(instruction_program_id(&instruction, &header) == ProgramIdStake); + } + { + MessageHeader header = {true, 0, {0, 0, 0, 1}, &program_id, NULL, 1}; + assert(instruction_program_id(&instruction, &header) == ProgramIdStake); + } } void test_instruction_program_id_unknown() { - Pubkey program_id = {{ BYTES32_BS58_2 }}; - Instruction instruction = { 0, NULL, 0, NULL, 0 }; - MessageHeader header = {{0, 0, 0, 1}, &program_id, NULL, 1}; - assert(instruction_program_id(&instruction, &header) == ProgramIdUnknown); + Pubkey program_id = {{BYTES32_BS58_2}}; + Instruction instruction = {0, NULL, 0, NULL, 0}; + { + MessageHeader header = {false, 0, {0, 0, 0, 1}, &program_id, NULL, 1}; + assert(instruction_program_id(&instruction, &header) == ProgramIdUnknown); + } + { + MessageHeader header = {true, 0, {0, 0, 0, 1}, &program_id, NULL, 1}; + assert(instruction_program_id(&instruction, &header) == ProgramIdUnknown); + } } void test_instruction_validate_ok() { uint8_t accounts[] = {1, 2, 3}; Instruction instruction = {0, accounts, 3, NULL, 0}; - MessageHeader header = {{0, 0, 0, 4}, NULL, NULL, 1}; - assert(instruction_validate(&instruction, &header) == 0); + { + MessageHeader header = {false, 0, {0, 0, 0, 4}, NULL, NULL, 1}; + assert(instruction_validate(&instruction, &header) == 0); + } + { + MessageHeader header = {true, 0, {0, 0, 0, 4}, NULL, NULL, 1}; + assert(instruction_validate(&instruction, &header) == 0); + } } void test_instruction_validate_bad_program_id_index_fail() { uint8_t accounts[] = {1, 2, 3}; Instruction instruction = {4, accounts, 3, NULL, 0}; - MessageHeader header = {{0, 0, 0, 4}, NULL, NULL, 1}; - assert(instruction_validate(&instruction, &header) == 1); + { + MessageHeader header = {false, 0, {0, 0, 0, 4}, NULL, NULL, 1}; + assert(instruction_validate(&instruction, &header) == 1); + } + { + MessageHeader header = {true, 0, {0, 0, 0, 4}, NULL, NULL, 1}; + assert(instruction_validate(&instruction, &header) == 1); + } } void test_instruction_validate_bad_first_account_index_fail() { uint8_t accounts[] = {4, 2, 3}; Instruction instruction = {0, accounts, 3, NULL, 0}; - MessageHeader header = {{0, 0, 0, 4}, NULL, NULL, 1}; - assert(instruction_validate(&instruction, &header) == 1); + { + MessageHeader header = {false, 0, {0, 0, 0, 4}, NULL, NULL, 1}; + assert(instruction_validate(&instruction, &header) == 1); + } + { + MessageHeader header = {true, 0, {0, 0, 0, 4}, NULL, NULL, 1}; + assert(instruction_validate(&instruction, &header) == 1); + } } void test_instruction_validate_bad_last_account_index_fail() { uint8_t accounts[] = {1, 2, 4}; Instruction instruction = {0, accounts, 3, NULL, 0}; - MessageHeader header = {{0, 0, 0, 4}, NULL, NULL, 1}; - assert(instruction_validate(&instruction, &header) == 1); + { + MessageHeader header = {false, 0, {0, 0, 0, 4}, NULL, NULL, 1}; + assert(instruction_validate(&instruction, &header) == 1); + } + { + MessageHeader header = {true, 0, {0, 0, 0, 4}, NULL, NULL, 1}; + assert(instruction_validate(&instruction, &header) == 1); + } } void test_static_brief_initializer_macros() { InstructionBrief system_test = SYSTEM_IX_BRIEF(SystemTransfer); - InstructionBrief system_expect = { - ProgramIdSystem, - .system = SystemTransfer - }; - assert( - memcmp(&system_test, &system_expect, sizeof(InstructionBrief)) == 0 - ); + InstructionBrief system_expect = {ProgramIdSystem, .system = SystemTransfer}; + assert(memcmp(&system_test, &system_expect, sizeof(InstructionBrief)) == 0); InstructionBrief stake_test = STAKE_IX_BRIEF(StakeDelegate); - InstructionBrief stake_expect = { ProgramIdStake, .stake = StakeDelegate }; + InstructionBrief stake_expect = {ProgramIdStake, .stake = StakeDelegate}; assert(memcmp(&stake_test, &stake_expect, sizeof(InstructionBrief)) == 0); } void test_instruction_info_matches_brief() { InstructionInfo info = { .kind = ProgramIdSystem, - .system = { - .kind = SystemTransfer, - .transfer = { NULL, NULL, 0 }, - }, + .system = + { + .kind = SystemTransfer, + .transfer = {NULL, NULL, 0}, + }, }; InstructionBrief brief_pass = SYSTEM_IX_BRIEF(SystemTransfer); assert(instruction_info_matches_brief(&info, &brief_pass)); @@ -88,22 +126,22 @@ void test_instruction_info_matches_brief() { } void test_instruction_infos_match_briefs() { - InstructionInfo infos[] = { - { - .kind = ProgramIdSystem, - .system = { - .kind = SystemTransfer, - .transfer = { NULL, NULL, 0 }, - }, - }, - { - .kind = ProgramIdStake, - .stake = { - .kind = StakeDelegate, - .delegate_stake = { NULL, NULL, NULL }, - }, - } - }; + InstructionInfo infos[] = {{ + .kind = ProgramIdSystem, + .system = + { + .kind = SystemTransfer, + .transfer = {NULL, NULL, 0}, + }, + }, + { + .kind = ProgramIdStake, + .stake = + { + .kind = StakeDelegate, + .delegate_stake = {NULL, NULL, NULL}, + }, + }}; InstructionBrief briefs[] = { SYSTEM_IX_BRIEF(SystemTransfer), STAKE_IX_BRIEF(StakeDelegate), @@ -112,7 +150,7 @@ void test_instruction_infos_match_briefs() { SYSTEM_IX_BRIEF(SystemTransfer), STAKE_IX_BRIEF(StakeSplit), }; - InstructionInfo* display_infos[] = { &infos[0], &infos[1] }; + InstructionInfo* display_infos[] = {&infos[0], &infos[1]}; size_t infos_len = ARRAY_LEN(infos); assert(infos_len == ARRAY_LEN(display_infos)); assert(infos_len == ARRAY_LEN(briefs)); @@ -131,16 +169,18 @@ void test_instruction_accounts_iterator_next() { 0, }; Pubkey header_pubkeys[] = { - {{ BYTES32_BS58_2 }}, - {{ BYTES32_BS58_3 }}, - {{ BYTES32_BS58_4 }}, - {{ BYTES32_BS58_5 }}, + {{BYTES32_BS58_2}}, + {{BYTES32_BS58_3}}, + {{BYTES32_BS58_4}}, + {{BYTES32_BS58_5}}, }; MessageHeader header = { - {0, 0, 0, ARRAY_LEN(header_pubkeys)}, - header_pubkeys, - NULL, - 1, + false, + 0, + {0, 0, 0, ARRAY_LEN(header_pubkeys)}, + header_pubkeys, + NULL, + 1, }; InstructionAccountsIterator it; instruction_accounts_iterator_init(&it, &header, &instruction); @@ -148,7 +188,7 @@ void test_instruction_accounts_iterator_next() { assert(instruction_accounts_iterator_remaining(&it) == expected_remaining--); const Pubkey* pubkey; - Pubkey expected1 = {{ BYTES32_BS58_2 }}; + Pubkey expected1 = {{BYTES32_BS58_2}}; assert(instruction_accounts_iterator_next(&it, &pubkey) == 0); assert(memcmp(pubkey, &expected1, PUBKEY_SIZE) == 0); assert(instruction_accounts_iterator_remaining(&it) == expected_remaining--); @@ -157,7 +197,7 @@ void test_instruction_accounts_iterator_next() { assert(instruction_accounts_iterator_next(&it, NULL) == 0); assert(instruction_accounts_iterator_remaining(&it) == expected_remaining--); - Pubkey expected3 = {{ BYTES32_BS58_4 }}; + Pubkey expected3 = {{BYTES32_BS58_4}}; assert(instruction_accounts_iterator_next(&it, &pubkey) == 0); assert(instruction_accounts_iterator_remaining(&it) == expected_remaining); assert(memcmp(pubkey, &expected3, PUBKEY_SIZE) == 0); diff --git a/libsol/message.c b/libsol/message.c index 6bf6556a..620ea244 100644 --- a/libsol/message.c +++ b/libsol/message.c @@ -14,11 +14,9 @@ #define MAX_INSTRUCTIONS 4 -int process_message_body( - const uint8_t* message_body, - int message_body_length, - const PrintConfig* print_config -) { +int process_message_body(const uint8_t* message_body, + int message_body_length, + const PrintConfig* print_config) { const MessageHeader* header = &print_config->header; BAIL_IF(header->instructions_length == 0); @@ -32,20 +30,13 @@ int process_message_body( InstructionInfo* display_instruction_info[MAX_INSTRUCTIONS]; Parser parser = {message_body, message_body_length}; - for ( - ; - instruction_count < header->instructions_length; - instruction_count++ - ) { + for (; instruction_count < header->instructions_length; instruction_count++) { Instruction instruction; BAIL_IF(parse_instruction(&parser, &instruction)); BAIL_IF(instruction_validate(&instruction, header)); InstructionInfo* info = &instruction_info[instruction_count]; - enum ProgramId program_id = instruction_program_id( - &instruction, - header - ); + enum ProgramId program_id = instruction_program_id(&instruction, header); switch (program_id) { case ProgramIdSerumAssertOwner: { // Serum assert-owner only has one instruction and we ignore it @@ -56,9 +47,7 @@ int process_message_body( if (parse_spl_associated_token_account_instructions( &instruction, header, - &info->spl_associated_token_account - ) == 0 - ) { + &info->spl_associated_token_account) == 0) { info->kind = program_id; } break; @@ -69,44 +58,24 @@ int process_message_body( break; } case ProgramIdSplToken: - if (parse_spl_token_instructions( - &instruction, header, - &info->spl_token - ) == 0 - ) { + if (parse_spl_token_instructions(&instruction, header, &info->spl_token) == 0) { info->kind = program_id; } break; - case ProgramIdSystem: - { - if (parse_system_instructions( - &instruction, header, - &info->system - ) == 0 - ) { + case ProgramIdSystem: { + if (parse_system_instructions(&instruction, header, &info->system) == 0) { info->kind = program_id; } break; } - case ProgramIdStake: - { - if (parse_stake_instructions( - &instruction, - header, - &info->stake - ) == 0 - ) { + case ProgramIdStake: { + if (parse_stake_instructions(&instruction, header, &info->stake) == 0) { info->kind = program_id; } break; } case ProgramIdVote: { - if (parse_vote_instructions( - &instruction, - header, - &info->vote - ) == 0 - ) { + if (parse_vote_instructions(&instruction, header, &info->vote) == 0) { info->kind = program_id; } break; @@ -130,6 +99,12 @@ int process_message_body( } } + if (header->versioned) { + size_t account_tables_length; + BAIL_IF(parse_length(&parser, &account_tables_length)); + BAIL_IF(account_tables_length > 0); + } + // Ensure we've consumed the entire message body BAIL_IF(!parser_is_empty(&parser)); diff --git a/libsol/message_test.c b/libsol/message_test.c index c08001e2..8850813b 100644 --- a/libsol/message_test.c +++ b/libsol/message_test.c @@ -6,6 +6,9 @@ #include #include +// Disable clang format for this file to keep clear buffer formating +/* clang-format off */ + void test_process_message_body_ok() { Pubkey accounts[] = { {{171, 88, 202, 32, 185, 160, 182, 116, 130, 185, 73, 48, 13, 216, 170, 71, 172, 195, 165, 123, 87, 70, 130, 219, 5, 157, 240, 187, 26, 191, 158, 218}}, @@ -13,7 +16,7 @@ void test_process_message_body_ok() { {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, }; Blockhash blockhash = {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}; - PrintConfig print_config = { .header = {{1, 0, 1, 3}, accounts, &blockhash, 1}, .expert_mode = true }; + PrintConfig print_config = { .header = {false, 0, {1, 0, 1, 3}, accounts, &blockhash, 1}, .expert_mode = true }; uint8_t msg_body[] = {2, 2, 0, 1, 12, 2, 0, 0, 0, 42, 0, 0, 0, 0, 0, 0, 0}; transaction_summary_reset(); @@ -32,7 +35,7 @@ void test_process_message_body_xfer_w_nonce_ok() { {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, }; Blockhash blockhash = {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}; - PrintConfig print_config = { .header = {{1, 0, 1, 3}, accounts, &blockhash, 2}, .expert_mode = true }; + PrintConfig print_config = { .header = {false, 0, {1, 0, 1, 3}, accounts, &blockhash, 2}, .expert_mode = true }; uint8_t msg_body[] = { 2, 3, 0, 1, 0, 4, 4, 0, 0, 0, // Nonce 2, 2, 0, 1, 12, 2, 0, 0, 0, 42, 0, 0, 0, 0, 0, 0, 0 @@ -47,7 +50,7 @@ void test_process_message_body_xfer_w_nonce_ok() { } void test_process_message_body_too_few_ix_fail() { - PrintConfig print_config = { .header = {{0, 0, 0, 0}, NULL, NULL, 0}, .expert_mode = true }; + PrintConfig print_config = { .header = {false, 0, {0, 0, 0, 0}, NULL, NULL, 0}, .expert_mode = true }; assert(process_message_body(NULL, 0, &print_config) == 1); } @@ -68,12 +71,12 @@ void test_process_message_body_too_many_ix_fail() { uint8_t* start = msg_body + (i * XFER_IX_LEN); memcpy(start, xfer_ix, XFER_IX_LEN); } - PrintConfig print_config = { .header = {{1, 0, 1, 3}, accounts, &blockhash, TOO_MANY_IX}, .expert_mode = true }; + PrintConfig print_config = { .header = {false, 0, {1, 0, 1, 3}, accounts, &blockhash, TOO_MANY_IX}, .expert_mode = true }; assert(process_message_body(msg_body, ARRAY_LEN(msg_body), &print_config) == 1); } void test_process_message_body_data_too_short_fail() { - PrintConfig print_config = { .header = {{0, 0, 0, 0}, NULL, NULL, 1}, .expert_mode = true }; + PrintConfig print_config = { .header = {false, 0, {0, 0, 0, 0}, NULL, NULL, 1}, .expert_mode = true }; assert(process_message_body(NULL, 0, &print_config) == 1); } @@ -84,7 +87,7 @@ void test_process_message_body_data_too_long_fail() { {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, }; Blockhash blockhash = {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}; - PrintConfig print_config = { .header = {{1, 0, 1, 3}, accounts, &blockhash, 1}, .expert_mode = true }; + PrintConfig print_config = { .header = {false, 0, {1, 0, 1, 3}, accounts, &blockhash, 1}, .expert_mode = true }; uint8_t msg_body[] = { 2, 2, 0, 1, 12, 2, 0, 0, 0, 42, 0, 0, 0, 0, 0, 0, 0, 0 @@ -93,7 +96,7 @@ void test_process_message_body_data_too_long_fail() { } void test_process_message_body_bad_ix_account_index_fail() { - PrintConfig print_config = { .header = {{0, 0, 0, 1}, NULL, NULL, 1}, .expert_mode = true }; + PrintConfig print_config = { .header = {false, 0, {0, 0, 0, 1}, NULL, NULL, 1}, .expert_mode = true }; uint8_t msg_body[] = {1, 0, 0}; assert(process_message_body(msg_body, ARRAY_LEN(msg_body), &print_config) == 1); } @@ -105,7 +108,7 @@ void test_process_message_body_unknown_ix_enum_fail() { {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, }; Blockhash blockhash = {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}; - PrintConfig print_config = { .header = {{1, 0, 1, 3}, accounts, &blockhash, 1}, .expert_mode = true }; + PrintConfig print_config = { .header = {false, 0, {1, 0, 1, 3}, accounts, &blockhash, 1}, .expert_mode = true }; uint8_t msg_body[] = { 2, 2, 0, 1, 12, 255, 255, 255, 255, 42, 0, 0, 0, 0, 0, 0, 0, }; @@ -119,7 +122,7 @@ void test_process_message_body_ix_with_unknown_program_id_fail() { {{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}}, }; Blockhash blockhash = {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}; - PrintConfig print_config = { .header = {{1, 0, 1, 3}, accounts, &blockhash, 1}, .expert_mode = true }; + PrintConfig print_config = { .header = {false, 0, {1, 0, 1, 3}, accounts, &blockhash, 1}, .expert_mode = true }; uint8_t msg_body[] = { 2, 2, 0, 1, 12, 2, 0, 0, 0, 42, 0, 0, 0, 0, 0, 0, 0, }; @@ -1745,6 +1748,28 @@ void test_process_message_body_spl_token_thaw_account() { } void test_process_message_body_spl_associated_token_create() { + uint8_t message[] = { + 0x01, 0x00, 0x05, + 0x06, + 0x0a, 0xc5, 0x47, 0xa6, 0x54, 0x8f, 0xee, 0x6a, 0x3c, 0x47, 0xd2, 0x8c, 0x32, 0x2e, 0x05, 0x40, 0xc5, 0xe9, 0xb8, 0xb9, 0xf0, 0x01, 0xbd, 0x3c, 0x55, 0xd0, 0xff, 0xff, 0x17, 0xc1, 0x80, 0xde, + 0x1d, 0x30, 0x63, 0xde, 0x69, 0x0b, 0xcd, 0xbe, 0x38, 0xec, 0x74, 0x44, 0x99, 0x23, 0x20, 0x25, 0xc1, 0xad, 0x64, 0x92, 0x6e, 0xd5, 0x6c, 0x69, 0xa5, 0xe3, 0x10, 0x34, 0x41, 0x19, 0xcb, 0x57, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x06, 0xdd, 0xf6, 0xe1, 0xd7, 0x65, 0xa1, 0x93, 0xd9, 0xcb, 0xe1, 0x46, 0xce, 0xeb, 0x79, 0xac, 0x1c, 0xb4, 0x85, 0xed, 0x5f, 0x5b, 0x37, 0x91, 0x3a, 0x8c, 0xf5, 0x85, 0x7e, 0xff, 0x00, 0xa9, + 0x8c, 0x97, 0x25, 0x8f, 0x4e, 0x24, 0x89, 0xf1, 0xbb, 0x3d, 0x10, 0x29, 0x14, 0x8e, 0x0d, 0x83, 0x0b, 0x5a, 0x13, 0x99, 0xda, 0xff, 0x10, 0x84, 0x04, 0x8e, 0x7b, 0xd8, 0xdb, 0xe9, 0xf8, 0x59, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, + // SPL Associate Token Account -- Create + 0x05, + 0x06, + 0x00, 0x01, 0x00, 0x02, 0x03, 0x04, + 0x00, + }; + process_message_body_and_sanity_check(message, sizeof(message), 5); +} + +// old version of ata create that accessed the rent sysvar via account load +void test_process_message_body_spl_associated_token_create_deprecated() { uint8_t message[] = { 0x01, 0x00, 0x05, 0x07, @@ -1836,6 +1861,8 @@ void test_process_message_body_spl_associated_token_create_with_transfer_and_ass process_message_body_and_sanity_check(message, sizeof(message), 9); } +/* clang-format on */ + int main() { test_process_message_body_spl_associated_token_create_with_transfer_and_assert_owner(); test_process_message_body_spl_associated_token_create_with_transfer(); diff --git a/libsol/os_error.h b/libsol/os_error.h index a23ecb1e..1fa7e5ec 100644 --- a/libsol/os_error.h +++ b/libsol/os_error.h @@ -1,6 +1,6 @@ #pragma once // Duplicating error codes from BOLOS's os.h -#define EXCEPTION 1 -#define INVALID_PARAMETER 2 +#define EXCEPTION 1 +#define INVALID_PARAMETER 2 #define EXCEPTION_OVERFLOW 3 diff --git a/libsol/parser.c b/libsol/parser.c index 05fcbefd..8f1ef419 100644 --- a/libsol/parser.c +++ b/libsol/parser.c @@ -1,6 +1,10 @@ #include "sol/parser.h" #include "util.h" +#define OFFCHAIN_MESSAGE_SIGNING_DOMAIN \ + "\xff" \ + "solana offchain" + static int check_buffer_length(Parser* parser, size_t num) { return parser->buffer_length < num ? 1 : 0; } @@ -21,7 +25,7 @@ static int parse_u16(Parser* parser, uint16_t* value) { uint8_t lower, upper; BAIL_IF(parse_u8(parser, &lower)); BAIL_IF(parse_u8(parser, &upper)); - *value = lower + ((uint16_t)upper << 8); + *value = lower + ((uint16_t) upper << 8); return 0; } @@ -29,7 +33,7 @@ int parse_u32(Parser* parser, uint32_t* value) { uint16_t lower, upper; BAIL_IF(parse_u16(parser, &lower)); BAIL_IF(parse_u16(parser, &upper)); - *value = lower + ((uint32_t)upper << 16); + *value = lower + ((uint32_t) upper << 16); return 0; } @@ -38,7 +42,7 @@ int parse_u64(Parser* parser, uint64_t* value) { uint32_t lower, upper; BAIL_IF(parse_u32(parser, &lower)); BAIL_IF(parse_u32(parser, &upper)); - *value = lower + ((uint64_t)upper << 32); + *value = lower + ((uint64_t) upper << 32); return 0; } @@ -58,7 +62,7 @@ int parse_length(Parser* parser, size_t* value) { if (value_u8 & 0x80) { BAIL_IF(parse_u8(parser, &value_u8)); *value = ((value_u8 & 0x7f) << 14) | *value; - } + } } return 0; } @@ -82,7 +86,7 @@ int parse_sized_string(Parser* parser, SizedString* string) { BAIL_IF(string->length > SIZE_MAX); size_t len = (size_t) string->length; BAIL_IF(check_buffer_length(parser, len)); - string->string = (const char*)parser->buffer; + string->string = (const char*) parser->buffer; advance(parser, len); return 0; } @@ -102,11 +106,7 @@ int parse_pubkeys_header(Parser* parser, PubkeysHeader* header) { return 0; } -int parse_pubkeys( - Parser* parser, - PubkeysHeader* header, - const Pubkey** pubkeys -) { +int parse_pubkeys(Parser* parser, PubkeysHeader* header, const Pubkey** pubkeys) { BAIL_IF(parse_pubkeys_header(parser, header)); size_t pubkeys_size = header->pubkeys_length * PUBKEY_SIZE; BAIL_IF(check_buffer_length(parser, pubkeys_size)); @@ -122,18 +122,44 @@ int parse_hash(Parser* parser, const Hash** hash) { return 0; } +int parse_version(Parser* parser, MessageHeader* header) { + BAIL_IF(check_buffer_length(parser, 1)); + const uint8_t version = *parser->buffer; + if (version & 0x80) { + header->versioned = true; + header->version = version & 0x7f; + advance(parser, 1); + } else { + header->versioned = false; + header->version = 0; + } + return 0; +} + int parse_message_header(Parser* parser, MessageHeader* header) { + BAIL_IF(parse_version(parser, header)); BAIL_IF(parse_pubkeys(parser, &header->pubkeys_header, &header->pubkeys)); BAIL_IF(parse_blockhash(parser, &header->blockhash)); BAIL_IF(parse_length(parser, &header->instructions_length)); return 0; } -static int parse_data( - Parser* parser, - const uint8_t** data, - size_t* data_length -) { +int parse_offchain_message_header(Parser* parser, OffchainMessageHeader* header) { + const size_t domain_len = strlen(OFFCHAIN_MESSAGE_SIGNING_DOMAIN); + BAIL_IF(check_buffer_length(parser, domain_len)); + int res; + if ((res = memcmp(OFFCHAIN_MESSAGE_SIGNING_DOMAIN, parser->buffer, domain_len)) != 0) { + return res; + } + advance(parser, domain_len); + + BAIL_IF(parse_u8(parser, &header->version)); + BAIL_IF(parse_u8(parser, &header->format)); + BAIL_IF(parse_u16(parser, &header->length)); + return 0; +} + +static int parse_data(Parser* parser, const uint8_t** data, size_t* data_length) { BAIL_IF(parse_length(parser, data_length)); BAIL_IF(check_buffer_length(parser, *data_length)); *data = parser->buffer; @@ -143,12 +169,7 @@ static int parse_data( int parse_instruction(Parser* parser, Instruction* instruction) { BAIL_IF(parse_u8(parser, &instruction->program_id_index)); - BAIL_IF( - parse_data( - parser, - &instruction->accounts, - &instruction->accounts_length - )); + BAIL_IF(parse_data(parser, &instruction->accounts, &instruction->accounts_length)); BAIL_IF(parse_data(parser, &instruction->data, &instruction->data_length)); return 0; } diff --git a/libsol/parser_test.c b/libsol/parser_test.c index 11d99578..80b70941 100644 --- a/libsol/parser_test.c +++ b/libsol/parser_test.c @@ -6,66 +6,60 @@ #include void test_parse_u8() { - uint8_t message[] = {1, 2}; - Parser parser = {message, sizeof(message)}; - uint8_t value; - assert(parse_u8(&parser, &value) == 0); - assert(parser.buffer_length == 1); - assert(parser.buffer == message + 1); - assert(value == 1); + uint8_t message[] = {1, 2}; + Parser parser = {message, sizeof(message)}; + uint8_t value; + assert(parse_u8(&parser, &value) == 0); + assert(parser.buffer_length == 1); + assert(parser.buffer == message + 1); + assert(value == 1); } void test_parse_u8_too_short() { - uint8_t message[] = {42}; - Parser parser = {message, sizeof(message)}; - uint8_t value; - assert(parse_u8(&parser, &value) == 0); - assert(parse_u8(&parser, &value) == 1); + uint8_t message[] = {42}; + Parser parser = {message, sizeof(message)}; + uint8_t value; + assert(parse_u8(&parser, &value) == 0); + assert(parse_u8(&parser, &value) == 1); } void test_parse_u16() { - uint8_t message[] = {0, 0, 255, 255}; - Parser parser = {message, sizeof(message)}; - uint16_t value; - assert(parse_u16(&parser, &value) == 0); - assert(value == 0); - assert(parse_u16(&parser, &value) == 0); - assert(value == UINT16_MAX); - assert(parser_is_empty(&parser)); + uint8_t message[] = {0, 0, 255, 255}; + Parser parser = {message, sizeof(message)}; + uint16_t value; + assert(parse_u16(&parser, &value) == 0); + assert(value == 0); + assert(parse_u16(&parser, &value) == 0); + assert(value == UINT16_MAX); + assert(parser_is_empty(&parser)); } void test_parse_u32() { - uint8_t message[] = {0, 0, 0, 0, 255, 255, 255, 255}; - Parser parser = {message, sizeof(message)}; - uint32_t value; - assert(parse_u32(&parser, &value) == 0); - assert(value == 0); - assert(parse_u32(&parser, &value) == 0); - assert(value == UINT32_MAX); - assert(parser_is_empty(&parser)); + uint8_t message[] = {0, 0, 0, 0, 255, 255, 255, 255}; + Parser parser = {message, sizeof(message)}; + uint32_t value; + assert(parse_u32(&parser, &value) == 0); + assert(value == 0); + assert(parse_u32(&parser, &value) == 0); + assert(value == UINT32_MAX); + assert(parser_is_empty(&parser)); } void test_parse_u64() { - uint8_t message[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 255, 255, 255, 255, 255, 255, 255, 255 - }; - Parser parser = {message, sizeof(message)}; - uint64_t value; - assert(parse_u64(&parser, &value) == 0); - assert(value == 0); - assert(parse_u64(&parser, &value) == 0); - assert(value == UINT64_MAX); - assert(parser_is_empty(&parser)); + uint8_t message[] = {0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255}; + Parser parser = {message, sizeof(message)}; + uint64_t value; + assert(parse_u64(&parser, &value) == 0); + assert(value == 0); + assert(parse_u64(&parser, &value) == 0); + assert(value == UINT64_MAX); + assert(parser_is_empty(&parser)); } void test_parse_i64() { - uint8_t buffer[] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f - }; - Parser parser = { buffer, sizeof(buffer) }; + uint8_t buffer[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f}; + Parser parser = {buffer, sizeof(buffer)}; int64_t value; assert(parse_i64(&parser, &value) == 0); assert(value == INT64_MIN); @@ -76,18 +70,18 @@ void test_parse_i64() { } void test_parse_length() { - uint8_t message[] = {1, 2}; - Parser parser = {message, sizeof(message)}; - size_t value; - assert(parse_length(&parser, &value) == 0); - assert(parser.buffer_length == 1); - assert(parser.buffer == message + 1); - assert(value == 1); + uint8_t message[] = {1, 2}; + Parser parser = {message, sizeof(message)}; + size_t value; + assert(parse_length(&parser, &value) == 0); + assert(parser.buffer_length == 1); + assert(parser.buffer == message + 1); + assert(value == 1); } void test_parser_option() { - uint8_t message[] = { 0x00, 0x01, 0x02, 0xff }; - Parser parser = { message, sizeof(message) }; + uint8_t message[] = {0x00, 0x01, 0x02, 0xff}; + Parser parser = {message, sizeof(message)}; enum Option value; assert(parse_option(&parser, &value) == 0); @@ -104,18 +98,46 @@ void test_parser_option() { void test_parse_sized_string() { SizedString value; - uint8_t buffer[] = { - /* "test" */ - 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x74, 0x65, 0x73, 0x74, - /* length too long */ - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - /* remaining buffer too short for length */ - 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - /* buffer to short to read length */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }; - Parser parser = { buffer, sizeof(buffer) }; + uint8_t buffer[] = {/* "test" */ + 0x04, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x74, + 0x65, + 0x73, + 0x74, + /* length too long */ + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + /* remaining buffer too short for length */ + 0x10, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + /* buffer to short to read length */ + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00}; + Parser parser = {buffer, sizeof(buffer)}; assert(parse_sized_string(&parser, &value) == 0); assert(value.length == 4); @@ -130,19 +152,72 @@ void test_parse_pubkey() { const Pubkey* value; const char* expected_string = "11111111111111111111111111111111"; char value_string[BASE58_PUBKEY_LENGTH]; - uint8_t buffer[] = { - /* valid */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - /* too short */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }; - Parser parser = { buffer, sizeof(buffer) }; + uint8_t buffer[] = {/* valid */ + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + /* too short */ + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00}; + Parser parser = {buffer, sizeof(buffer)}; assert(parse_pubkey(&parser, &value) == 0); encode_base58(value, sizeof(Pubkey), value_string, sizeof(value_string)); assert_string_equal(expected_string, value_string); @@ -151,90 +226,90 @@ void test_parse_pubkey() { } void test_parse_length_two_bytes() { - uint8_t message[] = {128, 1}; - Parser parser = {message, sizeof(message)}; - size_t value; - assert(parse_length(&parser, &value) == 0); - assert(parser_is_empty(&parser)); - assert(parser.buffer == message + 2); - assert(value == 128); + uint8_t message[] = {128, 1}; + Parser parser = {message, sizeof(message)}; + size_t value; + assert(parse_length(&parser, &value) == 0); + assert(parser_is_empty(&parser)); + assert(parser.buffer == message + 2); + assert(value == 128); } void test_parse_pubkeys_header() { - uint8_t message[] = {1, 2, 3, 4}; - Parser parser = {message, sizeof(message)}; - PubkeysHeader header; - assert(parse_pubkeys_header(&parser, &header) == 0); - assert(parser_is_empty(&parser)); - assert(parser.buffer == message + 4); - assert(header.pubkeys_length == 4); + uint8_t message[] = {1, 2, 3, 4}; + Parser parser = {message, sizeof(message)}; + PubkeysHeader header; + assert(parse_pubkeys_header(&parser, &header) == 0); + assert(parser_is_empty(&parser)); + assert(parser.buffer == message + 4); + assert(header.pubkeys_length == 4); } void test_parse_pubkeys() { - uint8_t message[PUBKEY_SIZE + 4] = {1, 2, 3, 1, 42}; - Parser parser = {message, sizeof(message)}; - PubkeysHeader header; - const Pubkey* pubkeys; - assert(parse_pubkeys(&parser, &header, &pubkeys) == 0); - assert(parser_is_empty(&parser)); - assert(parser.buffer == message + PUBKEY_SIZE + 4); - assert(pubkeys->data[0] == 42); + uint8_t message[PUBKEY_SIZE + 4] = {1, 2, 3, 1, 42}; + Parser parser = {message, sizeof(message)}; + PubkeysHeader header; + const Pubkey* pubkeys; + assert(parse_pubkeys(&parser, &header, &pubkeys) == 0); + assert(parser_is_empty(&parser)); + assert(parser.buffer == message + PUBKEY_SIZE + 4); + assert(pubkeys->data[0] == 42); } void test_parse_pubkeys_too_short() { - uint8_t message[] = {1, 2, 3, 1}; - Parser parser = {message, sizeof(message)}; - PubkeysHeader header; - const Pubkey* pubkeys; - assert(parse_pubkeys(&parser, &header, &pubkeys) == 1); + uint8_t message[] = {1, 2, 3, 1}; + Parser parser = {message, sizeof(message)}; + PubkeysHeader header; + const Pubkey* pubkeys; + assert(parse_pubkeys(&parser, &header, &pubkeys) == 1); } void test_parse_hash() { - uint8_t message[HASH_SIZE] = {42}; - Parser parser = {message, sizeof(message)}; - const Hash* hash; - assert(parse_hash(&parser, &hash) == 0); - assert(parser_is_empty(&parser)); - assert(parser.buffer == message + HASH_SIZE); - assert(hash->data[0] == 42); + uint8_t message[HASH_SIZE] = {42}; + Parser parser = {message, sizeof(message)}; + const Hash* hash; + assert(parse_hash(&parser, &hash) == 0); + assert(parser_is_empty(&parser)); + assert(parser.buffer == message + HASH_SIZE); + assert(hash->data[0] == 42); } void test_parse_hash_too_short() { - uint8_t message[31]; // <--- Too short! - Parser parser = {message, sizeof(message)}; - const Hash* hash; - assert(parse_hash(&parser, &hash) == 1); + uint8_t message[31]; // <--- Too short! + Parser parser = {message, sizeof(message)}; + const Hash* hash; + assert(parse_hash(&parser, &hash) == 1); } void test_parse_data() { - uint8_t message[] = {1, 2}; - Parser parser = {message, sizeof(message)}; - const uint8_t* data; - size_t data_length; - assert(parse_data(&parser, &data, &data_length) == 0); - assert(parser_is_empty(&parser)); - assert(parser.buffer == message + 2); - assert(data[0] == 2); + uint8_t message[] = {1, 2}; + Parser parser = {message, sizeof(message)}; + const uint8_t* data; + size_t data_length; + assert(parse_data(&parser, &data, &data_length) == 0); + assert(parser_is_empty(&parser)); + assert(parser.buffer == message + 2); + assert(data[0] == 2); } void test_parse_data_too_short() { - uint8_t message[] = {1}; // <--- Too short! - Parser parser = {message, sizeof(message)}; - const uint8_t* data; - size_t data_length; - assert(parse_data(&parser, &data, &data_length) == 1); + uint8_t message[] = {1}; // <--- Too short! + Parser parser = {message, sizeof(message)}; + const uint8_t* data; + size_t data_length; + assert(parse_data(&parser, &data, &data_length) == 1); } void test_parse_instruction() { - uint8_t message[] = {0, 2, 33, 34, 1, 36}; - Parser parser = {message, sizeof(message)}; - Instruction instruction; - assert(parse_instruction(&parser, &instruction) == 0); - MessageHeader header = {{0, 0, 0, 35}, NULL, NULL, 1}; - assert(instruction_validate(&instruction, &header) == 0); - assert(parser_is_empty(&parser)); - assert(instruction.accounts[0] == 33); - assert(instruction.data[0] == 36); + uint8_t message[] = {0, 2, 33, 34, 1, 36}; + Parser parser = {message, sizeof(message)}; + Instruction instruction; + assert(parse_instruction(&parser, &instruction) == 0); + MessageHeader header = {false, 0, {0, 0, 0, 35}, NULL, NULL, 1}; + assert(instruction_validate(&instruction, &header) == 0); + assert(parser_is_empty(&parser)); + assert(instruction.accounts[0] == 33); + assert(instruction.data[0] == 36); } void test_parser_is_empty() { diff --git a/libsol/print_config.c b/libsol/print_config.c index 615a83d0..b575d1d5 100644 --- a/libsol/print_config.c +++ b/libsol/print_config.c @@ -1,10 +1,6 @@ #include "sol/print_config.h" #include "util.h" -bool print_config_show_authority( - const PrintConfig* print_config, - const Pubkey* authority -) { - return print_config->expert_mode - || !pubkeys_equal(print_config->signer_pubkey, authority); +bool print_config_show_authority(const PrintConfig* print_config, const Pubkey* authority) { + return print_config->expert_mode || !pubkeys_equal(print_config->signer_pubkey, authority); } diff --git a/libsol/print_config_test.c b/libsol/print_config_test.c index 025e781e..015c9999 100644 --- a/libsol/print_config_test.c +++ b/libsol/print_config_test.c @@ -4,9 +4,9 @@ #include void test_print_config_show_authority() { - Pubkey signer = {{ BYTES32_BS58_1 }}; - Pubkey not_signer = {{ BYTES32_BS58_2 }}; - PrintConfig print_config = { .expert_mode = false, .signer_pubkey = &signer }; + Pubkey signer = {{BYTES32_BS58_1}}; + Pubkey not_signer = {{BYTES32_BS58_2}}; + PrintConfig print_config = {.expert_mode = false, .signer_pubkey = &signer}; assert(!print_config_show_authority(&print_config, &signer)); assert(print_config_show_authority(&print_config, ¬_signer)); diff --git a/libsol/printer.c b/libsol/printer.c index e049c1e4..27b7489f 100644 --- a/libsol/printer.c +++ b/libsol/printer.c @@ -8,16 +8,14 @@ // max amount is max uint64 scaled down: "18446744073.709551615" #define AMOUNT_MAX_SIZE 22 -int print_token_amount( - uint64_t amount, - const char * const asset, - uint8_t decimals, - char *out, - const size_t out_length -) { +int print_token_amount(uint64_t amount, + const char *const asset, + uint8_t decimals, + char *out, + const size_t out_length) { BAIL_IF(out_length > INT_MAX); uint64_t dVal = amount; - const int outlen = (int)out_length; + const int outlen = (int) out_length; int i = 0; int min_chars = decimals + 1; @@ -47,7 +45,7 @@ int print_token_amount( i += 1; // Strip trailing . - if (out[i-1] == '.') i -= 1; + if (out[i - 1] == '.') i -= 1; if (asset) { const int asset_length = strlen(asset); @@ -64,19 +62,11 @@ int print_token_amount( } #define SOL_DECIMALS 9 -int print_amount( - uint64_t amount, - char *out, - size_t out_length -) { +int print_amount(uint64_t amount, char *out, size_t out_length) { return print_token_amount(amount, "SOL", SOL_DECIMALS, out, out_length); } -int print_sized_string( - const SizedString* string, - char* out, - size_t out_length -) { +int print_sized_string(const SizedString *string, char *out, size_t out_length) { size_t len = MIN(out_length, string->length); strncpy(out, string->string, len); if (string->length < out_length) { @@ -92,7 +82,7 @@ int print_sized_string( } } -int print_string(const char *in, char *out, size_t out_length){ +int print_string(const char *in, char *out, size_t out_length) { strncpy(out, in, out_length); int rc = (out[--out_length] != '\0'); if (rc) { @@ -106,24 +96,18 @@ int print_string(const char *in, char *out, size_t out_length){ return rc; } -int print_summary( - const char *in, - char *out, - size_t out_length, - size_t left_length, - size_t right_length -) { +int print_summary(const char *in, + char *out, + size_t out_length, + size_t left_length, + size_t right_length) { BAIL_IF(out_length <= (left_length + right_length + 2)); size_t in_length = strlen(in); if ((in_length + 1) > out_length) { memcpy(out, in, left_length); out[left_length] = '.'; out[left_length + 1] = '.'; - memcpy( - out + left_length + 2, - in + in_length - right_length, - right_length - ); + memcpy(out + left_length + 2, in + in_length - right_length, right_length); out[left_length + right_length + 2] = '\0'; } else { print_string(in, out, out_length); @@ -132,15 +116,11 @@ int print_summary( return 0; } -static const char BASE58_ALPHABET[] = { - '1', '2', '3', '4', '5', '6', '7', '8', '9', - 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J', - 'K', 'L', 'M', 'N', 'P', 'Q', 'R', 'S', 'T', - 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', - 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'm', - 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', - 'w', 'x', 'y', 'z' -}; +static const char BASE58_ALPHABET[] = {'1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', + 'D', 'E', 'F', 'G', 'H', 'J', 'K', 'L', 'M', 'N', 'P', 'Q', + 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', + 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'm', 'n', 'o', 'p', + 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'}; int encode_base58(const void *in, size_t length, char *out, size_t maxoutlen) { uint8_t tmp[64]; @@ -161,15 +141,15 @@ int encode_base58(const void *in, size_t length, char *out, size_t maxoutlen) { uint16_t remainder = 0; size_t div_loop; for (div_loop = start_at; div_loop < length; div_loop++) { - uint16_t digit256 = (uint16_t)(tmp[div_loop] & 0xff); + uint16_t digit256 = (uint16_t) (tmp[div_loop] & 0xff); uint16_t tmp_div = remainder * 256 + digit256; - tmp[div_loop] = (uint8_t)(tmp_div / 58); + tmp[div_loop] = (uint8_t) (tmp_div / 58); remainder = (tmp_div % 58); } if (tmp[start_at] == 0) { ++start_at; } - buffer[--j] = (uint8_t)BASE58_ALPHABET[remainder]; + buffer[--j] = (uint8_t) BASE58_ALPHABET[remainder]; } while ((j < (2 * length)) && (buffer[j] == BASE58_ALPHABET[0])) { ++j; @@ -186,7 +166,7 @@ int encode_base58(const void *in, size_t length, char *out, size_t maxoutlen) { return 0; } -int print_i64(int64_t i64, char* out, size_t out_length) { +int print_i64(int64_t i64, char *out, size_t out_length) { BAIL_IF(out_length < 1); uint64_t u64 = (uint64_t) i64; if (i64 < 0) { @@ -198,10 +178,10 @@ int print_i64(int64_t i64, char* out, size_t out_length) { return print_u64(u64, out, out_length); } -int print_u64(uint64_t u64, char* out, size_t out_length) { +int print_u64(uint64_t u64, char *out, size_t out_length) { BAIL_IF(out_length > INT_MAX); uint64_t dVal = u64; - int outlen = (int)out_length; + int outlen = (int) out_length; int i = 0; int j = 0; @@ -230,6 +210,6 @@ int print_u64(uint64_t u64, char* out, size_t out_length) { return 0; } -int print_timestamp(int64_t timestamp, char* out, size_t out_length) { +int print_timestamp(int64_t timestamp, char *out, size_t out_length) { return rfc3339_format(out, out_length, timestamp); } diff --git a/libsol/printer_test.c b/libsol/printer_test.c index fad3f211..285e13b5 100644 --- a/libsol/printer_test.c +++ b/libsol/printer_test.c @@ -3,53 +3,53 @@ #include void test_print_amount() { - char printed[24]; - - print_amount(0, printed, sizeof(printed)); - assert_string_equal(printed, "0 SOL"); - print_amount(1, printed, sizeof(printed)); - assert_string_equal(printed, "0.000000001 SOL"); - print_amount(1000000000, printed, sizeof(printed)); - assert_string_equal(printed, "1 SOL"); - print_amount(10000000000000001, printed, sizeof(printed)); - assert_string_equal(printed, "10000000.000000001 SOL"); - print_amount(10000000001, printed, sizeof(printed)); - assert_string_equal(printed, "10.000000001 SOL"); - print_amount(10000000100000000, printed, sizeof(printed)); - assert_string_equal(printed, "10000000.1 SOL"); + char printed[24]; + + print_amount(0, printed, sizeof(printed)); + assert_string_equal(printed, "0 SOL"); + print_amount(1, printed, sizeof(printed)); + assert_string_equal(printed, "0.000000001 SOL"); + print_amount(1000000000, printed, sizeof(printed)); + assert_string_equal(printed, "1 SOL"); + print_amount(10000000000000001, printed, sizeof(printed)); + assert_string_equal(printed, "10000000.000000001 SOL"); + print_amount(10000000001, printed, sizeof(printed)); + assert_string_equal(printed, "10.000000001 SOL"); + print_amount(10000000100000000, printed, sizeof(printed)); + assert_string_equal(printed, "10000000.1 SOL"); } void test_print_token_amount() { - char printed[26]; - - print_token_amount(0, "TST", 0, printed, sizeof(printed)); - assert_string_equal(printed, "0 TST"); - print_token_amount(0, "TST", 10, printed, sizeof(printed)); - assert_string_equal(printed, "0 TST"); - print_token_amount(0, "TST", 19, printed, sizeof(printed)); - assert_string_equal(printed, "0 TST"); - print_token_amount(1, "TST", 0, printed, sizeof(printed)); - assert_string_equal(printed, "1 TST"); - print_token_amount(1, "TST", 10, printed, sizeof(printed)); - assert_string_equal(printed, "0.0000000001 TST"); - print_token_amount(1, "TST", 19, printed, sizeof(printed)); - assert_string_equal(printed, "0.0000000000000000001 TST"); - print_token_amount(10000000000000000000ULL, "TST", 19, printed, sizeof(printed)); - assert_string_equal(printed, "1 TST"); - print_token_amount(UINT64_MAX, "TST", 19, printed, sizeof(printed)); - assert_string_equal(printed, "1.8446744073709551615 TST"); - print_token_amount(UINT64_MAX, "TST", 10, printed, sizeof(printed)); - assert_string_equal(printed, "1844674407.3709551615 TST"); - print_token_amount(UINT64_MAX, "TST", 1, printed, sizeof(printed)); - assert_string_equal(printed, "1844674407370955161.5 TST"); - print_token_amount(UINT64_MAX, "TST", 0, printed, sizeof(printed)); - assert_string_equal(printed, "18446744073709551615 TST"); + char printed[26]; + + print_token_amount(0, "TST", 0, printed, sizeof(printed)); + assert_string_equal(printed, "0 TST"); + print_token_amount(0, "TST", 10, printed, sizeof(printed)); + assert_string_equal(printed, "0 TST"); + print_token_amount(0, "TST", 19, printed, sizeof(printed)); + assert_string_equal(printed, "0 TST"); + print_token_amount(1, "TST", 0, printed, sizeof(printed)); + assert_string_equal(printed, "1 TST"); + print_token_amount(1, "TST", 10, printed, sizeof(printed)); + assert_string_equal(printed, "0.0000000001 TST"); + print_token_amount(1, "TST", 19, printed, sizeof(printed)); + assert_string_equal(printed, "0.0000000000000000001 TST"); + print_token_amount(10000000000000000000ULL, "TST", 19, printed, sizeof(printed)); + assert_string_equal(printed, "1 TST"); + print_token_amount(UINT64_MAX, "TST", 19, printed, sizeof(printed)); + assert_string_equal(printed, "1.8446744073709551615 TST"); + print_token_amount(UINT64_MAX, "TST", 10, printed, sizeof(printed)); + assert_string_equal(printed, "1844674407.3709551615 TST"); + print_token_amount(UINT64_MAX, "TST", 1, printed, sizeof(printed)); + assert_string_equal(printed, "1844674407370955161.5 TST"); + print_token_amount(UINT64_MAX, "TST", 0, printed, sizeof(printed)); + assert_string_equal(printed, "18446744073709551615 TST"); } void test_print_sized_string() { char buf[5]; - const char test[] = { 0x74, 0x65, 0x73, 0x74 }; - SizedString string = { sizeof(test), test }; + const char test[] = {0x74, 0x65, 0x73, 0x74}; + SizedString string = {sizeof(test), test}; assert(print_sized_string(&string, buf, sizeof(buf)) == 0); assert_string_equal(buf, "test"); @@ -79,25 +79,17 @@ void test_print_string() { void test_print_summary() { char summary[27]; - assert( - print_summary( - "GADFVW3UXVKDOU626XUPYDJU2BFCGFJHQ6SREYOZ6IJV4XSHOALEQN2I", - summary, - sizeof(summary), - 12, - 12 - ) == 0 - ); + assert(print_summary("GADFVW3UXVKDOU626XUPYDJU2BFCGFJHQ6SREYOZ6IJV4XSHOALEQN2I", + summary, + sizeof(summary), + 12, + 12) == 0); assert_string_equal(summary, "GADFVW3UXVKD..4XSHOALEQN2I"); - assert( - print_summary( - "GADFVW3UXVKDOU626XUPYDJU2BFCGFJHQ6SREYOZ6IJV4XSHOALEQN2I", - summary, - sizeof(summary), - 6, - 6 - ) == 0 - ); + assert(print_summary("GADFVW3UXVKDOU626XUPYDJU2BFCGFJHQ6SREYOZ6IJV4XSHOALEQN2I", + summary, + sizeof(summary), + 6, + 6) == 0); assert_string_equal(summary, "GADFVW..LEQN2I"); const char* test_fits = "short enough"; @@ -120,7 +112,7 @@ void test_print_i64() { } void test_print_u64() { -#define U64_MAX_STR (20 + 1) // strlen("18446744073709551615") + NUL +#define U64_MAX_STR (20 + 1) // strlen("18446744073709551615") + NUL char out[U64_MAX_STR]; assert(print_u64(0, out, sizeof(out)) == 0); diff --git a/libsol/rfc3339.c b/libsol/rfc3339.c index 9062b412..ad210077 100644 --- a/libsol/rfc3339.c +++ b/libsol/rfc3339.c @@ -2,16 +2,16 @@ * Copyright (c) 2014 Christian Hansen * * All rights reserved. - * + * * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * + * modification, are permitted provided that the following conditions are met: + * * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. + * list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * + * and/or other materials provided with the distribution. + * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE @@ -27,14 +27,11 @@ #include "rfc3339.h" #include "util.h" -static const uint16_t DayOffset[13] = { - 0, 306, 337, 0, 31, 61, 92, 122, 153, 184, 214, 245, 275 -}; +static const uint16_t DayOffset[13] = {0, 306, 337, 0, 31, 61, 92, 122, 153, 184, 214, 245, 275}; /* Rata Die algorithm by Peter Baum */ -static int -rdn_to_ymd(uint32_t rdn, uint16_t *yp, uint16_t *mp, uint16_t *dp) { +static int rdn_to_ymd(uint32_t rdn, uint16_t *yp, uint16_t *mp, uint16_t *dp) { uint32_t Z, H, A, B; uint32_t y, m, d; @@ -45,19 +42,21 @@ rdn_to_ymd(uint32_t rdn, uint16_t *yp, uint16_t *mp, uint16_t *dp) { y = (100 * B + H) / 36525; d = B + Z - (1461 * y >> 2); m = (535 * d + 48950) >> 14; - if (m > 12) - y++, m -= 12; + if (m > 12) { + y++; + m -= 12; + } BAIL_IF(y > 9999 || m > 12 || d > (31U + DayOffset[m])); - *yp = (uint16_t)y; - *mp = (uint16_t)m; - *dp = (uint16_t)(d - DayOffset[m]); + *yp = (uint16_t) y; + *mp = (uint16_t) m; + *dp = (uint16_t) (d - DayOffset[m]); return 0; } -#define EPOCH INT64_C(62135683200) /* 1970-01-01 00:00:00 */ +#define EPOCH INT64_C(62135683200) /* 1970-01-01 00:00:00 */ int rfc3339_format(char *dst, size_t len, int64_t seconds) { unsigned char *p; @@ -74,35 +73,44 @@ int rfc3339_format(char *dst, size_t len, int64_t seconds) { BAIL_IF(rdn_to_ymd(rdn, &y, &m, &d) != 0); - /* - * 1 - * 0123456789012345678 - * YYYY-MM-DDThh:mm:ss - */ - p = (unsigned char *)dst; + /* + * 1 + * 0123456789012345678 + * YYYY-MM-DDThh:mm:ss + */ + p = (unsigned char *) dst; v = sec % 86400; - p[18] = '0' + (v % 10); v /= 10; - p[17] = '0' + (v % 6); v /= 6; + p[18] = '0' + (v % 10); + v /= 10; + p[17] = '0' + (v % 6); + v /= 6; p[16] = ':'; - p[15] = '0' + (v % 10); v /= 10; - p[14] = '0' + (v % 6); v /= 6; + p[15] = '0' + (v % 10); + v /= 10; + p[14] = '0' + (v % 6); + v /= 6; p[13] = ':'; - p[12] = '0' + (v % 10); v /= 10; + p[12] = '0' + (v % 10); + v /= 10; p[11] = '0' + (v % 10); p[10] = ' '; - p[ 9] = '0' + (d % 10); d /= 10; - p[ 8] = '0' + (d % 10); - p[ 7] = '-'; - p[ 6] = '0' + (m % 10); m /= 10; - p[ 5] = '0' + (m % 10); - p[ 4] = '-'; - p[ 3] = '0' + (y % 10); y /= 10; - p[ 2] = '0' + (y % 10); y /= 10; - p[ 1] = '0' + (y % 10); y /= 10; - p[ 0] = '0' + (y % 10); + p[9] = '0' + (d % 10); + d /= 10; + p[8] = '0' + (d % 10); + p[7] = '-'; + p[6] = '0' + (m % 10); + m /= 10; + p[5] = '0' + (m % 10); + p[4] = '-'; + p[3] = '0' + (y % 10); + y /= 10; + p[2] = '0' + (y % 10); + y /= 10; + p[1] = '0' + (y % 10); + y /= 10; + p[0] = '0' + (y % 10); p += 19; *p = 0; return 0; } - diff --git a/libsol/rfc3339_test.c b/libsol/rfc3339_test.c index 3920700b..c66c7a0a 100644 --- a/libsol/rfc3339_test.c +++ b/libsol/rfc3339_test.c @@ -16,7 +16,7 @@ void test_rfc3339_format() { // seconds too small fails int64_t too_small = -EPOCH - 1; assert(rfc3339_format(s, sizeof(s), too_small) == 1); - + assert(rfc3339_format(s, sizeof(s), -EPOCH) == 0); assert_string_equal(s, "0000-12-31 00:00:00"); assert(rfc3339_format(s, sizeof(s), 0) == 0); diff --git a/libsol/serum_assert_owner_instruction.c b/libsol/serum_assert_owner_instruction.c index d71a1f58..e9c181bc 100644 --- a/libsol/serum_assert_owner_instruction.c +++ b/libsol/serum_assert_owner_instruction.c @@ -7,8 +7,8 @@ bool is_serum_assert_owner_program_id(const Pubkey* program_id) { static const Pubkey program_ids[] = { - {{ PROGRAM_ID_SERUM_ASSERT_OWNER_PHANTOM }}, - {{ PROGRAM_ID_SERUM_ASSERT_OWNER }}, + {{PROGRAM_ID_SERUM_ASSERT_OWNER_PHANTOM}}, + {{PROGRAM_ID_SERUM_ASSERT_OWNER}}, }; for (size_t i = 0; i < ARRAY_LEN(program_ids); i++) { if (pubkeys_equal(program_id, &program_ids[i])) { diff --git a/libsol/serum_assert_owner_instruction_test.c b/libsol/serum_assert_owner_instruction_test.c index 7a95921e..c6a6956a 100644 --- a/libsol/serum_assert_owner_instruction_test.c +++ b/libsol/serum_assert_owner_instruction_test.c @@ -5,8 +5,8 @@ #include void test_is_serum_assert_owner_program_id() { - const Pubkey serum_deployment = {{ PROGRAM_ID_SERUM_ASSERT_OWNER }}; - const Pubkey phantom_deployment = {{ PROGRAM_ID_SERUM_ASSERT_OWNER_PHANTOM }}; + const Pubkey serum_deployment = {{PROGRAM_ID_SERUM_ASSERT_OWNER}}; + const Pubkey phantom_deployment = {{PROGRAM_ID_SERUM_ASSERT_OWNER_PHANTOM}}; assert(is_serum_assert_owner_program_id(&serum_deployment)); assert(is_serum_assert_owner_program_id(&phantom_deployment)); diff --git a/libsol/spl_associated_token_account_instruction.c b/libsol/spl_associated_token_account_instruction.c index 52331213..86ecdae8 100644 --- a/libsol/spl_associated_token_account_instruction.c +++ b/libsol/spl_associated_token_account_instruction.c @@ -5,15 +5,12 @@ #include "spl_associated_token_account_instruction.h" #include "util.h" -const Pubkey spl_associated_token_account_program_id = {{ - PROGRAM_ID_SPL_ASSOCIATED_TOKEN_ACCOUNT -}}; +const Pubkey spl_associated_token_account_program_id = {{PROGRAM_ID_SPL_ASSOCIATED_TOKEN_ACCOUNT}}; static int parse_create_spl_associated_token_account_instruction( const Instruction* instruction, const MessageHeader* header, - SplAssociatedTokenAccountCreateInfo* info -) { + SplAssociatedTokenAccountCreateInfo* info) { InstructionAccountsIterator it; instruction_accounts_iterator_init(&it, header, instruction); @@ -25,28 +22,22 @@ static int parse_create_spl_associated_token_account_instruction( BAIL_IF(instruction_accounts_iterator_next(&it, NULL)); // Skip spl token program_id BAIL_IF(instruction_accounts_iterator_next(&it, NULL)); - // Skip rent sysvar - BAIL_IF(instruction_accounts_iterator_next(&it, NULL)); + // Skip (optional) rent sysvar + instruction_accounts_iterator_next(&it, NULL); return 0; } -int parse_spl_associated_token_account_instructions( - const Instruction* instruction, - const MessageHeader* header, - SplAssociatedTokenAccountInfo* info -) { - return parse_create_spl_associated_token_account_instruction( - instruction, - header, - &info->create - ); +int parse_spl_associated_token_account_instructions(const Instruction* instruction, + const MessageHeader* header, + SplAssociatedTokenAccountInfo* info) { + return parse_create_spl_associated_token_account_instruction(instruction, + header, + &info->create); } -int print_spl_associated_token_account_create_info( - const SplAssociatedTokenAccountCreateInfo* info, - const PrintConfig* print_config -) { +int print_spl_associated_token_account_create_info(const SplAssociatedTokenAccountCreateInfo* info, + const PrintConfig* print_config) { UNUSED(print_config); SummaryItem* item = transaction_summary_primary_item(); @@ -69,12 +60,7 @@ int print_spl_associated_token_account_create_info( return 0; } -int print_spl_associated_token_account_info( - const SplAssociatedTokenAccountInfo* info, - const PrintConfig* print_config -) { - return print_spl_associated_token_account_create_info( - &info->create, - print_config - ); +int print_spl_associated_token_account_info(const SplAssociatedTokenAccountInfo* info, + const PrintConfig* print_config) { + return print_spl_associated_token_account_create_info(&info->create, print_config); } diff --git a/libsol/spl_associated_token_account_instruction.h b/libsol/spl_associated_token_account_instruction.h index fbb2e5df..d0ce39ed 100644 --- a/libsol/spl_associated_token_account_instruction.h +++ b/libsol/spl_associated_token_account_instruction.h @@ -21,18 +21,12 @@ typedef struct SplAssociatedTokenAccountInfo { }; } SplAssociatedTokenAccountInfo; -int parse_spl_associated_token_account_instructions( - const Instruction* instruction, - const MessageHeader* header, - SplAssociatedTokenAccountInfo* info -); - -int print_spl_associated_token_account_info( - const SplAssociatedTokenAccountInfo* info, - const PrintConfig* print_config -); - -int print_spl_associated_token_account_create_info( - const SplAssociatedTokenAccountCreateInfo* info, - const PrintConfig* print_config -); +int parse_spl_associated_token_account_instructions(const Instruction* instruction, + const MessageHeader* header, + SplAssociatedTokenAccountInfo* info); + +int print_spl_associated_token_account_info(const SplAssociatedTokenAccountInfo* info, + const PrintConfig* print_config); + +int print_spl_associated_token_account_create_info(const SplAssociatedTokenAccountCreateInfo* info, + const PrintConfig* print_config); diff --git a/libsol/spl_memo_instruction.c b/libsol/spl_memo_instruction.c index b27bea68..6812628d 100644 --- a/libsol/spl_memo_instruction.c +++ b/libsol/spl_memo_instruction.c @@ -2,8 +2,4 @@ #include "sol/parser.h" #include "spl_memo_instruction.h" -const Pubkey spl_memo_program_id = {{ - PROGRAM_ID_SPL_MEMO -}}; - - +const Pubkey spl_memo_program_id = {{PROGRAM_ID_SPL_MEMO}}; diff --git a/libsol/spl_token_instruction.c b/libsol/spl_token_instruction.c index 87b0b0bc..91d8c4d8 100644 --- a/libsol/spl_token_instruction.c +++ b/libsol/spl_token_instruction.c @@ -6,14 +6,9 @@ #include "token_info.h" #include "util.h" -const Pubkey spl_token_program_id = {{ - PROGRAM_ID_SPL_TOKEN -}}; - -static int parse_spl_token_instruction_kind( - Parser* parser, - SplTokenInstructionKind* kind -) { +const Pubkey spl_token_program_id = {{PROGRAM_ID_SPL_TOKEN}}; + +static int parse_spl_token_instruction_kind(Parser* parser, SplTokenInstructionKind* kind) { uint8_t maybe_kind; BAIL_IF(parse_u8(parser, &maybe_kind)); switch (maybe_kind) { @@ -43,12 +38,10 @@ static int parse_spl_token_instruction_kind( return 1; } -static int parse_initialize_mint_spl_token_instruction( - Parser* parser, - const Instruction* instruction, - const MessageHeader* header, - SplTokenInitializeMintInfo* info -) { +static int parse_initialize_mint_spl_token_instruction(Parser* parser, + const Instruction* instruction, + const MessageHeader* header, + SplTokenInitializeMintInfo* info) { InstructionAccountsIterator it; instruction_accounts_iterator_init(&it, header, instruction); @@ -69,18 +62,16 @@ static int parse_initialize_mint_spl_token_instruction( return 0; } -static int parse_initialize_account_spl_token_instruction( - Parser* parser, - const Instruction* instruction, - const MessageHeader* header, - SplTokenInitializeAccountInfo* info, - bool expect_owner_in_accounts -) { +static int parse_initialize_account_spl_token_instruction(Parser* parser, + const Instruction* instruction, + const MessageHeader* header, + SplTokenInitializeAccountInfo* info, + bool expect_owner_in_accounts) { InstructionAccountsIterator it; instruction_accounts_iterator_init(&it, header, instruction); if (expect_owner_in_accounts) { - BAIL_IF(instruction->accounts_length != 4); + BAIL_IF(instruction->accounts_length != 4); } BAIL_IF(instruction_accounts_iterator_next(&it, &info->token_account)); @@ -98,10 +89,8 @@ static int parse_initialize_account_spl_token_instruction( return 0; } -static int parse_spl_token_multisigners( - InstructionAccountsIterator* it, - SplTokenMultisigners* signers -) { +static int parse_spl_token_multisigners(InstructionAccountsIterator* it, + SplTokenMultisigners* signers) { size_t n = instruction_accounts_iterator_remaining(it); BAIL_IF(n > Token_MAX_SIGNERS); BAIL_IF(instruction_accounts_iterator_next(it, &signers->first)); @@ -110,12 +99,10 @@ static int parse_spl_token_multisigners( return 0; } -static int parse_initialize_multisig_spl_token_instruction( - Parser* parser, - const Instruction* instruction, - const MessageHeader* header, - SplTokenInitializeMultisigInfo* info -) { +static int parse_initialize_multisig_spl_token_instruction(Parser* parser, + const Instruction* instruction, + const MessageHeader* header, + SplTokenInitializeMultisigInfo* info) { InstructionAccountsIterator it; instruction_accounts_iterator_init(&it, header, instruction); @@ -130,10 +117,7 @@ static int parse_initialize_multisig_spl_token_instruction( return 0; } -static int parse_spl_token_sign( - InstructionAccountsIterator* it, - SplTokenSign* sign -) { +static int parse_spl_token_sign(InstructionAccountsIterator* it, SplTokenSign* sign) { size_t n = instruction_accounts_iterator_remaining(it); BAIL_IF(n == 0); @@ -148,12 +132,10 @@ static int parse_spl_token_sign( return 0; } -static int parse_transfer_spl_token_instruction( - Parser* parser, - const Instruction* instruction, - const MessageHeader* header, - SplTokenTransferInfo* info -) { +static int parse_transfer_spl_token_instruction(Parser* parser, + const Instruction* instruction, + const MessageHeader* header, + SplTokenTransferInfo* info) { InstructionAccountsIterator it; instruction_accounts_iterator_init(&it, header, instruction); @@ -169,12 +151,10 @@ static int parse_transfer_spl_token_instruction( return 0; } -static int parse_approve_spl_token_instruction( - Parser* parser, - const Instruction* instruction, - const MessageHeader* header, - SplTokenApproveInfo* info -) { +static int parse_approve_spl_token_instruction(Parser* parser, + const Instruction* instruction, + const MessageHeader* header, + SplTokenApproveInfo* info) { InstructionAccountsIterator it; instruction_accounts_iterator_init(&it, header, instruction); @@ -190,11 +170,9 @@ static int parse_approve_spl_token_instruction( return 0; } -static int parse_revoke_spl_token_instruction( - const Instruction* instruction, - const MessageHeader* header, - SplTokenRevokeInfo* info -) { +static int parse_revoke_spl_token_instruction(const Instruction* instruction, + const MessageHeader* header, + SplTokenRevokeInfo* info) { InstructionAccountsIterator it; instruction_accounts_iterator_init(&it, header, instruction); @@ -205,10 +183,7 @@ static int parse_revoke_spl_token_instruction( return 0; } -static int parse_token_authority_type( - Parser* parser, - Token_AuthorityType* auth_type -) { +static int parse_token_authority_type(Parser* parser, Token_AuthorityType* auth_type) { uint8_t maybe_type; BAIL_IF(parse_u8(parser, &maybe_type)); switch (maybe_type) { @@ -216,7 +191,7 @@ static int parse_token_authority_type( case Token_AuthorityType_FreezeAccount: case Token_AuthorityType_AccountOwner: case Token_AuthorityType_CloseAccount: - *auth_type = (Token_AuthorityType)maybe_type; + *auth_type = (Token_AuthorityType) maybe_type; return 0; } return 1; @@ -236,12 +211,10 @@ static const char* stringify_token_authority_type(Token_AuthorityType auth_type) return NULL; } -static int parse_set_authority_spl_token_instruction( - Parser* parser, - const Instruction* instruction, - const MessageHeader* header, - SplTokenSetAuthorityInfo* info -) { +static int parse_set_authority_spl_token_instruction(Parser* parser, + const Instruction* instruction, + const MessageHeader* header, + SplTokenSetAuthorityInfo* info) { InstructionAccountsIterator it; instruction_accounts_iterator_init(&it, header, instruction); @@ -262,12 +235,10 @@ static int parse_set_authority_spl_token_instruction( return 0; } -static int parse_mint_to_spl_token_instruction( - Parser* parser, - const Instruction* instruction, - const MessageHeader* header, - SplTokenMintToInfo* info -) { +static int parse_mint_to_spl_token_instruction(Parser* parser, + const Instruction* instruction, + const MessageHeader* header, + SplTokenMintToInfo* info) { InstructionAccountsIterator it; instruction_accounts_iterator_init(&it, header, instruction); @@ -282,12 +253,10 @@ static int parse_mint_to_spl_token_instruction( return 0; } -static int parse_burn_spl_token_instruction( - Parser* parser, - const Instruction* instruction, - const MessageHeader* header, - SplTokenBurnInfo* info -) { +static int parse_burn_spl_token_instruction(Parser* parser, + const Instruction* instruction, + const MessageHeader* header, + SplTokenBurnInfo* info) { InstructionAccountsIterator it; instruction_accounts_iterator_init(&it, header, instruction); @@ -302,11 +271,9 @@ static int parse_burn_spl_token_instruction( return 0; } -static int parse_close_account_spl_token_instruction( - const Instruction* instruction, - const MessageHeader* header, - SplTokenCloseAccountInfo* info -) { +static int parse_close_account_spl_token_instruction(const Instruction* instruction, + const MessageHeader* header, + SplTokenCloseAccountInfo* info) { InstructionAccountsIterator it; instruction_accounts_iterator_init(&it, header, instruction); @@ -318,11 +285,9 @@ static int parse_close_account_spl_token_instruction( return 0; } -static int parse_freeze_account_spl_token_instruction( - const Instruction* instruction, - const MessageHeader* header, - SplTokenFreezeAccountInfo* info -) { +static int parse_freeze_account_spl_token_instruction(const Instruction* instruction, + const MessageHeader* header, + SplTokenFreezeAccountInfo* info) { InstructionAccountsIterator it; instruction_accounts_iterator_init(&it, header, instruction); @@ -334,11 +299,9 @@ static int parse_freeze_account_spl_token_instruction( return 0; } -static int parse_thaw_account_spl_token_instruction( - const Instruction* instruction, - const MessageHeader* header, - SplTokenThawAccountInfo* info -) { +static int parse_thaw_account_spl_token_instruction(const Instruction* instruction, + const MessageHeader* header, + SplTokenThawAccountInfo* info) { InstructionAccountsIterator it; instruction_accounts_iterator_init(&it, header, instruction); @@ -350,11 +313,9 @@ static int parse_thaw_account_spl_token_instruction( return 0; } -static int parse_sync_native_spl_token_instruction( - const Instruction* instruction, - const MessageHeader* header, - SplTokenSyncNativeInfo* info -) { +static int parse_sync_native_spl_token_instruction(const Instruction* instruction, + const MessageHeader* header, + SplTokenSyncNativeInfo* info) { InstructionAccountsIterator it; instruction_accounts_iterator_init(&it, header, instruction); @@ -363,111 +324,74 @@ static int parse_sync_native_spl_token_instruction( return 0; } -int parse_spl_token_instructions( - const Instruction* instruction, - const MessageHeader* header, - SplTokenInfo* info -) { +int parse_spl_token_instructions(const Instruction* instruction, + const MessageHeader* header, + SplTokenInfo* info) { Parser parser = {instruction->data, instruction->data_length}; BAIL_IF(parse_spl_token_instruction_kind(&parser, &info->kind)); switch (info->kind) { case SplTokenKind(InitializeMint): - return parse_initialize_mint_spl_token_instruction( - &parser, - instruction, - header, - &info->initialize_mint - ); + return parse_initialize_mint_spl_token_instruction(&parser, + instruction, + header, + &info->initialize_mint); case SplTokenKind(InitializeAccount): - return parse_initialize_account_spl_token_instruction( - &parser, - instruction, - header, - &info->initialize_account, - true - ); + return parse_initialize_account_spl_token_instruction(&parser, + instruction, + header, + &info->initialize_account, + true); case SplTokenKind(InitializeAccount2): - return parse_initialize_account_spl_token_instruction( - &parser, - instruction, - header, - &info->initialize_account, - false - ); + return parse_initialize_account_spl_token_instruction(&parser, + instruction, + header, + &info->initialize_account, + false); case SplTokenKind(InitializeMultisig): - return parse_initialize_multisig_spl_token_instruction( - &parser, - instruction, - header, - &info->initialize_multisig - ); + return parse_initialize_multisig_spl_token_instruction(&parser, + instruction, + header, + &info->initialize_multisig); case SplTokenKind(Revoke): - return parse_revoke_spl_token_instruction( - instruction, - header, - &info->revoke - ); + return parse_revoke_spl_token_instruction(instruction, header, &info->revoke); case SplTokenKind(SetAuthority): - return parse_set_authority_spl_token_instruction( - &parser, - instruction, - header, - &info->set_owner - ); + return parse_set_authority_spl_token_instruction(&parser, + instruction, + header, + &info->set_owner); case SplTokenKind(CloseAccount): - return parse_close_account_spl_token_instruction( - instruction, - header, - &info->close_account - ); + return parse_close_account_spl_token_instruction(instruction, + header, + &info->close_account); case SplTokenKind(FreezeAccount): - return parse_freeze_account_spl_token_instruction( - instruction, - header, - &info->freeze_account - ); + return parse_freeze_account_spl_token_instruction(instruction, + header, + &info->freeze_account); case SplTokenKind(ThawAccount): - return parse_thaw_account_spl_token_instruction( - instruction, - header, - &info->thaw_account - ); + return parse_thaw_account_spl_token_instruction(instruction, + header, + &info->thaw_account); case SplTokenKind(TransferChecked): - return parse_transfer_spl_token_instruction( - &parser, - instruction, - header, - &info->transfer - ); + return parse_transfer_spl_token_instruction(&parser, + instruction, + header, + &info->transfer); case SplTokenKind(ApproveChecked): - return parse_approve_spl_token_instruction( - &parser, - instruction, - header, - &info->approve - ); + return parse_approve_spl_token_instruction(&parser, + instruction, + header, + &info->approve); case SplTokenKind(MintToChecked): - return parse_mint_to_spl_token_instruction( - &parser, - instruction, - header, - &info->mint_to - ); + return parse_mint_to_spl_token_instruction(&parser, + instruction, + header, + &info->mint_to); case SplTokenKind(BurnChecked): - return parse_burn_spl_token_instruction( - &parser, - instruction, - header, - &info->burn - ); + return parse_burn_spl_token_instruction(&parser, instruction, header, &info->burn); case SplTokenKind(SyncNative): - return parse_sync_native_spl_token_instruction( - instruction, - header, - &info->sync_native - ); + return parse_sync_native_spl_token_instruction(instruction, header, &info->sync_native); // Deprecated instructions case SplTokenKind(Transfer): case SplTokenKind(Approve): @@ -478,10 +402,7 @@ int parse_spl_token_instructions( return 1; } -static int print_spl_token_sign( - const SplTokenSign* sign, - const PrintConfig* print_config -) { +static int print_spl_token_sign(const SplTokenSign* sign, const PrintConfig* print_config) { SummaryItem* item; item = transaction_summary_general_item(); @@ -498,11 +419,9 @@ static int print_spl_token_sign( return 0; } -static int print_spl_token_initialize_mint_info( - const char* primary_title, - const SplTokenInitializeMintInfo* info, - const PrintConfig* print_config -) { +static int print_spl_token_initialize_mint_info(const char* primary_title, + const SplTokenInitializeMintInfo* info, + const PrintConfig* print_config) { UNUSED(print_config); SummaryItem* item; @@ -526,11 +445,9 @@ static int print_spl_token_initialize_mint_info( return 0; } -static int print_spl_token_initialize_account_info( - const char* primary_title, - const SplTokenInitializeAccountInfo* info, - const PrintConfig* print_config -) { +static int print_spl_token_initialize_account_info(const char* primary_title, + const SplTokenInitializeAccountInfo* info, + const PrintConfig* print_config) { UNUSED(print_config); SummaryItem* item; @@ -549,11 +466,9 @@ static int print_spl_token_initialize_account_info( return 0; } -static int print_spl_token_initialize_multisig_info( - const char* primary_title, - const SplTokenInitializeMultisigInfo* info, - const PrintConfig* print_config -) { +static int print_spl_token_initialize_multisig_info(const char* primary_title, + const SplTokenInitializeMultisigInfo* info, + const PrintConfig* print_config) { UNUSED(print_config); SummaryItem* item; @@ -569,11 +484,9 @@ static int print_spl_token_initialize_multisig_info( return 0; } -int print_spl_token_transfer_info( - const SplTokenTransferInfo* info, - const PrintConfig* print_config, - bool primary -) { +int print_spl_token_transfer_info(const SplTokenTransferInfo* info, + const PrintConfig* print_config, + bool primary) { SummaryItem* item; if (primary) { @@ -583,13 +496,11 @@ int print_spl_token_transfer_info( } const char* symbol = get_token_symbol(info->mint_account); - summary_item_set_token_amount( - item, - "Transfer tokens", - info->body.amount, - symbol, - info->body.decimals - ); + summary_item_set_token_amount(item, + "Transfer tokens", + info->body.amount, + symbol, + info->body.decimals); item = transaction_summary_general_item(); summary_item_set_pubkey(item, "From", info->src_account); @@ -602,10 +513,8 @@ int print_spl_token_transfer_info( return 0; } -static int print_spl_token_approve_info( - const SplTokenApproveInfo* info, - const PrintConfig* print_config -) { +static int print_spl_token_approve_info(const SplTokenApproveInfo* info, + const PrintConfig* print_config) { SummaryItem* item; item = transaction_summary_primary_item(); @@ -613,13 +522,11 @@ static int print_spl_token_approve_info( item = transaction_summary_general_item(); const char* symbol = get_token_symbol(info->mint_account); - summary_item_set_token_amount( - item, - "Allowance", - info->body.amount, - symbol, - info->body.decimals - ); + summary_item_set_token_amount(item, + "Allowance", + info->body.amount, + symbol, + info->body.decimals); item = transaction_summary_general_item(); summary_item_set_pubkey(item, "From", info->token_account); @@ -629,10 +536,8 @@ static int print_spl_token_approve_info( return 0; } -static int print_spl_token_revoke_info( - const SplTokenRevokeInfo* info, - const PrintConfig* print_config -) { +static int print_spl_token_revoke_info(const SplTokenRevokeInfo* info, + const PrintConfig* print_config) { UNUSED(print_config); SummaryItem* item; @@ -645,10 +550,8 @@ static int print_spl_token_revoke_info( return 0; } -static int print_spl_token_set_authority_info( - const SplTokenSetAuthorityInfo* info, - const PrintConfig* print_config -) { +static int print_spl_token_set_authority_info(const SplTokenSetAuthorityInfo* info, + const PrintConfig* print_config) { UNUSED(print_config); SummaryItem* item; @@ -676,21 +579,17 @@ static int print_spl_token_set_authority_info( return 0; } -static int print_spl_token_mint_to_info( - const SplTokenMintToInfo* info, - const PrintConfig* print_config -) { +static int print_spl_token_mint_to_info(const SplTokenMintToInfo* info, + const PrintConfig* print_config) { SummaryItem* item; item = transaction_summary_primary_item(); const char* symbol = get_token_symbol(info->mint_account); - summary_item_set_token_amount( - item, - "Mint tokens", - info->body.amount, - symbol, - info->body.decimals - ); + summary_item_set_token_amount(item, + "Mint tokens", + info->body.amount, + symbol, + info->body.decimals); if (print_config->expert_mode) { item = transaction_summary_general_item(); @@ -705,23 +604,19 @@ static int print_spl_token_mint_to_info( return 0; } -static int print_spl_token_burn_info( - const SplTokenBurnInfo* info, - const PrintConfig* print_config -) { +static int print_spl_token_burn_info(const SplTokenBurnInfo* info, + const PrintConfig* print_config) { UNUSED(print_config); SummaryItem* item; item = transaction_summary_primary_item(); const char* symbol = get_token_symbol(info->mint_account); - summary_item_set_token_amount( - item, - "Burn tokens", - info->body.amount, - symbol, - info->body.decimals - ); + summary_item_set_token_amount(item, + "Burn tokens", + info->body.amount, + symbol, + info->body.decimals); item = transaction_summary_general_item(); summary_item_set_pubkey(item, "From", info->token_account); @@ -731,10 +626,8 @@ static int print_spl_token_burn_info( return 0; } -static int print_spl_token_close_account_info( - const SplTokenCloseAccountInfo* info, - const PrintConfig* print_config -) { +static int print_spl_token_close_account_info(const SplTokenCloseAccountInfo* info, + const PrintConfig* print_config) { UNUSED(print_config); SummaryItem* item; @@ -750,10 +643,8 @@ static int print_spl_token_close_account_info( return 0; } -static int print_spl_token_freeze_account_info( - const SplTokenFreezeAccountInfo* info, - const PrintConfig* print_config -) { +static int print_spl_token_freeze_account_info(const SplTokenFreezeAccountInfo* info, + const PrintConfig* print_config) { SummaryItem* item; item = transaction_summary_primary_item(); @@ -769,10 +660,8 @@ static int print_spl_token_freeze_account_info( return 0; } -static int print_spl_token_thaw_account_info( - const SplTokenThawAccountInfo* info, - const PrintConfig* print_config -) { +static int print_spl_token_thaw_account_info(const SplTokenThawAccountInfo* info, + const PrintConfig* print_config) { SummaryItem* item; item = transaction_summary_primary_item(); @@ -788,10 +677,8 @@ static int print_spl_token_thaw_account_info( return 0; } -static int print_spl_token_sync_native_info( - const SplTokenSyncNativeInfo* info, - const PrintConfig* print_config -) { +static int print_spl_token_sync_native_info(const SplTokenSyncNativeInfo* info, + const PrintConfig* print_config) { UNUSED(print_config); SummaryItem* item; @@ -802,30 +689,21 @@ static int print_spl_token_sync_native_info( return 0; } -int print_spl_token_info( - const SplTokenInfo* info, - const PrintConfig* print_config -) { +int print_spl_token_info(const SplTokenInfo* info, const PrintConfig* print_config) { switch (info->kind) { case SplTokenKind(InitializeMint): - return print_spl_token_initialize_mint_info( - "Init mint", - &info->initialize_mint, - print_config - ); + return print_spl_token_initialize_mint_info("Init mint", + &info->initialize_mint, + print_config); case SplTokenKind(InitializeAccount): case SplTokenKind(InitializeAccount2): - return print_spl_token_initialize_account_info( - "Init acct", - &info->initialize_account, - print_config - ); + return print_spl_token_initialize_account_info("Init acct", + &info->initialize_account, + print_config); case SplTokenKind(InitializeMultisig): - return print_spl_token_initialize_multisig_info( - "Init multisig", - &info->initialize_multisig, - print_config - ); + return print_spl_token_initialize_multisig_info("Init multisig", + &info->initialize_multisig, + print_config); case SplTokenKind(Revoke): return print_spl_token_revoke_info(&info->revoke, print_config); case SplTokenKind(SetAuthority): @@ -857,7 +735,7 @@ int print_spl_token_info( return 1; } -#define M_OF_N_MAX_LEN 9 // "11 of 11" + NUL +#define M_OF_N_MAX_LEN 9 // "11 of 11" + NUL static int print_m_of_n_string(uint8_t m, uint8_t n, char* buf, size_t buflen) { BAIL_IF(n > Token_MAX_SIGNERS); BAIL_IF(m > n); @@ -883,14 +761,12 @@ void summary_item_set_multisig_m_of_n(SummaryItem* item, uint8_t m, uint8_t n) { } } -const Pubkey* spl_token_option_pubkey_get( - const SplTokenOptionPubkey* option_pubkey -) { +const Pubkey* spl_token_option_pubkey_get(const SplTokenOptionPubkey* option_pubkey) { switch (option_pubkey->tag) { case SplTokenToOptionPubkeyKind(None): break; case SplTokenToOptionPubkeyKind(Some): - return (const Pubkey*)&option_pubkey->some; + return (const Pubkey*) &option_pubkey->some; } return NULL; } diff --git a/libsol/spl_token_instruction.h b/libsol/spl_token_instruction.h index e37a826d..0c13f0f7 100644 --- a/libsol/spl_token_instruction.h +++ b/libsol/spl_token_instruction.h @@ -4,8 +4,8 @@ #include "sol/transaction_summary.h" #include "spl/token.h" -#define SplTokenBody(b) Token_TokenInstruction_Token_ ## b ## _Body -#define SplTokenKind(b) Token_TokenInstruction_ ## b +#define SplTokenBody(b) Token_TokenInstruction_Token_##b##_Body +#define SplTokenKind(b) Token_TokenInstruction_##b #define SplTokenInstructionKind Token_TokenInstruction_Tag @@ -136,31 +136,18 @@ typedef struct SplTokenInfo { }; } SplTokenInfo; -int parse_spl_token_instructions( - const Instruction* instruction, - const MessageHeader* header, - SplTokenInfo* info -); -int print_spl_token_info( - const SplTokenInfo* info, - const PrintConfig* print_config -); -void summary_item_set_multisig_m_of_n( - SummaryItem* item, - uint8_t m, - uint8_t n -); - -#define SplTokenOptionPubkeyKind Token_COption_Pubkey_Tag -#define SplTokenToOptionPubkeyKind(k) Token_COption_Pubkey_ ## k ## _Pubkey -#define SplTokenOptionPubkeyBody Token_COption_Pubkey_Token_Some_Body_Pubkey -#define SplTokenOptionPubkey Token_COption_Pubkey -const Pubkey* spl_token_option_pubkey_get( - const SplTokenOptionPubkey* option_pubkey -); - -int print_spl_token_transfer_info( - const SplTokenTransferInfo* info, - const PrintConfig* print_config, - bool primary -); +int parse_spl_token_instructions(const Instruction* instruction, + const MessageHeader* header, + SplTokenInfo* info); +int print_spl_token_info(const SplTokenInfo* info, const PrintConfig* print_config); +void summary_item_set_multisig_m_of_n(SummaryItem* item, uint8_t m, uint8_t n); + +#define SplTokenOptionPubkeyKind Token_COption_Pubkey_Tag +#define SplTokenToOptionPubkeyKind(k) Token_COption_Pubkey_##k##_Pubkey +#define SplTokenOptionPubkeyBody Token_COption_Pubkey_Token_Some_Body_Pubkey +#define SplTokenOptionPubkey Token_COption_Pubkey +const Pubkey* spl_token_option_pubkey_get(const SplTokenOptionPubkey* option_pubkey); + +int print_spl_token_transfer_info(const SplTokenTransferInfo* info, + const PrintConfig* print_config, + bool primary); diff --git a/libsol/spl_token_instruction_test.c b/libsol/spl_token_instruction_test.c index 6b445b85..616a76d1 100644 --- a/libsol/spl_token_instruction_test.c +++ b/libsol/spl_token_instruction_test.c @@ -10,55 +10,74 @@ void print_pubkey(const Pubkey* pubkey) { printf("%s\n", buf); } -#define BLOCKHASH BYTES32_BS58_1 -#define MINT_ACCOUNT BYTES32_BS58_2 -#define TOKEN_ACCOUNT BYTES32_BS58_3 -#define OWNER_ACCOUNT BYTES32_BS58_4 -#define MULTISIG_ACCOUNT OWNER_ACCOUNT -#define SIGNER1 BYTES32_BS58_5 -#define SIGNER2 BYTES32_BS58_6 -#define SIGNER3 BYTES32_BS58_7 -#define DEST_ACCOUNT BYTES32_BS58_8 -#define DELEGATE DEST_ACCOUNT -#define NEW_OWNER DEST_ACCOUNT +#define BLOCKHASH BYTES32_BS58_1 +#define MINT_ACCOUNT BYTES32_BS58_2 +#define TOKEN_ACCOUNT BYTES32_BS58_3 +#define OWNER_ACCOUNT BYTES32_BS58_4 +#define MULTISIG_ACCOUNT OWNER_ACCOUNT +#define SIGNER1 BYTES32_BS58_5 +#define SIGNER2 BYTES32_BS58_6 +#define SIGNER3 BYTES32_BS58_7 +#define DEST_ACCOUNT BYTES32_BS58_8 +#define DELEGATE DEST_ACCOUNT +#define NEW_OWNER DEST_ACCOUNT void test_parse_spl_token_create_token() { - uint8_t message[] = { - 2, 0, 3, - 5, - OWNER_ACCOUNT, - MINT_ACCOUNT, - SYSVAR_RENT, - PROGRAM_ID_SYSTEM, - PROGRAM_ID_SPL_TOKEN, - BLOCKHASH, - 2, - 3, - 2, - 0, 1, - 52, - 0, 0, 0, 0, - 245, 1, 0, 0, 0, 0, 0, 0, - 88, 0, 0, 0, 0, 0, 0, 0, - PROGRAM_ID_SPL_TOKEN, - 4, - 2, - 1, 2, - 35, - 0, - 9, - OWNER_ACCOUNT, - 0 - }; + uint8_t message[] = {2, + 0, + 3, + 5, + OWNER_ACCOUNT, + MINT_ACCOUNT, + SYSVAR_RENT, + PROGRAM_ID_SYSTEM, + PROGRAM_ID_SPL_TOKEN, + BLOCKHASH, + 2, + 3, + 2, + 0, + 1, + 52, + 0, + 0, + 0, + 0, + 245, + 1, + 0, + 0, + 0, + 0, + 0, + 0, + 88, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + PROGRAM_ID_SPL_TOKEN, + 4, + 2, + 1, + 2, + 35, + 0, + 9, + OWNER_ACCOUNT, + 0}; Parser parser = {message, sizeof(message)}; MessageHeader header; assert(parse_message_header(&parser, &header) == 0); Instruction instruction; - assert(parse_instruction(&parser, &instruction) == 0); // SystemCreateAccount (ignored) + assert(parse_instruction(&parser, &instruction) == 0); // SystemCreateAccount (ignored) assert(instruction_validate(&instruction, &header) == 0); - assert(parse_instruction(&parser, &instruction) == 0); // SplTokenInitializeMint + assert(parse_instruction(&parser, &instruction) == 0); // SplTokenInitializeMint assert(instruction_validate(&instruction, &header) == 0); SplTokenInfo info; @@ -69,10 +88,10 @@ void test_parse_spl_token_create_token() { const SplTokenInitializeMintInfo* init_mint = &info.initialize_mint; - const Pubkey mint_account = {{ MINT_ACCOUNT }}; + const Pubkey mint_account = {{MINT_ACCOUNT}}; assert_pubkey_equal(init_mint->mint_account, &mint_account); - const Pubkey owner = {{ OWNER_ACCOUNT }}; + const Pubkey owner = {{OWNER_ACCOUNT}}; assert_pubkey_equal(init_mint->mint_authority, &owner); assert(init_mint->decimals == 9); @@ -82,31 +101,54 @@ void test_parse_spl_token_create_token() { void test_parse_spl_token_create_account() { uint8_t message[] = { - 0x02, 0x00, 0x03, + 0x02, + 0x00, + 0x03, 0x06, - OWNER_ACCOUNT, - TOKEN_ACCOUNT, - MINT_ACCOUNT, - SYSVAR_RENT, - PROGRAM_ID_SYSTEM, - PROGRAM_ID_SPL_TOKEN, + OWNER_ACCOUNT, + TOKEN_ACCOUNT, + MINT_ACCOUNT, + SYSVAR_RENT, + PROGRAM_ID_SYSTEM, + PROGRAM_ID_SPL_TOKEN, BLOCKHASH, 0x02, - // SystemCreateAccount - 0x04, - 0x02, - 0x00, 0x01, - 0x34, - 0x00, 0x00, 0x00, 0x00, - 0x80, 0x56, 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - PROGRAM_ID_SPL_TOKEN, - // SplTokenInitializeAccount - 0x05, - 0x04, - 0x01, 0x02, 0x00, 0x03, - 0x01, - 0x01, + // SystemCreateAccount + 0x04, + 0x02, + 0x00, + 0x01, + 0x34, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x56, + 0x1a, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x78, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + PROGRAM_ID_SPL_TOKEN, + // SplTokenInitializeAccount + 0x05, + 0x04, + 0x01, + 0x02, + 0x00, + 0x03, + 0x01, + 0x01, }; Parser parser = {message, sizeof(message)}; @@ -114,9 +156,9 @@ void test_parse_spl_token_create_account() { assert(parse_message_header(&parser, &header) == 0); Instruction instruction; - assert(parse_instruction(&parser, &instruction) == 0); // SystemCreateAccount (ignored) + assert(parse_instruction(&parser, &instruction) == 0); // SystemCreateAccount (ignored) assert(instruction_validate(&instruction, &header) == 0); - assert(parse_instruction(&parser, &instruction) == 0); // SplTokenInitializeAccount + assert(parse_instruction(&parser, &instruction) == 0); // SplTokenInitializeAccount assert(instruction_validate(&instruction, &header) == 0); SplTokenInfo info; @@ -126,54 +168,74 @@ void test_parse_spl_token_create_account() { assert(info.kind == SplTokenKind(InitializeAccount)); const SplTokenInitializeAccountInfo* init_acc = &info.initialize_account; - const Pubkey token_account = {{ TOKEN_ACCOUNT }}; + const Pubkey token_account = {{TOKEN_ACCOUNT}}; assert_pubkey_equal(init_acc->token_account, &token_account); - const Pubkey mint_account = {{ MINT_ACCOUNT }}; + const Pubkey mint_account = {{MINT_ACCOUNT}}; assert_pubkey_equal(init_acc->mint_account, &mint_account); - const Pubkey owner = {{ OWNER_ACCOUNT }}; + const Pubkey owner = {{OWNER_ACCOUNT}}; assert_pubkey_equal(init_acc->owner, &owner); } void test_parse_spl_token_create_account2() { - uint8_t message[] = { - 0x02, 0x00, 0x04, - 0x06, - OWNER_ACCOUNT, - TOKEN_ACCOUNT, - MINT_ACCOUNT, - SYSVAR_RENT, - PROGRAM_ID_SYSTEM, - PROGRAM_ID_SPL_TOKEN, - BLOCKHASH, - 0x02, - // SystemCreateAccount - 0x04, - 0x02, - 0x00, 0x01, - 0x34, - 0x00, 0x00, 0x00, 0x00, - 0x80, 0x56, 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - PROGRAM_ID_SPL_TOKEN, - // SplTokenInitializeAccount2 - 0x05, - 0x03, - 0x01, 0x02, 0x03, - 0x21, - 0x10, - OWNER_ACCOUNT - }; + uint8_t message[] = {0x02, + 0x00, + 0x04, + 0x06, + OWNER_ACCOUNT, + TOKEN_ACCOUNT, + MINT_ACCOUNT, + SYSVAR_RENT, + PROGRAM_ID_SYSTEM, + PROGRAM_ID_SPL_TOKEN, + BLOCKHASH, + 0x02, + // SystemCreateAccount + 0x04, + 0x02, + 0x00, + 0x01, + 0x34, + 0x00, + 0x00, + 0x00, + 0x00, + 0x80, + 0x56, + 0x1a, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x78, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + PROGRAM_ID_SPL_TOKEN, + // SplTokenInitializeAccount2 + 0x05, + 0x03, + 0x01, + 0x02, + 0x03, + 0x21, + 0x10, + OWNER_ACCOUNT}; Parser parser = {message, sizeof(message)}; MessageHeader header; assert(parse_message_header(&parser, &header) == 0); Instruction instruction; - assert(parse_instruction(&parser, &instruction) == 0); // SystemCreateAccount (ignored) + assert(parse_instruction(&parser, &instruction) == 0); // SystemCreateAccount (ignored) assert(instruction_validate(&instruction, &header) == 0); - assert(parse_instruction(&parser, &instruction) == 0); // SplTokenInitializeAccount2 + assert(parse_instruction(&parser, &instruction) == 0); // SplTokenInitializeAccount2 assert(instruction_validate(&instruction, &header) == 0); SplTokenInfo info; @@ -183,55 +245,77 @@ void test_parse_spl_token_create_account2() { assert(info.kind == SplTokenKind(InitializeAccount2)); const SplTokenInitializeAccountInfo* init_acc = &info.initialize_account; - const Pubkey token_account = {{ TOKEN_ACCOUNT }}; + const Pubkey token_account = {{TOKEN_ACCOUNT}}; assert_pubkey_equal(init_acc->token_account, &token_account); - const Pubkey mint_account = {{ MINT_ACCOUNT }}; + const Pubkey mint_account = {{MINT_ACCOUNT}}; assert_pubkey_equal(init_acc->mint_account, &mint_account); - const Pubkey owner = {{ OWNER_ACCOUNT }}; + const Pubkey owner = {{OWNER_ACCOUNT}}; assert_pubkey_equal(init_acc->owner, &owner); } void test_parse_spl_token_create_multisig() { - uint8_t message[] = { - 2, 0, 5, - 8, - OWNER_ACCOUNT, - MULTISIG_ACCOUNT, - SYSVAR_RENT, - SIGNER1, - SIGNER2, - SIGNER3, - PROGRAM_ID_SYSTEM, - PROGRAM_ID_SPL_TOKEN, - BLOCKHASH, - 2, - // SystemCreateAccount - 6, - 2, - 0, 1, - 52, - 0, 0, 0, 0, - 245, 1, 0, 0, 0, 0, 0, 0, - 40, 0, 0, 0, 0, 0, 0, 0, - PROGRAM_ID_SPL_TOKEN, - // SplTokenInitializeMultisig - 7, - 5, - 1, 2, 3, 4, 5, - 2, - 2, - 2 - }; + uint8_t message[] = {2, + 0, + 5, + 8, + OWNER_ACCOUNT, + MULTISIG_ACCOUNT, + SYSVAR_RENT, + SIGNER1, + SIGNER2, + SIGNER3, + PROGRAM_ID_SYSTEM, + PROGRAM_ID_SPL_TOKEN, + BLOCKHASH, + 2, + // SystemCreateAccount + 6, + 2, + 0, + 1, + 52, + 0, + 0, + 0, + 0, + 245, + 1, + 0, + 0, + 0, + 0, + 0, + 0, + 40, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + PROGRAM_ID_SPL_TOKEN, + // SplTokenInitializeMultisig + 7, + 5, + 1, + 2, + 3, + 4, + 5, + 2, + 2, + 2}; Parser parser = {message, sizeof(message)}; MessageHeader header; assert(parse_message_header(&parser, &header) == 0); Instruction instruction; - assert(parse_instruction(&parser, &instruction) == 0); // SystemCreateAccount (ignored) + assert(parse_instruction(&parser, &instruction) == 0); // SystemCreateAccount (ignored) assert(instruction_validate(&instruction, &header) == 0); - assert(parse_instruction(&parser, &instruction) == 0); // SplTokenInitializeMultisig + assert(parse_instruction(&parser, &instruction) == 0); // SplTokenInitializeMultisig assert(instruction_validate(&instruction, &header) == 0); SplTokenInfo info; @@ -243,44 +327,54 @@ void test_parse_spl_token_create_multisig() { assert(init_ms->body.m == 2); - const Pubkey multisig_account = {{ MULTISIG_ACCOUNT }}; + const Pubkey multisig_account = {{MULTISIG_ACCOUNT}}; assert_pubkey_equal(init_ms->multisig_account, &multisig_account); assert(init_ms->signers.count == 3); const Pubkey* signer = init_ms->signers.first; - const Pubkey signer1 = {{ SIGNER1 }}; + const Pubkey signer1 = {{SIGNER1}}; assert_pubkey_equal(signer++, &signer1); - const Pubkey signer2 = {{ SIGNER2 }}; + const Pubkey signer2 = {{SIGNER2}}; assert_pubkey_equal(signer++, &signer2); - const Pubkey signer3 = {{ SIGNER3 }}; + const Pubkey signer3 = {{SIGNER3}}; assert_pubkey_equal(signer++, &signer3); } void test_parse_spl_token_transfer() { - uint8_t message[] = { - 1, 0, 2, - 5, - OWNER_ACCOUNT, - TOKEN_ACCOUNT, - DEST_ACCOUNT, - MINT_ACCOUNT, - PROGRAM_ID_SPL_TOKEN, - BLOCKHASH, - 1, - 4, - 4, - 1, 3, 2, 0, - 10, - 12, - 42, 0, 0, 0, 0, 0, 0, 0, - 9 - }; + uint8_t message[] = {1, + 0, + 2, + 5, + OWNER_ACCOUNT, + TOKEN_ACCOUNT, + DEST_ACCOUNT, + MINT_ACCOUNT, + PROGRAM_ID_SPL_TOKEN, + BLOCKHASH, + 1, + 4, + 4, + 1, + 3, + 2, + 0, + 10, + 12, + 42, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 9}; Parser parser = {message, sizeof(message)}; MessageHeader header; assert(parse_message_header(&parser, &header) == 0); Instruction instruction; - assert(parse_instruction(&parser, &instruction) == 0); // SplTokenTransfer2 + assert(parse_instruction(&parser, &instruction) == 0); // SplTokenTransfer2 assert(instruction_validate(&instruction, &header) == 0); SplTokenInfo info; @@ -293,43 +387,53 @@ void test_parse_spl_token_transfer() { assert(tr_info->body.amount == 42); assert(tr_info->body.decimals == 9); - const Pubkey src_account = {{ TOKEN_ACCOUNT }}; + const Pubkey src_account = {{TOKEN_ACCOUNT}}; assert_pubkey_equal(tr_info->src_account, &src_account); - const Pubkey dest_account = {{ DEST_ACCOUNT }}; + const Pubkey dest_account = {{DEST_ACCOUNT}}; assert_pubkey_equal(tr_info->dest_account, &dest_account); - const Pubkey owner = {{ OWNER_ACCOUNT }}; + const Pubkey owner = {{OWNER_ACCOUNT}}; assert_pubkey_equal(tr_info->sign.single.signer, &owner); - const Pubkey mint_account = {{ MINT_ACCOUNT }}; + const Pubkey mint_account = {{MINT_ACCOUNT}}; assert_pubkey_equal(tr_info->mint_account, &mint_account); } void test_parse_spl_token_approve() { - uint8_t message[] = { - 1, 0, 2, - 4, - OWNER_ACCOUNT, - TOKEN_ACCOUNT, - PROGRAM_ID_SPL_TOKEN, - DEST_ACCOUNT, - BLOCKHASH, - 1, - 2, - 4, - 1, 2, 3, 0, - 10, - 13, - 42, 0, 0, 0, 0, 0, 0, 0, - 9 - }; + uint8_t message[] = {1, + 0, + 2, + 4, + OWNER_ACCOUNT, + TOKEN_ACCOUNT, + PROGRAM_ID_SPL_TOKEN, + DEST_ACCOUNT, + BLOCKHASH, + 1, + 2, + 4, + 1, + 2, + 3, + 0, + 10, + 13, + 42, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 9}; Parser parser = {message, sizeof(message)}; MessageHeader header; assert(parse_message_header(&parser, &header) == 0); Instruction instruction; - assert(parse_instruction(&parser, &instruction) == 0); // SplTokenApprove2 + assert(parse_instruction(&parser, &instruction) == 0); // SplTokenApprove2 assert(instruction_validate(&instruction, &header) == 0); SplTokenInfo info; @@ -342,40 +446,41 @@ void test_parse_spl_token_approve() { assert(ap_info->body.amount == 42); assert(ap_info->body.decimals == 9); - const Pubkey token_account = {{ TOKEN_ACCOUNT }}; + const Pubkey token_account = {{TOKEN_ACCOUNT}}; assert_pubkey_equal(ap_info->token_account, &token_account); - const Pubkey delegate = {{ DELEGATE }}; + const Pubkey delegate = {{DELEGATE}}; assert_pubkey_equal(ap_info->delegate, &delegate); - const Pubkey owner = {{ OWNER_ACCOUNT }}; + const Pubkey owner = {{OWNER_ACCOUNT}}; assert_pubkey_equal(ap_info->sign.single.signer, &owner); - const Pubkey mint_account = {{ PROGRAM_ID_SPL_TOKEN }}; + const Pubkey mint_account = {{PROGRAM_ID_SPL_TOKEN}}; assert_pubkey_equal(ap_info->mint_account, &mint_account); } void test_parse_spl_token_revoke() { - uint8_t message[] = { - 1, 0, 2, - 3, - OWNER_ACCOUNT, - TOKEN_ACCOUNT, - PROGRAM_ID_SPL_TOKEN, - BLOCKHASH, - 1, - 2, - 2, - 1, 0, - 1, - 5 - }; + uint8_t message[] = {1, + 0, + 2, + 3, + OWNER_ACCOUNT, + TOKEN_ACCOUNT, + PROGRAM_ID_SPL_TOKEN, + BLOCKHASH, + 1, + 2, + 2, + 1, + 0, + 1, + 5}; Parser parser = {message, sizeof(message)}; MessageHeader header; assert(parse_message_header(&parser, &header) == 0); Instruction instruction; - assert(parse_instruction(&parser, &instruction) == 0); // SplTokenRevoke + assert(parse_instruction(&parser, &instruction) == 0); // SplTokenRevoke assert(instruction_validate(&instruction, &header) == 0); SplTokenInfo info; @@ -385,37 +490,38 @@ void test_parse_spl_token_revoke() { assert(info.kind == SplTokenKind(Revoke)); const SplTokenRevokeInfo* re_info = &info.revoke; - const Pubkey token_account = {{ TOKEN_ACCOUNT }}; + const Pubkey token_account = {{TOKEN_ACCOUNT}}; assert_pubkey_equal(re_info->token_account, &token_account); - const Pubkey owner = {{ OWNER_ACCOUNT }}; + const Pubkey owner = {{OWNER_ACCOUNT}}; assert_pubkey_equal(re_info->sign.single.signer, &owner); } void test_parse_spl_token_set_authority() { - uint8_t message[] = { - 1, 0, 1, - 3, - OWNER_ACCOUNT, - TOKEN_ACCOUNT, - PROGRAM_ID_SPL_TOKEN, - BLOCKHASH, - 1, - 2, - 2, - 1, 0, - 35, - 6, - 2, - 1, - NEW_OWNER - }; + uint8_t message[] = {1, + 0, + 1, + 3, + OWNER_ACCOUNT, + TOKEN_ACCOUNT, + PROGRAM_ID_SPL_TOKEN, + BLOCKHASH, + 1, + 2, + 2, + 1, + 0, + 35, + 6, + 2, + 1, + NEW_OWNER}; Parser parser = {message, sizeof(message)}; MessageHeader header; assert(parse_message_header(&parser, &header) == 0); Instruction instruction; - assert(parse_instruction(&parser, &instruction) == 0); // SplTokenSetAuthority + assert(parse_instruction(&parser, &instruction) == 0); // SplTokenSetAuthority assert(instruction_validate(&instruction, &header) == 0); SplTokenInfo info; @@ -425,41 +531,50 @@ void test_parse_spl_token_set_authority() { assert(info.kind == SplTokenKind(SetAuthority)); const SplTokenSetAuthorityInfo* so_info = &info.set_owner; - const Pubkey token_account = {{ TOKEN_ACCOUNT }}; + const Pubkey token_account = {{TOKEN_ACCOUNT}}; assert_pubkey_equal(so_info->account, &token_account); assert(so_info->authority_type == Token_AuthorityType_AccountOwner); - const Pubkey new_owner = {{ NEW_OWNER }}; + const Pubkey new_owner = {{NEW_OWNER}}; assert_pubkey_equal(so_info->new_authority, &new_owner); - const Pubkey owner = {{ OWNER_ACCOUNT }}; + const Pubkey owner = {{OWNER_ACCOUNT}}; assert_pubkey_equal(so_info->sign.single.signer, &owner); } void test_parse_spl_token_mint_to() { - uint8_t message[] = { - 1, 0, 0, - 3, - OWNER_ACCOUNT, - PROGRAM_ID_SPL_TOKEN, - TOKEN_ACCOUNT, - BLOCKHASH, - 1, - 1, - 3, - 1, 2, 0, - 10, - 14, - 42, 0, 0, 0, 0, 0, 0, 0, - 9 - }; + uint8_t message[] = {1, + 0, + 0, + 3, + OWNER_ACCOUNT, + PROGRAM_ID_SPL_TOKEN, + TOKEN_ACCOUNT, + BLOCKHASH, + 1, + 1, + 3, + 1, + 2, + 0, + 10, + 14, + 42, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 9}; Parser parser = {message, sizeof(message)}; MessageHeader header; assert(parse_message_header(&parser, &header) == 0); Instruction instruction; - assert(parse_instruction(&parser, &instruction) == 0); // SplTokenMintTo2 + assert(parse_instruction(&parser, &instruction) == 0); // SplTokenMintTo2 assert(instruction_validate(&instruction, &header) == 0); SplTokenInfo info; @@ -472,40 +587,49 @@ void test_parse_spl_token_mint_to() { assert(mt_info->body.amount == 42); assert(mt_info->body.decimals == 9); - const Pubkey mint_account = {{ PROGRAM_ID_SPL_TOKEN }}; + const Pubkey mint_account = {{PROGRAM_ID_SPL_TOKEN}}; assert_pubkey_equal(mt_info->mint_account, &mint_account); - const Pubkey token_account = {{ TOKEN_ACCOUNT }}; + const Pubkey token_account = {{TOKEN_ACCOUNT}}; assert_pubkey_equal(mt_info->token_account, &token_account); - const Pubkey owner = {{ OWNER_ACCOUNT }}; + const Pubkey owner = {{OWNER_ACCOUNT}}; assert_pubkey_equal(mt_info->sign.single.signer, &owner); } void test_parse_spl_token_burn() { - uint8_t message[] = { - 1, 0, 0, - 4, - OWNER_ACCOUNT, - TOKEN_ACCOUNT, - MINT_ACCOUNT, - PROGRAM_ID_SPL_TOKEN, - BLOCKHASH, - 1, - 3, - 3, - 1, 2, 0, - 10, - 15, - 42, 0, 0, 0, 0, 0, 0, 0, - 9 - }; + uint8_t message[] = {1, + 0, + 0, + 4, + OWNER_ACCOUNT, + TOKEN_ACCOUNT, + MINT_ACCOUNT, + PROGRAM_ID_SPL_TOKEN, + BLOCKHASH, + 1, + 3, + 3, + 1, + 2, + 0, + 10, + 15, + 42, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 9}; Parser parser = {message, sizeof(message)}; MessageHeader header; assert(parse_message_header(&parser, &header) == 0); Instruction instruction; - assert(parse_instruction(&parser, &instruction) == 0); // SplTokenBurn + assert(parse_instruction(&parser, &instruction) == 0); // SplTokenBurn assert(instruction_validate(&instruction, &header) == 0); SplTokenInfo info; @@ -518,38 +642,42 @@ void test_parse_spl_token_burn() { assert(bn_info->body.amount == 42); assert(bn_info->body.decimals == 9); - const Pubkey token_account = {{ TOKEN_ACCOUNT }}; + const Pubkey token_account = {{TOKEN_ACCOUNT}}; assert_pubkey_equal(bn_info->token_account, &token_account); - const Pubkey owner = {{ OWNER_ACCOUNT }}; + const Pubkey owner = {{OWNER_ACCOUNT}}; assert_pubkey_equal(bn_info->sign.single.signer, &owner); - const Pubkey mint_account = {{ MINT_ACCOUNT }}; + const Pubkey mint_account = {{MINT_ACCOUNT}}; assert_pubkey_equal(bn_info->mint_account, &mint_account); } void test_parse_spl_token_close_account() { uint8_t message[] = { - 0x01, 0x00, 0x01, + 0x01, + 0x00, + 0x01, 0x03, - OWNER_ACCOUNT, - TOKEN_ACCOUNT, - PROGRAM_ID_SPL_TOKEN, + OWNER_ACCOUNT, + TOKEN_ACCOUNT, + PROGRAM_ID_SPL_TOKEN, BLOCKHASH, 0x01, - // SplTokenCloseAccount - 0x02, - 0x03, - 0x01, 0x00, 0x00, - 0x01, - 0x09, + // SplTokenCloseAccount + 0x02, + 0x03, + 0x01, + 0x00, + 0x00, + 0x01, + 0x09, }; Parser parser = {message, sizeof(message)}; MessageHeader header; assert(parse_message_header(&parser, &header) == 0); Instruction instruction; - assert(parse_instruction(&parser, &instruction) == 0); // SplTokenCloseAccount + assert(parse_instruction(&parser, &instruction) == 0); // SplTokenCloseAccount assert(instruction_validate(&instruction, &header) == 0); SplTokenInfo info; @@ -559,37 +687,39 @@ void test_parse_spl_token_close_account() { assert(info.kind == SplTokenKind(CloseAccount)); const SplTokenCloseAccountInfo* close_acc = &info.close_account; - const Pubkey token_account = {{ TOKEN_ACCOUNT }}; + const Pubkey token_account = {{TOKEN_ACCOUNT}}; assert_pubkey_equal(close_acc->token_account, &token_account); - const Pubkey owner = {{ OWNER_ACCOUNT }}; + const Pubkey owner = {{OWNER_ACCOUNT}}; assert_pubkey_equal(close_acc->dest_account, &owner); assert_pubkey_equal(close_acc->sign.single.signer, &owner); } void test_parse_spl_token_freeze_account() { - uint8_t message[] = { - 1, 0, 2, - 4, - OWNER_ACCOUNT, - TOKEN_ACCOUNT, - MINT_ACCOUNT, - PROGRAM_ID_SPL_TOKEN, - BLOCKHASH, - 1, - 3, - 3, - 1, 2, 0, - 1, - 10 - }; + uint8_t message[] = {1, + 0, + 2, + 4, + OWNER_ACCOUNT, + TOKEN_ACCOUNT, + MINT_ACCOUNT, + PROGRAM_ID_SPL_TOKEN, + BLOCKHASH, + 1, + 3, + 3, + 1, + 2, + 0, + 1, + 10}; Parser parser = {message, sizeof(message)}; MessageHeader header; assert(parse_message_header(&parser, &header) == 0); Instruction instruction; - assert(parse_instruction(&parser, &instruction) == 0); // SplTokenFreezeAccount + assert(parse_instruction(&parser, &instruction) == 0); // SplTokenFreezeAccount assert(instruction_validate(&instruction, &header) == 0); SplTokenInfo info; @@ -599,38 +729,40 @@ void test_parse_spl_token_freeze_account() { assert(info.kind == SplTokenKind(FreezeAccount)); const SplTokenFreezeAccountInfo* freeze_account = &info.freeze_account; - const Pubkey token_account = {{ TOKEN_ACCOUNT }}; + const Pubkey token_account = {{TOKEN_ACCOUNT}}; assert_pubkey_equal(freeze_account->token_account, &token_account); - const Pubkey mint_account = {{ MINT_ACCOUNT }}; + const Pubkey mint_account = {{MINT_ACCOUNT}}; assert_pubkey_equal(freeze_account->mint_account, &mint_account); - const Pubkey owner = {{ OWNER_ACCOUNT }}; + const Pubkey owner = {{OWNER_ACCOUNT}}; assert_pubkey_equal(freeze_account->sign.single.signer, &owner); } void test_parse_spl_token_thaw_account() { - uint8_t message[] = { - 1, 0, 2, - 4, - OWNER_ACCOUNT, - TOKEN_ACCOUNT, - MINT_ACCOUNT, - PROGRAM_ID_SPL_TOKEN, - BLOCKHASH, - 1, - 3, - 3, - 1, 2, 0, - 1, - 11 - }; + uint8_t message[] = {1, + 0, + 2, + 4, + OWNER_ACCOUNT, + TOKEN_ACCOUNT, + MINT_ACCOUNT, + PROGRAM_ID_SPL_TOKEN, + BLOCKHASH, + 1, + 3, + 3, + 1, + 2, + 0, + 1, + 11}; Parser parser = {message, sizeof(message)}; MessageHeader header; assert(parse_message_header(&parser, &header) == 0); Instruction instruction; - assert(parse_instruction(&parser, &instruction) == 0); // SplTokenThawAccount + assert(parse_instruction(&parser, &instruction) == 0); // SplTokenThawAccount assert(instruction_validate(&instruction, &header) == 0); SplTokenInfo info; @@ -640,37 +772,37 @@ void test_parse_spl_token_thaw_account() { assert(info.kind == SplTokenKind(ThawAccount)); const SplTokenThawAccountInfo* thaw_account = &info.thaw_account; - const Pubkey token_account = {{ TOKEN_ACCOUNT }}; + const Pubkey token_account = {{TOKEN_ACCOUNT}}; assert_pubkey_equal(thaw_account->token_account, &token_account); - const Pubkey mint_account = {{ MINT_ACCOUNT }}; + const Pubkey mint_account = {{MINT_ACCOUNT}}; assert_pubkey_equal(thaw_account->mint_account, &mint_account); - const Pubkey owner = {{ OWNER_ACCOUNT }}; + const Pubkey owner = {{OWNER_ACCOUNT}}; assert_pubkey_equal(thaw_account->sign.single.signer, &owner); } void test_parse_spl_token_sync_native() { - uint8_t message[] = { - 1, 0, 1, - 4, - OWNER_ACCOUNT, - TOKEN_ACCOUNT, - PROGRAM_ID_SPL_TOKEN, - BLOCKHASH, - 1, - 2, - 1, - 1, - 1, - 17 - }; + uint8_t message[] = {1, + 0, + 1, + 4, + OWNER_ACCOUNT, + TOKEN_ACCOUNT, + PROGRAM_ID_SPL_TOKEN, + BLOCKHASH, + 1, + 2, + 1, + 1, + 1, + 17}; Parser parser = {message, sizeof(message)}; MessageHeader header; assert(parse_message_header(&parser, &header) == 0); Instruction instruction; - assert(parse_instruction(&parser, &instruction) == 0); // SplTokenSyncNative + assert(parse_instruction(&parser, &instruction) == 0); // SplTokenSyncNative assert(instruction_validate(&instruction, &header) == 0); SplTokenInfo info; @@ -680,16 +812,15 @@ void test_parse_spl_token_sync_native() { assert(info.kind == SplTokenKind(SyncNative)); const SplTokenSyncNativeInfo* sync_native = &info.sync_native; - const Pubkey token_account = {{ TOKEN_ACCOUNT }}; + const Pubkey token_account = {{TOKEN_ACCOUNT}}; assert_pubkey_equal(sync_native->token_account, &token_account); } - void test_parse_spl_token_instruction_kind() { SplTokenInstructionKind kind; - uint8_t buf[] = { 0 }; - Parser parser = { buf, ARRAY_LEN(buf) }; + uint8_t buf[] = {0}; + Parser parser = {buf, ARRAY_LEN(buf)}; assert(parse_spl_token_instruction_kind(&parser, &kind) == 0); assert(kind == SplTokenKind(InitializeMint)); @@ -807,11 +938,11 @@ void test_parse_spl_token_instruction_kind() { void test_parse_spl_token_sign() { const size_t max_signers = Token_MAX_SIGNERS; - const size_t max_accounts = 1 + max_signers; // multisig_account + signers - const size_t accounts_len = max_accounts + 1; // one too many + const size_t max_accounts = 1 + max_signers; // multisig_account + signers + const size_t accounts_len = max_accounts + 1; // one too many const Pubkey pubkeys[1]; const MessageHeader header = { - .pubkeys_header = { 0, 0, 0, 1}, + .pubkeys_header = {0, 0, 0, 1}, .pubkeys = pubkeys, }; uint8_t accounts[accounts_len]; diff --git a/libsol/stake_instruction.c b/libsol/stake_instruction.c index 209d7302..a932c93d 100644 --- a/libsol/stake_instruction.c +++ b/libsol/stake_instruction.c @@ -7,14 +7,9 @@ #include #include -const Pubkey stake_program_id = {{ - PROGRAM_ID_STAKE -}}; - -static int parse_stake_instruction_kind( - Parser* parser, - enum StakeInstructionKind* kind -) { +const Pubkey stake_program_id = {{PROGRAM_ID_STAKE}}; + +static int parse_stake_instruction_kind(Parser* parser, enum StakeInstructionKind* kind) { uint32_t maybe_kind; BAIL_IF(parse_u32(parser, &maybe_kind)); switch (maybe_kind) { @@ -37,10 +32,7 @@ static int parse_stake_instruction_kind( return 1; } -static int parse_stake_authorize( - Parser* parser, - enum StakeAuthorize* authorize -) { +static int parse_stake_authorize(Parser* parser, enum StakeAuthorize* authorize) { uint32_t maybe_authorize; BAIL_IF(parse_u32(parser, &maybe_authorize)); switch (maybe_authorize) { @@ -54,11 +46,9 @@ static int parse_stake_authorize( // Returns 0 and populates StakeDelegateInfo if provided a MessageHeader // and a delegate instruction, otherwise non-zero. -static int parse_delegate_stake_instruction( - const Instruction* instruction, - const MessageHeader* header, - StakeDelegateInfo* info -) { +static int parse_delegate_stake_instruction(const Instruction* instruction, + const MessageHeader* header, + StakeDelegateInfo* info) { InstructionAccountsIterator it; instruction_accounts_iterator_init(&it, header, instruction); @@ -75,12 +65,10 @@ static int parse_delegate_stake_instruction( return 0; } -static int parse_stake_initialize_instruction( - Parser* parser, - const Instruction* instruction, - const MessageHeader* header, - StakeInitializeInfo* info -) { +static int parse_stake_initialize_instruction(Parser* parser, + const Instruction* instruction, + const MessageHeader* header, + StakeInitializeInfo* info) { InstructionAccountsIterator it; instruction_accounts_iterator_init(&it, header, instruction); @@ -99,12 +87,10 @@ static int parse_stake_initialize_instruction( return 0; } -static int parse_stake_initialize_checked_instruction( - Parser* parser, - const Instruction* instruction, - const MessageHeader* header, - StakeInitializeInfo* info -) { +static int parse_stake_initialize_checked_instruction(Parser* parser, + const Instruction* instruction, + const MessageHeader* header, + StakeInitializeInfo* info) { UNUSED(parser); InstructionAccountsIterator it; @@ -122,12 +108,10 @@ static int parse_stake_initialize_checked_instruction( return 0; } -static int parse_stake_withdraw_instruction( - Parser* parser, - const Instruction* instruction, - const MessageHeader* header, - StakeWithdrawInfo* info -) { +static int parse_stake_withdraw_instruction(Parser* parser, + const Instruction* instruction, + const MessageHeader* header, + StakeWithdrawInfo* info) { InstructionAccountsIterator it; instruction_accounts_iterator_init(&it, header, instruction); @@ -144,12 +128,10 @@ static int parse_stake_withdraw_instruction( return 0; } -static int parse_stake_authorize_instruction( - Parser* parser, - const Instruction* instruction, - const MessageHeader* header, - StakeAuthorizeInfo* info -) { +static int parse_stake_authorize_instruction(Parser* parser, + const Instruction* instruction, + const MessageHeader* header, + StakeAuthorizeInfo* info) { InstructionAccountsIterator it; instruction_accounts_iterator_init(&it, header, instruction); @@ -166,12 +148,10 @@ static int parse_stake_authorize_instruction( return 0; } -static int parse_stake_authorize_checked_instruction( - Parser* parser, - const Instruction* instruction, - const MessageHeader* header, - StakeAuthorizeInfo* info -) { +static int parse_stake_authorize_checked_instruction(Parser* parser, + const Instruction* instruction, + const MessageHeader* header, + StakeAuthorizeInfo* info) { InstructionAccountsIterator it; instruction_accounts_iterator_init(&it, header, instruction); @@ -188,12 +168,10 @@ static int parse_stake_authorize_checked_instruction( return 0; } -static int parse_stake_deactivate_instruction( - Parser* parser, - const Instruction* instruction, - const MessageHeader* header, - StakeDeactivateInfo* info -) { +static int parse_stake_deactivate_instruction(Parser* parser, + const Instruction* instruction, + const MessageHeader* header, + StakeDeactivateInfo* info) { UNUSED(parser); InstructionAccountsIterator it; @@ -207,11 +185,7 @@ static int parse_stake_deactivate_instruction( return 0; } -static int parse_stake_lockupargs( - Parser* parser, - StakeLockup* lockup, - bool parse_custodian -) { +static int parse_stake_lockupargs(Parser* parser, StakeLockup* lockup, bool parse_custodian) { // LockupArgs enum StakeLockupPresent present = StakeLockupHasNone; enum Option option; @@ -237,12 +211,10 @@ static int parse_stake_lockupargs( return 0; } -static int parse_stake_set_lockup_instruction( - Parser* parser, - const Instruction* instruction, - const MessageHeader* header, - StakeSetLockupInfo* info -) { +static int parse_stake_set_lockup_instruction(Parser* parser, + const Instruction* instruction, + const MessageHeader* header, + StakeSetLockupInfo* info) { InstructionAccountsIterator it; instruction_accounts_iterator_init(&it, header, instruction); @@ -254,12 +226,10 @@ static int parse_stake_set_lockup_instruction( return 0; } -static int parse_stake_set_lockup_checked_instruction( - Parser* parser, - const Instruction* instruction, - const MessageHeader* header, - StakeSetLockupInfo* info -) { +static int parse_stake_set_lockup_checked_instruction(Parser* parser, + const Instruction* instruction, + const MessageHeader* header, + StakeSetLockupInfo* info) { InstructionAccountsIterator it; instruction_accounts_iterator_init(&it, header, instruction); @@ -275,12 +245,10 @@ static int parse_stake_set_lockup_checked_instruction( return 0; } -static int parse_stake_split_instruction( - Parser* parser, - const Instruction* instruction, - const MessageHeader* header, - StakeSplitInfo* info -) { +static int parse_stake_split_instruction(Parser* parser, + const Instruction* instruction, + const MessageHeader* header, + StakeSplitInfo* info) { InstructionAccountsIterator it; instruction_accounts_iterator_init(&it, header, instruction); @@ -293,11 +261,9 @@ static int parse_stake_split_instruction( return 0; } -static int parse_stake_merge_instruction( - const Instruction* instruction, - const MessageHeader* header, - StakeMergeInfo* info -) { +static int parse_stake_merge_instruction(const Instruction* instruction, + const MessageHeader* header, + StakeMergeInfo* info) { InstructionAccountsIterator it; instruction_accounts_iterator_init(&it, header, instruction); @@ -312,91 +278,57 @@ static int parse_stake_merge_instruction( return 0; } -int parse_stake_instructions( - const Instruction* instruction, - const MessageHeader* header, - StakeInfo* info -) { +int parse_stake_instructions(const Instruction* instruction, + const MessageHeader* header, + StakeInfo* info) { Parser parser = {instruction->data, instruction->data_length}; BAIL_IF(parse_stake_instruction_kind(&parser, &info->kind)); switch (info->kind) { case StakeDelegate: - return parse_delegate_stake_instruction( - instruction, - header, - &info->delegate_stake - ); + return parse_delegate_stake_instruction(instruction, header, &info->delegate_stake); case StakeInitialize: - return parse_stake_initialize_instruction( - &parser, - instruction, - header, - &info->initialize - ); + return parse_stake_initialize_instruction(&parser, + instruction, + header, + &info->initialize); case StakeInitializeChecked: - return parse_stake_initialize_checked_instruction( - &parser, - instruction, - header, - &info->initialize - ); + return parse_stake_initialize_checked_instruction(&parser, + instruction, + header, + &info->initialize); case StakeWithdraw: - return parse_stake_withdraw_instruction( - &parser, - instruction, - header, - &info->withdraw - ); + return parse_stake_withdraw_instruction(&parser, instruction, header, &info->withdraw); case StakeAuthorize: - return parse_stake_authorize_instruction( - &parser, - instruction, - header, - &info->authorize - ); + return parse_stake_authorize_instruction(&parser, + instruction, + header, + &info->authorize); case StakeAuthorizeChecked: - return parse_stake_authorize_checked_instruction( - &parser, - instruction, - header, - &info->authorize - ); + return parse_stake_authorize_checked_instruction(&parser, + instruction, + header, + &info->authorize); case StakeDeactivate: - return parse_stake_deactivate_instruction( - &parser, - instruction, - header, - &info->deactivate - ); + return parse_stake_deactivate_instruction(&parser, + instruction, + header, + &info->deactivate); case StakeSetLockup: - return parse_stake_set_lockup_instruction( - &parser, - instruction, - header, - &info->set_lockup - ); + return parse_stake_set_lockup_instruction(&parser, + instruction, + header, + &info->set_lockup); case StakeSetLockupChecked: - return parse_stake_set_lockup_checked_instruction( - &parser, - instruction, - header, - &info->set_lockup - ); + return parse_stake_set_lockup_checked_instruction(&parser, + instruction, + header, + &info->set_lockup); case StakeSplit: - return parse_stake_split_instruction( - &parser, - instruction, - header, - &info->split - ); + return parse_stake_split_instruction(&parser, instruction, header, &info->split); case StakeMerge: - return parse_stake_merge_instruction( - instruction, - header, - &info->merge - ); + return parse_stake_merge_instruction(instruction, header, &info->merge); // Unsupported instructions case StakeAuthorizeWithSeed: case StakeAuthorizeCheckedWithSeed: @@ -406,16 +338,14 @@ int parse_stake_instructions( return 1; } -int print_delegate_stake_info( - const char* primary_title, - const StakeDelegateInfo* info, - const PrintConfig* print_config -) { +int print_delegate_stake_info(const char* primary_title, + const StakeDelegateInfo* info, + const PrintConfig* print_config) { SummaryItem* item; if (primary_title != NULL) { - item = transaction_summary_primary_item(); - summary_item_set_pubkey(item, primary_title, info->stake_pubkey); + item = transaction_summary_primary_item(); + summary_item_set_pubkey(item, primary_title, info->stake_pubkey); } if (print_config_show_authority(print_config, info->authorized_pubkey)) { @@ -429,10 +359,8 @@ int print_delegate_stake_info( return 0; } -static int print_stake_withdraw_info( - const StakeWithdrawInfo* info, - const PrintConfig* print_config -) { +static int print_stake_withdraw_info(const StakeWithdrawInfo* info, + const PrintConfig* print_config) { SummaryItem* item; item = transaction_summary_primary_item(); @@ -452,10 +380,8 @@ static int print_stake_withdraw_info( return 0; } -static int print_stake_authorize_info( - const StakeAuthorizeInfo* info, - const PrintConfig* print_config -) { +static int print_stake_authorize_info(const StakeAuthorizeInfo* info, + const PrintConfig* print_config) { const char* new_authority_title = NULL; SummaryItem* item; @@ -479,9 +405,7 @@ static int print_stake_authorize_info( summary_item_set_pubkey(item, "Authorized by", info->authority); } - if (info->custodian - && print_config_show_authority(print_config, info->custodian) - ) { + if (info->custodian && print_config_show_authority(print_config, info->custodian)) { item = transaction_summary_general_item(); summary_item_set_pubkey(item, "Custodian", info->custodian); } @@ -489,10 +413,8 @@ static int print_stake_authorize_info( return 0; } -static int print_stake_deactivate_info( - const StakeDeactivateInfo* info, - const PrintConfig* print_config -) { +static int print_stake_deactivate_info(const StakeDeactivateInfo* info, + const PrintConfig* print_config) { SummaryItem* item; item = transaction_summary_primary_item(); @@ -506,10 +428,8 @@ static int print_stake_deactivate_info( return 0; } -static int print_stake_set_lockup_info( - const StakeSetLockupInfo* info, - const PrintConfig* print_config -) { +static int print_stake_set_lockup_info(const StakeSetLockupInfo* info, + const PrintConfig* print_config) { SummaryItem* item; item = transaction_summary_primary_item(); @@ -518,11 +438,7 @@ static int print_stake_set_lockup_info( enum StakeLockupPresent present = info->lockup.present; if (present & StakeLockupHasTimestamp) { item = transaction_summary_general_item(); - summary_item_set_timestamp( - item, - "Time", - info->lockup.unix_timestamp - ); + summary_item_set_timestamp(item, "Time", info->lockup.unix_timestamp); } if (present & StakeLockupHasEpoch) { @@ -532,11 +448,7 @@ static int print_stake_set_lockup_info( if (present & StakeLockupHasCustodian) { item = transaction_summary_general_item(); - summary_item_set_pubkey( - item, - "New authority", - info->lockup.custodian - ); + summary_item_set_pubkey(item, "New authority", info->lockup.custodian); } if (print_config_show_authority(print_config, info->custodian)) { @@ -547,18 +459,12 @@ static int print_stake_set_lockup_info( return 0; } -static int print_stake_split_info( - const StakeSplitInfo* info, - const PrintConfig* print_config -) { +static int print_stake_split_info(const StakeSplitInfo* info, const PrintConfig* print_config) { BAIL_IF(print_stake_split_info1(info, print_config)); return print_stake_split_info2(info, print_config); } -static int print_stake_merge_info( - const StakeMergeInfo* info, - const PrintConfig* print_config -) { +static int print_stake_merge_info(const StakeMergeInfo* info, const PrintConfig* print_config) { SummaryItem* item; item = transaction_summary_primary_item(); @@ -575,24 +481,13 @@ static int print_stake_merge_info( return 0; } -int print_stake_info( - const StakeInfo* info, - const PrintConfig* print_config -) { +int print_stake_info(const StakeInfo* info, const PrintConfig* print_config) { switch (info->kind) { case StakeDelegate: - return print_delegate_stake_info( - "Delegate from", - &info->delegate_stake, - print_config - ); + return print_delegate_stake_info("Delegate from", &info->delegate_stake, print_config); case StakeInitialize: case StakeInitializeChecked: - return print_stake_initialize_info( - "Init stake acct", - &info->initialize, - print_config - ); + return print_stake_initialize_info("Init stake acct", &info->initialize, print_config); case StakeWithdraw: return print_stake_withdraw_info(&info->withdraw, print_config); case StakeAuthorize: @@ -616,16 +511,11 @@ int print_stake_info( return 1; } -int print_stake_initialize_info( - const char* primary_title, - const StakeInitializeInfo* info, - const PrintConfig* print_config -) { +int print_stake_initialize_info(const char* primary_title, + const StakeInitializeInfo* info, + const PrintConfig* print_config) { SummaryItem* item; - bool one_authority = pubkeys_equal( - info->withdraw_authority, - info->stake_authority - ); + bool one_authority = pubkeys_equal(info->withdraw_authority, info->stake_authority); if (primary_title != NULL) { item = transaction_summary_primary_item(); @@ -640,11 +530,7 @@ int print_stake_initialize_info( summary_item_set_pubkey(item, "New stake auth", info->stake_authority); item = transaction_summary_general_item(); - summary_item_set_pubkey( - item, - "New withdraw auth", - info->withdraw_authority - ); + summary_item_set_pubkey(item, "New withdraw auth", info->withdraw_authority); } int64_t lockup_time = info->lockup.unix_timestamp; @@ -652,11 +538,7 @@ int print_stake_initialize_info( if (lockup_time > 0 || lockup_epoch > 0) { if (lockup_time > 0) { item = transaction_summary_general_item(); - summary_item_set_timestamp( - item, - "Lockup time", - lockup_time - ); + summary_item_set_timestamp(item, "Lockup time", lockup_time); } if (lockup_epoch > 0) { @@ -665,27 +547,16 @@ int print_stake_initialize_info( } item = transaction_summary_general_item(); - summary_item_set_pubkey( - item, - "Lockup authority", - info->lockup.custodian - ); + summary_item_set_pubkey(item, "Lockup authority", info->lockup.custodian); } else if (print_config->expert_mode) { item = transaction_summary_general_item(); - summary_item_set_string( - item, - "Lockup", - "None" - ); + summary_item_set_string(item, "Lockup", "None"); } return 0; } -int print_stake_split_info1( - const StakeSplitInfo* info, - const PrintConfig* print_config -) { +int print_stake_split_info1(const StakeSplitInfo* info, const PrintConfig* print_config) { UNUSED(print_config); SummaryItem* item; @@ -702,10 +573,7 @@ int print_stake_split_info1( return 0; } -int print_stake_split_info2( - const StakeSplitInfo* info, - const PrintConfig* print_config -) { +int print_stake_split_info2(const StakeSplitInfo* info, const PrintConfig* print_config) { if (print_config_show_authority(print_config, info->authority)) { SummaryItem* item; diff --git a/libsol/stake_instruction.h b/libsol/stake_instruction.h index f2424c6d..1bdcac6d 100644 --- a/libsol/stake_instruction.h +++ b/libsol/stake_instruction.h @@ -31,15 +31,11 @@ typedef struct StakeDelegateInfo { // which looks like a `Lockup`, but all of the members are wrapped // with `Option<>`s typedef enum StakeLockupPresent { - StakeLockupHasNone = 0, + StakeLockupHasNone = 0, StakeLockupHasTimestamp = 1 << 0, - StakeLockupHasEpoch = 1 << 1, + StakeLockupHasEpoch = 1 << 1, StakeLockupHasCustodian = 1 << 2, - StakeLockupHasAll = ( - StakeLockupHasTimestamp - | StakeLockupHasEpoch - | StakeLockupHasCustodian - ), + StakeLockupHasAll = (StakeLockupHasTimestamp | StakeLockupHasEpoch | StakeLockupHasCustodian), } StakeLockupPresent; typedef struct StakeLockup { @@ -114,34 +110,19 @@ typedef struct StakeInfo { }; } StakeInfo; -int parse_stake_instructions( - const Instruction* instruction, - const MessageHeader* header, - StakeInfo* info -); -int print_stake_info( - const StakeInfo* info, - const PrintConfig* print_config -); - -int print_stake_initialize_info( - const char* primary_title, - const StakeInitializeInfo* info, - const PrintConfig* print_config -); - -int print_stake_split_info1( - const StakeSplitInfo* info, - const PrintConfig* print_config -); - -int print_stake_split_info2( - const StakeSplitInfo* info, - const PrintConfig* print_config -); - -int print_delegate_stake_info( - const char* primary_title, - const StakeDelegateInfo* info, - const PrintConfig* print_config -); +int parse_stake_instructions(const Instruction* instruction, + const MessageHeader* header, + StakeInfo* info); +int print_stake_info(const StakeInfo* info, const PrintConfig* print_config); + +int print_stake_initialize_info(const char* primary_title, + const StakeInitializeInfo* info, + const PrintConfig* print_config); + +int print_stake_split_info1(const StakeSplitInfo* info, const PrintConfig* print_config); + +int print_stake_split_info2(const StakeSplitInfo* info, const PrintConfig* print_config); + +int print_delegate_stake_info(const char* primary_title, + const StakeDelegateInfo* info, + const PrintConfig* print_config); diff --git a/libsol/stake_instruction_test.c b/libsol/stake_instruction_test.c index 5a6c7015..ece5ba9e 100644 --- a/libsol/stake_instruction_test.c +++ b/libsol/stake_instruction_test.c @@ -6,31 +6,22 @@ void test_parse_delegate_stake_instructions() { uint8_t message[] = { - 1, 1, 5, - 7, - 204, 241, 115, 109, 41, 173, 110, 48, 24, 113, 210, 213, 163, 78, 1, 112, - 146, 114, 235, 220, 96, 185, 184, 85, 163, 27, 124, 48, 54, 250, 233, 54, - 171, 88, 202, 32, 185, 160, 182, 116, 130, 185, 73, 48, 13, 216, 170, 71, - 172, 195, 165, 123, 87, 70, 130, 219, 5, 157, 240, 187, 26, 191, 158, 218, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 6, 167, 213, 23, 24, 199, 116, 201, 40, 86, 99, 152, 105, 29, 94, 182, - 139, 94, 184, 163, 155, 75, 109, 92, 115, 85, 91, 33, 0, 0, 0, 0, - 6, 167, 213, 23, 25, 53, 132, 208, 254, 237, 155, 179, 67, 29, 19, 32, - 107, 229, 68, 40, 27, 87, 184, 86, 108, 197, 55, 95, 244, 0, 0, 0, - 6, 161, 216, 23, 165, 2, 5, 11, 104, 7, 145, 230, 206, 109, 184, 142, - 30, 91, 113, 80, 246, 31, 198, 121, 10, 78, 180, 209, 0, 0, 0, 0, - 6, 161, 216, 23, 145, 55, 84, 42, 152, 52, 55, 189, 254, 42, 122, 178, - 85, 127, 83, 92, 138, 120, 114, 43, 104, 164, 157, 192, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1, - 6, - 6, - 1, 2, 3, 4, 5, 0, - 4, - 2, 0, 0, 0 - }; + 1, 1, 5, 7, 204, 241, 115, 109, 41, 173, 110, 48, 24, 113, 210, 213, 163, 78, + 1, 112, 146, 114, 235, 220, 96, 185, 184, 85, 163, 27, 124, 48, 54, 250, 233, 54, + 171, 88, 202, 32, 185, 160, 182, 116, 130, 185, 73, 48, 13, 216, 170, 71, 172, 195, + 165, 123, 87, 70, 130, 219, 5, 157, 240, 187, 26, 191, 158, 218, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 167, 213, 23, 24, 199, 116, 201, + 40, 86, 99, 152, 105, 29, 94, 182, 139, 94, 184, 163, 155, 75, 109, 92, 115, 85, + 91, 33, 0, 0, 0, 0, 6, 167, 213, 23, 25, 53, 132, 208, 254, 237, 155, 179, + 67, 29, 19, 32, 107, 229, 68, 40, 27, 87, 184, 86, 108, 197, 55, 95, 244, 0, + 0, 0, 6, 161, 216, 23, 165, 2, 5, 11, 104, 7, 145, 230, 206, 109, 184, 142, + 30, 91, 113, 80, 246, 31, 198, 121, 10, 78, 180, 209, 0, 0, 0, 0, 6, 161, + 216, 23, 145, 55, 84, 42, 152, 52, 55, 189, 254, 42, 122, 178, 85, 127, 83, 92, + 138, 120, 114, 43, 104, 164, 157, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 6, 6, 1, 2, 3, 4, 5, 0, 4, + 2, 0, 0, 0}; Parser parser = {message, sizeof(message)}; MessageHeader header; assert(parse_message_header(&parser, &header) == 0); @@ -45,39 +36,49 @@ void test_parse_delegate_stake_instructions() { } void test_parse_stake_initialize_instruction() { -#define ACCOUNT_PUBKEY_BYTES BYTES32_BS58_2 -#define ST_AUTHORITY_PUBKEY_BYTES BYTES32_BS58_3 -#define WD_AUTHORITY_PUBKEY_BYTES BYTES32_BS58_4 -#define CUSTODIAN_PUBKEY_BYTES BYTES32_BS58_5 +#define ACCOUNT_PUBKEY_BYTES BYTES32_BS58_2 +#define ST_AUTHORITY_PUBKEY_BYTES BYTES32_BS58_3 +#define WD_AUTHORITY_PUBKEY_BYTES BYTES32_BS58_4 +#define CUSTODIAN_PUBKEY_BYTES BYTES32_BS58_5 Pubkey pubkeys[3] = { - {{ ACCOUNT_PUBKEY_BYTES }}, - {{ SYSVAR_RENT }}, + {{ACCOUNT_PUBKEY_BYTES}}, + {{SYSVAR_RENT}}, }; memcpy(&pubkeys[2], &stake_program_id, PUBKEY_SIZE); - Blockhash blockhash = {{ BYTES32_BS58_6 }}; - MessageHeader header = { - { 1, 0, 1, ARRAY_LEN(pubkeys) }, - pubkeys, - &blockhash, - 1 - }; - uint8_t accounts[] = { 0, 1 }; - uint8_t ix_data[] = { - /* kind */ - 0x00, 0x00, 0x00, 0x00, - /* authorized */ - /* staker */ - ST_AUTHORITY_PUBKEY_BYTES, - /* withdrawer */ - WD_AUTHORITY_PUBKEY_BYTES, - /* lockup */ - /* unix_timestamp (16) */ - 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - /* epoch (1) */ - 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - /* custodian */ - CUSTODIAN_PUBKEY_BYTES - }; + Blockhash blockhash = {{BYTES32_BS58_6}}; + MessageHeader header = {false, 0, {1, 0, 1, ARRAY_LEN(pubkeys)}, pubkeys, &blockhash, 1}; + uint8_t accounts[] = {0, 1}; + uint8_t ix_data[] = {/* kind */ + 0x00, + 0x00, + 0x00, + 0x00, + /* authorized */ + /* staker */ + ST_AUTHORITY_PUBKEY_BYTES, + /* withdrawer */ + WD_AUTHORITY_PUBKEY_BYTES, + /* lockup */ + /* unix_timestamp (16) */ + 0x10, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + /* epoch (1) */ + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + /* custodian */ + CUSTODIAN_PUBKEY_BYTES}; Instruction instruction = { 2, accounts, @@ -87,40 +88,21 @@ void test_parse_stake_initialize_instruction() { }; /* kind is already parsed when we get here, skip it */ - Parser parser = { - ix_data + sizeof(uint32_t), - sizeof(ix_data) - sizeof(uint32_t) - }; + Parser parser = {ix_data + sizeof(uint32_t), sizeof(ix_data) - sizeof(uint32_t)}; StakeInfo info; - assert( - parse_stake_initialize_instruction( - &parser, - &instruction, - &header, - &info.initialize - ) == 0 - ); + assert(parse_stake_initialize_instruction(&parser, &instruction, &header, &info.initialize) == + 0); StakeInitializeInfo* sii = &info.initialize; assert(sii->lockup.unix_timestamp == 16); assert(sii->lockup.epoch == 1); - Pubkey new_account = {{ - ACCOUNT_PUBKEY_BYTES - }}; + Pubkey new_account = {{ACCOUNT_PUBKEY_BYTES}}; assert(memcmp(&new_account, sii->account, PUBKEY_SIZE) == 0); - Pubkey stake_authority = {{ - ST_AUTHORITY_PUBKEY_BYTES - }}; + Pubkey stake_authority = {{ST_AUTHORITY_PUBKEY_BYTES}}; assert(memcmp(&stake_authority, sii->stake_authority, PUBKEY_SIZE) == 0); - Pubkey withdraw_authority = {{ - WD_AUTHORITY_PUBKEY_BYTES - }}; - assert( - memcmp(&withdraw_authority, sii->withdraw_authority, PUBKEY_SIZE) == 0 - ); - - Pubkey custodian = {{ - CUSTODIAN_PUBKEY_BYTES - }}; + Pubkey withdraw_authority = {{WD_AUTHORITY_PUBKEY_BYTES}}; + assert(memcmp(&withdraw_authority, sii->withdraw_authority, PUBKEY_SIZE) == 0); + + Pubkey custodian = {{CUSTODIAN_PUBKEY_BYTES}}; assert(memcmp(&custodian, sii->lockup.custodian, PUBKEY_SIZE) == 0); /* Check that we're routed properly */ @@ -259,28 +241,56 @@ void test_parse_stake_lockup_args() { 0x00, // Just timestamp 0x01, - 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, 0x00, 0x00, // Just epoch 0x00, 0x01, - 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, 0x00, // Just custodian 0x00, 0x00, 0x01, - BYTES32_BS58_1, + BYTES32_BS58_1, // All Some 0x01, - 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x04, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, 0x01, - 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x05, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, 0x01, - BYTES32_BS58_2, + BYTES32_BS58_2, }; - Parser parser = { buf, sizeof(buf) }; + Parser parser = {buf, sizeof(buf)}; StakeLockup lockup; assert(parse_stake_lockupargs(&parser, &lockup, true) == 0); @@ -296,14 +306,14 @@ void test_parse_stake_lockup_args() { assert(parse_stake_lockupargs(&parser, &lockup, true) == 0); assert(lockup.present == StakeLockupHasCustodian); - Pubkey custodian1 = {{ BYTES32_BS58_1 }}; + Pubkey custodian1 = {{BYTES32_BS58_1}}; assert(memcmp(lockup.custodian, &custodian1, sizeof(Pubkey)) == 0); assert(parse_stake_lockupargs(&parser, &lockup, true) == 0); assert(lockup.present == StakeLockupHasAll); assert(lockup.unix_timestamp == 4); assert(lockup.epoch == 5); - Pubkey custodian2 = {{ BYTES32_BS58_2 }}; + Pubkey custodian2 = {{BYTES32_BS58_2}}; assert(memcmp(lockup.custodian, &custodian2, sizeof(Pubkey)) == 0); } @@ -315,21 +325,49 @@ void test_parse_stake_lockup_checked_args() { 0x00, // Just timestamp 0x01, - 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, 0x00, 0x00, // Just epoch 0x00, 0x01, - 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, 0x00, // All Some 0x01, - 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x04, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, 0x01, - 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x05, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, }; - Parser parser = { buf, sizeof(buf) }; + Parser parser = {buf, sizeof(buf)}; StakeLockup lockup; assert(parse_stake_lockupargs(&parser, &lockup, false) == 0); @@ -344,7 +382,7 @@ void test_parse_stake_lockup_checked_args() { assert(lockup.epoch == 3); assert(parse_stake_lockupargs(&parser, &lockup, false) == 0); - assert(lockup.present == (StakeLockupHasTimestamp|StakeLockupHasEpoch)); + assert(lockup.present == (StakeLockupHasTimestamp | StakeLockupHasEpoch)); assert(lockup.unix_timestamp == 4); assert(lockup.epoch == 5); } diff --git a/libsol/system_instruction.c b/libsol/system_instruction.c index d6155df0..f32ef82a 100644 --- a/libsol/system_instruction.c +++ b/libsol/system_instruction.c @@ -8,12 +8,9 @@ #define CREATE_ACCOUNT_TITLE "Create account" -const Pubkey system_program_id = {{ PROGRAM_ID_SYSTEM }}; +const Pubkey system_program_id = {{PROGRAM_ID_SYSTEM}}; -static int parse_system_instruction_kind( - Parser* parser, - enum SystemInstructionKind* kind -) { +static int parse_system_instruction_kind(Parser* parser, enum SystemInstructionKind* kind) { uint32_t maybe_kind; BAIL_IF(parse_u32(parser, &maybe_kind)); switch (maybe_kind) { @@ -36,12 +33,10 @@ static int parse_system_instruction_kind( // Returns 0 and populates SystemTransferInfo if provided a MessageHeader // and a transfer instruction, otherwise non-zero. -static int parse_system_transfer_instruction( - Parser* parser, - const Instruction* instruction, - const MessageHeader* header, - SystemTransferInfo* info -) { +static int parse_system_transfer_instruction(Parser* parser, + const Instruction* instruction, + const MessageHeader* header, + SystemTransferInfo* info) { InstructionAccountsIterator it; instruction_accounts_iterator_init(&it, header, instruction); @@ -53,12 +48,10 @@ static int parse_system_transfer_instruction( return 0; } -static int parse_system_create_account_instruction( - Parser* parser, - const Instruction* instruction, - const MessageHeader* header, - SystemCreateAccountInfo* info -) { +static int parse_system_create_account_instruction(Parser* parser, + const Instruction* instruction, + const MessageHeader* header, + SystemCreateAccountInfo* info) { InstructionAccountsIterator it; instruction_accounts_iterator_init(&it, header, instruction); @@ -74,8 +67,7 @@ static int parse_system_create_account_with_seed_instruction( Parser* parser, const Instruction* instruction, const MessageHeader* header, - SystemCreateAccountWithSeedInfo* info -) { + SystemCreateAccountWithSeedInfo* info) { InstructionAccountsIterator it; instruction_accounts_iterator_init(&it, header, instruction); @@ -89,12 +81,10 @@ static int parse_system_create_account_with_seed_instruction( return 0; } -static int parse_system_advance_nonce_account_instruction( - Parser* parser, - const Instruction* instruction, - const MessageHeader* header, - SystemAdvanceNonceInfo* info -) { +static int parse_system_advance_nonce_account_instruction(Parser* parser, + const Instruction* instruction, + const MessageHeader* header, + SystemAdvanceNonceInfo* info) { UNUSED(parser); InstructionAccountsIterator it; @@ -108,12 +98,10 @@ static int parse_system_advance_nonce_account_instruction( return 0; } -static int parse_system_initialize_nonce_account_instruction( - Parser* parser, - const Instruction* instruction, - const MessageHeader* header, - SystemInitializeNonceInfo* info -) { +static int parse_system_initialize_nonce_account_instruction(Parser* parser, + const Instruction* instruction, + const MessageHeader* header, + SystemInitializeNonceInfo* info) { InstructionAccountsIterator it; instruction_accounts_iterator_init(&it, header, instruction); @@ -128,12 +116,10 @@ static int parse_system_initialize_nonce_account_instruction( return 0; } -static int parse_system_withdraw_nonce_account_instruction( - Parser* parser, - const Instruction* instruction, - const MessageHeader* header, - SystemWithdrawNonceInfo* info -) { +static int parse_system_withdraw_nonce_account_instruction(Parser* parser, + const Instruction* instruction, + const MessageHeader* header, + SystemWithdrawNonceInfo* info) { InstructionAccountsIterator it; instruction_accounts_iterator_init(&it, header, instruction); @@ -150,12 +136,10 @@ static int parse_system_withdraw_nonce_account_instruction( return 0; } -static int parse_system_authorize_nonce_account_instruction( - Parser* parser, - const Instruction* instruction, - const MessageHeader* header, - SystemAuthorizeNonceInfo* info -) { +static int parse_system_authorize_nonce_account_instruction(Parser* parser, + const Instruction* instruction, + const MessageHeader* header, + SystemAuthorizeNonceInfo* info) { InstructionAccountsIterator it; instruction_accounts_iterator_init(&it, header, instruction); @@ -167,12 +151,10 @@ static int parse_system_authorize_nonce_account_instruction( return 0; } -static int parse_system_allocate_instruction( - Parser* parser, - const Instruction* instruction, - const MessageHeader* header, - SystemAllocateInfo* info -) { +static int parse_system_allocate_instruction(Parser* parser, + const Instruction* instruction, + const MessageHeader* header, + SystemAllocateInfo* info) { InstructionAccountsIterator it; instruction_accounts_iterator_init(&it, header, instruction); @@ -183,12 +165,10 @@ static int parse_system_allocate_instruction( return 0; } -static int parse_system_assign_instruction( - Parser* parser, - const Instruction* instruction, - const MessageHeader* header, - SystemAssignInfo* info -) { +static int parse_system_assign_instruction(Parser* parser, + const Instruction* instruction, + const MessageHeader* header, + SystemAssignInfo* info) { InstructionAccountsIterator it; instruction_accounts_iterator_init(&it, header, instruction); @@ -199,12 +179,10 @@ static int parse_system_assign_instruction( return 0; } -static int parse_system_allocate_with_seed_instruction( - Parser* parser, - const Instruction* instruction, - const MessageHeader* header, - SystemAllocateWithSeedInfo* info -) { +static int parse_system_allocate_with_seed_instruction(Parser* parser, + const Instruction* instruction, + const MessageHeader* header, + SystemAllocateWithSeedInfo* info) { InstructionAccountsIterator it; instruction_accounts_iterator_init(&it, header, instruction); @@ -220,86 +198,56 @@ static int parse_system_allocate_with_seed_instruction( return 0; } -int parse_system_instructions( - const Instruction* instruction, - const MessageHeader* header, - SystemInfo* info -) { +int parse_system_instructions(const Instruction* instruction, + const MessageHeader* header, + SystemInfo* info) { Parser parser = {instruction->data, instruction->data_length}; BAIL_IF(parse_system_instruction_kind(&parser, &info->kind)); switch (info->kind) { case SystemTransfer: - return parse_system_transfer_instruction( - &parser, - instruction, - header, - &info->transfer - ); + return parse_system_transfer_instruction(&parser, instruction, header, &info->transfer); case SystemAdvanceNonceAccount: - return parse_system_advance_nonce_account_instruction( - &parser, - instruction, - header, - &info->advance_nonce - ); + return parse_system_advance_nonce_account_instruction(&parser, + instruction, + header, + &info->advance_nonce); case SystemCreateAccount: - return parse_system_create_account_instruction( - &parser, - instruction, - header, - &info->create_account - ); + return parse_system_create_account_instruction(&parser, + instruction, + header, + &info->create_account); case SystemCreateAccountWithSeed: return parse_system_create_account_with_seed_instruction( &parser, instruction, header, - &info->create_account_with_seed - ); + &info->create_account_with_seed); case SystemInitializeNonceAccount: - return parse_system_initialize_nonce_account_instruction( - &parser, - instruction, - header, - &info->initialize_nonce - ); + return parse_system_initialize_nonce_account_instruction(&parser, + instruction, + header, + &info->initialize_nonce); case SystemWithdrawNonceAccount: - return parse_system_withdraw_nonce_account_instruction( - &parser, - instruction, - header, - &info->withdraw_nonce - ); + return parse_system_withdraw_nonce_account_instruction(&parser, + instruction, + header, + &info->withdraw_nonce); case SystemAuthorizeNonceAccount: - return parse_system_authorize_nonce_account_instruction( - &parser, - instruction, - header, - &info->authorize_nonce - ); + return parse_system_authorize_nonce_account_instruction(&parser, + instruction, + header, + &info->authorize_nonce); case SystemAssign: - return parse_system_assign_instruction( - &parser, - instruction, - header, - &info->assign - ); + return parse_system_assign_instruction(&parser, instruction, header, &info->assign); case SystemAllocate: - return parse_system_allocate_instruction( - &parser, - instruction, - header, - &info->allocate - ); + return parse_system_allocate_instruction(&parser, instruction, header, &info->allocate); case SystemAllocateWithSeed: - return parse_system_allocate_with_seed_instruction( - &parser, - instruction, - header, - &info->allocate_with_seed - ); + return parse_system_allocate_with_seed_instruction(&parser, + instruction, + header, + &info->allocate_with_seed); case SystemAssignWithSeed: break; } @@ -307,10 +255,8 @@ int parse_system_instructions( return 1; } -static int print_system_transfer_info( - const SystemTransferInfo* info, - const PrintConfig* print_config -) { +static int print_system_transfer_info(const SystemTransferInfo* info, + const PrintConfig* print_config) { SummaryItem* item; item = transaction_summary_primary_item(); @@ -327,10 +273,8 @@ static int print_system_transfer_info( return 0; } -static int print_system_advance_nonce_account( - const SystemAdvanceNonceInfo* info, - const PrintConfig* print_config -) { +static int print_system_advance_nonce_account(const SystemAdvanceNonceInfo* info, + const PrintConfig* print_config) { SummaryItem* item; item = transaction_summary_primary_item(); @@ -344,10 +288,8 @@ static int print_system_advance_nonce_account( return 0; } -static int print_system_withdraw_nonce_info( - const SystemWithdrawNonceInfo* info, - const PrintConfig* print_config -) { +static int print_system_withdraw_nonce_info(const SystemWithdrawNonceInfo* info, + const PrintConfig* print_config) { SummaryItem* item; item = transaction_summary_primary_item(); @@ -367,10 +309,8 @@ static int print_system_withdraw_nonce_info( return 0; } -static int print_system_authorize_nonce_info( - const SystemAuthorizeNonceInfo* info, - const PrintConfig* print_config -) { +static int print_system_authorize_nonce_info(const SystemAuthorizeNonceInfo* info, + const PrintConfig* print_config) { SummaryItem* item; item = transaction_summary_primary_item(); @@ -387,10 +327,8 @@ static int print_system_authorize_nonce_info( return 0; } -static int print_system_allocate_info( - const SystemAllocateInfo* info, - const PrintConfig* print_config -) { +static int print_system_allocate_info(const SystemAllocateInfo* info, + const PrintConfig* print_config) { UNUSED(print_config); SummaryItem* item; @@ -404,10 +342,7 @@ static int print_system_allocate_info( return 0; } -static int print_system_assign_info( - const SystemAssignInfo* info, - const PrintConfig* print_config -) { +static int print_system_assign_info(const SystemAssignInfo* info, const PrintConfig* print_config) { UNUSED(print_config); SummaryItem* item; @@ -426,48 +361,31 @@ int print_system_info(const SystemInfo* info, const PrintConfig* print_config) { case SystemTransfer: return print_system_transfer_info(&info->transfer, print_config); case SystemAdvanceNonceAccount: - return print_system_advance_nonce_account( - &info->advance_nonce, - print_config - ); + return print_system_advance_nonce_account(&info->advance_nonce, print_config); case SystemCreateAccount: - return print_system_create_account_info( - CREATE_ACCOUNT_TITLE, - &info->create_account, - print_config - ); + return print_system_create_account_info(CREATE_ACCOUNT_TITLE, + &info->create_account, + print_config); case SystemCreateAccountWithSeed: - return print_system_create_account_with_seed_info( - CREATE_ACCOUNT_TITLE, - &info->create_account_with_seed, - print_config - ); + return print_system_create_account_with_seed_info(CREATE_ACCOUNT_TITLE, + &info->create_account_with_seed, + print_config); case SystemInitializeNonceAccount: - return print_system_initialize_nonce_info( - "Init nonce acct", - &info->initialize_nonce, - print_config - ); + return print_system_initialize_nonce_info("Init nonce acct", + &info->initialize_nonce, + print_config); case SystemWithdrawNonceAccount: - return print_system_withdraw_nonce_info( - &info->withdraw_nonce, - print_config - ); + return print_system_withdraw_nonce_info(&info->withdraw_nonce, print_config); case SystemAuthorizeNonceAccount: - return print_system_authorize_nonce_info( - &info->authorize_nonce, - print_config - ); + return print_system_authorize_nonce_info(&info->authorize_nonce, print_config); case SystemAssign: return print_system_assign_info(&info->assign, print_config); case SystemAllocate: return print_system_allocate_info(&info->allocate, print_config); case SystemAllocateWithSeed: - return print_system_allocate_with_seed_info( - "Allocate acct", - &info->allocate_with_seed, - print_config - ); + return print_system_allocate_with_seed_info("Allocate acct", + &info->allocate_with_seed, + print_config); case SystemAssignWithSeed: break; } @@ -475,11 +393,9 @@ int print_system_info(const SystemInfo* info, const PrintConfig* print_config) { return 1; } -int print_system_nonced_transaction_sentinel( - const SystemInfo* info, - const PrintConfig* print_config -) { - if (print_config->expert_mode) { +int print_system_nonced_transaction_sentinel(const SystemInfo* info, + const PrintConfig* print_config) { + if (print_config->expert_mode) { const SystemAdvanceNonceInfo* nonce_info = &info->advance_nonce; SummaryItem* item; @@ -493,11 +409,9 @@ int print_system_nonced_transaction_sentinel( return 0; } -int print_system_create_account_info( - const char* primary_title, - const SystemCreateAccountInfo* info, - const PrintConfig* print_config -) { +int print_system_create_account_info(const char* primary_title, + const SystemCreateAccountInfo* info, + const PrintConfig* print_config) { SummaryItem* item; if (primary_title != NULL) { item = transaction_summary_primary_item(); @@ -515,11 +429,9 @@ int print_system_create_account_info( return 0; } -int print_system_create_account_with_seed_info( - const char* primary_title, - const SystemCreateAccountWithSeedInfo* info, - const PrintConfig* print_config -) { +int print_system_create_account_with_seed_info(const char* primary_title, + const SystemCreateAccountWithSeedInfo* info, + const PrintConfig* print_config) { SummaryItem* item; if (primary_title != NULL) { item = transaction_summary_primary_item(); @@ -545,11 +457,9 @@ int print_system_create_account_with_seed_info( return 0; } -int print_system_initialize_nonce_info( - const char* primary_title, - const SystemInitializeNonceInfo* info, - const PrintConfig* print_config -) { +int print_system_initialize_nonce_info(const char* primary_title, + const SystemInitializeNonceInfo* info, + const PrintConfig* print_config) { UNUSED(print_config); SummaryItem* item; @@ -564,11 +474,9 @@ int print_system_initialize_nonce_info( return 0; } -int print_system_allocate_with_seed_info( - const char* primary_title, - const SystemAllocateWithSeedInfo* info, - const PrintConfig* print_config -) { +int print_system_allocate_with_seed_info(const char* primary_title, + const SystemAllocateWithSeedInfo* info, + const PrintConfig* print_config) { SummaryItem* item; if (primary_title != NULL) { diff --git a/libsol/system_instruction.h b/libsol/system_instruction.h index 0b77844a..fdc82f00 100644 --- a/libsol/system_instruction.h +++ b/libsol/system_instruction.h @@ -96,36 +96,21 @@ typedef struct SystemInfo { }; } SystemInfo; -int parse_system_instructions( - const Instruction* instruction, - const MessageHeader* header, - SystemInfo* info -); -int print_system_info( - const SystemInfo* info, - const PrintConfig* print_config -); -int print_system_nonced_transaction_sentinel( - const SystemInfo* info, - const PrintConfig* print_config -); -int print_system_create_account_info( - const char* primary_title, - const SystemCreateAccountInfo* info, - const PrintConfig* print_config -); -int print_system_create_account_with_seed_info( - const char* primary_title, - const SystemCreateAccountWithSeedInfo* info, - const PrintConfig* print_config -); -int print_system_initialize_nonce_info( - const char* primary_title, - const SystemInitializeNonceInfo* info, - const PrintConfig* print_config -); -int print_system_allocate_with_seed_info( - const char* primary_title, - const SystemAllocateWithSeedInfo* info, - const PrintConfig* print_config -); +int parse_system_instructions(const Instruction* instruction, + const MessageHeader* header, + SystemInfo* info); +int print_system_info(const SystemInfo* info, const PrintConfig* print_config); +int print_system_nonced_transaction_sentinel(const SystemInfo* info, + const PrintConfig* print_config); +int print_system_create_account_info(const char* primary_title, + const SystemCreateAccountInfo* info, + const PrintConfig* print_config); +int print_system_create_account_with_seed_info(const char* primary_title, + const SystemCreateAccountWithSeedInfo* info, + const PrintConfig* print_config); +int print_system_initialize_nonce_info(const char* primary_title, + const SystemInitializeNonceInfo* info, + const PrintConfig* print_config); +int print_system_allocate_with_seed_info(const char* primary_title, + const SystemAllocateWithSeedInfo* info, + const PrintConfig* print_config); diff --git a/libsol/system_instruction_test.c b/libsol/system_instruction_test.c index 397758b7..5c541339 100644 --- a/libsol/system_instruction_test.c +++ b/libsol/system_instruction_test.c @@ -6,25 +6,16 @@ #include void test_parse_system_transfer_instructions() { - uint8_t message[] = { - 1, 0, 1, - 3, - 171, 88, 202, 32, 185, 160, 182, 116, 130, 185, 73, 48, 13, 216, 170, 71, - 172, 195, 165, 123, 87, 70, 130, 219, 5, 157, 240, 187, 26, 191, 158, 218, - 204, 241, 115, 109, 41, 173, 110, 48, 24, 113, 210, 213, 163, 78, 1, 112, - 146, 114, 235, 220, 96, 185, 184, 85, 163, 27, 124, 48, 54, 250, 233, 54, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1, - 2, - 2, - 0, 1, - 12, - 2, 0, 0, 0, - 42, 0, 0, 0, 0, 0, 0, 0 - }; + uint8_t message[] = {1, 0, 1, 3, 171, 88, 202, 32, 185, 160, 182, 116, 130, 185, 73, + 48, 13, 216, 170, 71, 172, 195, 165, 123, 87, 70, 130, 219, 5, 157, + 240, 187, 26, 191, 158, 218, 204, 241, 115, 109, 41, 173, 110, 48, 24, + 113, 210, 213, 163, 78, 1, 112, 146, 114, 235, 220, 96, 185, 184, 85, + 163, 27, 124, 48, 54, 250, 233, 54, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, + 0, 1, 12, 2, 0, 0, 0, 42, 0, 0, 0, 0, 0, 0, 0}; Parser parser = {message, sizeof(message)}; MessageHeader header; assert(parse_message_header(&parser, &header) == 0); @@ -42,25 +33,16 @@ void test_parse_system_transfer_instructions() { } void test_parse_system_transfer_instructions_with_payer() { - uint8_t message[] = { - 2, 0, 1, - 3, - 204, 241, 115, 109, 41, 173, 110, 48, 24, 113, 210, 213, 163, 78, 1, 112, - 146, 114, 235, 220, 96, 185, 184, 85, 163, 27, 124, 48, 54, 250, 233, 54, - 171, 88, 202, 32, 185, 160, 182, 116, 130, 185, 73, 48, 13, 216, 170, 71, - 172, 195, 165, 123, 87, 70, 130, 219, 5, 157, 240, 187, 26, 191, 158, 218, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1, - 2, - 2, - 1, 0, - 12, - 2, 0, 0, 0, - 42, 0, 0, 0, 0, 0, 0, 0 - }; + uint8_t message[] = {2, 0, 1, 3, 204, 241, 115, 109, 41, 173, 110, 48, 24, 113, 210, + 213, 163, 78, 1, 112, 146, 114, 235, 220, 96, 185, 184, 85, 163, 27, + 124, 48, 54, 250, 233, 54, 171, 88, 202, 32, 185, 160, 182, 116, 130, + 185, 73, 48, 13, 216, 170, 71, 172, 195, 165, 123, 87, 70, 130, 219, + 5, 157, 240, 187, 26, 191, 158, 218, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, + 1, 0, 12, 2, 0, 0, 0, 42, 0, 0, 0, 0, 0, 0, 0}; Parser parser = {message, sizeof(message)}; MessageHeader header; assert(parse_message_header(&parser, &header) == 0); @@ -79,25 +61,16 @@ void test_parse_system_transfer_instructions_with_payer() { void test_parse_system_advance_nonce_account_instruction() { uint8_t message[] = { - 1, 1, 2, - 4, - 18, 67, 85, 168, 124, 173, 88, 142, 77, 171, 80, 178, 8, 218, 230, 68, - 85, 231, 39, 54, 184, 42, 162, 85, 172, 139, 54, 173, 194, 7, 64, 250, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 6, 167, 213, 23, 25, 44, 86, 142, 224, 138, 132, 95, 115, 210, 151, 136, - 207, 3, 92, 49, 69, 178, 26, 179, 68, 216, 6, 46, 169, 64, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1, - 3, - 3, - 1, 2, 0, - 4, - 4, 0, 0, 0 - }; + 1, 1, 2, 4, 18, 67, 85, 168, 124, 173, 88, 142, 77, 171, 80, 178, 8, 218, + 230, 68, 85, 231, 39, 54, 184, 42, 162, 85, 172, 139, 54, 173, 194, 7, 64, 250, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 6, 167, 213, 23, + 25, 44, 86, 142, 224, 138, 132, 95, 115, 210, 151, 136, 207, 3, 92, 49, 69, 178, + 26, 179, 68, 216, 6, 46, 169, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 3, 3, 1, 2, 0, 4, 4, 0, 0, 0}; Parser parser = {message, sizeof(message)}; PrintConfig print_config; print_config.expert_mode = true; @@ -108,34 +81,19 @@ void test_parse_system_advance_nonce_account_instruction() { assert(instruction_validate(&instruction, &print_config.header) == 0); enum SystemInstructionKind kind; - Parser instruction_parser = { instruction.data, instruction.data_length }; + Parser instruction_parser = {instruction.data, instruction.data_length}; assert(parse_system_instruction_kind(&instruction_parser, &kind) == 0); assert(kind == SystemAdvanceNonceAccount); SystemAdvanceNonceInfo info; - assert( - parse_system_advance_nonce_account_instruction( - &instruction_parser, - &instruction, &print_config.header, - &info - ) == 0 - ); + assert(parse_system_advance_nonce_account_instruction(&instruction_parser, + &instruction, + &print_config.header, + &info) == 0); size_t account_index = instruction.accounts[0]; size_t authority_index = instruction.accounts[2]; - assert( - memcmp( - info.account, - &print_config.header.pubkeys[account_index], - PUBKEY_SIZE - ) == 0 - ); - assert( - memcmp( - info.authority, - &print_config.header.pubkeys[authority_index], - PUBKEY_SIZE - ) == 0 - ); + assert(memcmp(info.account, &print_config.header.pubkeys[account_index], PUBKEY_SIZE) == 0); + assert(memcmp(info.authority, &print_config.header.pubkeys[authority_index], PUBKEY_SIZE) == 0); transaction_summary_reset(); assert(print_system_advance_nonce_account(&info, &print_config) == 0); @@ -147,20 +105,8 @@ void test_parse_system_advance_nonce_account_instruction() { SystemInfo info2; assert(parse_system_instructions(&instruction, &print_config.header, &info2) == 0); - assert( - memcmp( - info.account, - &print_config.header.pubkeys[account_index], - PUBKEY_SIZE - ) == 0 - ); - assert( - memcmp( - info.authority, - &print_config.header.pubkeys[authority_index], - PUBKEY_SIZE - ) == 0 - ); + assert(memcmp(info.account, &print_config.header.pubkeys[account_index], PUBKEY_SIZE) == 0); + assert(memcmp(info.authority, &print_config.header.pubkeys[authority_index], PUBKEY_SIZE) == 0); num_kinds = 0; transaction_summary_reset(); @@ -171,37 +117,64 @@ void test_parse_system_advance_nonce_account_instruction() { } void test_system_create_account_with_seed_instruction() { -#define FROM_PUBKEY BYTES32_BS58_2 -#define TO_PUBKEY BYTES32_BS58_3 -#define BASE_PUBKEY BYTES32_BS58_4 +#define FROM_PUBKEY BYTES32_BS58_2 +#define TO_PUBKEY BYTES32_BS58_3 +#define BASE_PUBKEY BYTES32_BS58_4 Pubkey pubkeys[3] = { - {{ FROM_PUBKEY }}, - {{ TO_PUBKEY }}, + {{FROM_PUBKEY}}, + {{TO_PUBKEY}}, }; memcpy(&pubkeys[2], &system_program_id, PUBKEY_SIZE); - Blockhash blockhash = {{ BYTES32_BS58_5 }}; + Blockhash blockhash = {{BYTES32_BS58_5}}; MessageHeader header = { - { 2, 0, 0, ARRAY_LEN(pubkeys) }, + false, + 0, + {2, 0, 0, ARRAY_LEN(pubkeys)}, pubkeys, &blockhash, 1, }; - uint8_t accounts[] = { 0, 1 }; - uint8_t ix_data[] = { - /* kind */ - 0x03, 0x00, 0x00, 0x00, - /* base */ - BASE_PUBKEY, - /* seed ("seed" as sized string) */ - 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x73, 0x65, 0x65, 0x64, - /* lamports (1) */ - 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - /* space (16) */ - 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - /* program id */ - PROGRAM_ID_STAKE - }; + uint8_t accounts[] = {0, 1}; + uint8_t ix_data[] = {/* kind */ + 0x03, + 0x00, + 0x00, + 0x00, + /* base */ + BASE_PUBKEY, + /* seed ("seed" as sized string) */ + 0x04, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x73, + 0x65, + 0x65, + 0x64, + /* lamports (1) */ + 0x01, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + /* space (16) */ + 0x10, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + /* program id */ + PROGRAM_ID_STAKE}; Instruction instruction = { 2, accounts, @@ -211,23 +184,18 @@ void test_system_create_account_with_seed_instruction() { }; /* skip kind */ - Parser parser = { - ix_data + sizeof(uint32_t), - sizeof(ix_data) - sizeof(uint32_t) - }; + Parser parser = {ix_data + sizeof(uint32_t), sizeof(ix_data) - sizeof(uint32_t)}; SystemInfo info; - assert(parse_system_create_account_with_seed_instruction( - &parser, - &instruction, - &header, - &info.create_account_with_seed - ) == 0); + assert(parse_system_create_account_with_seed_instruction(&parser, + &instruction, + &header, + &info.create_account_with_seed) == 0); SystemCreateAccountWithSeedInfo* cws_info = &info.create_account_with_seed; - Pubkey from = {{ FROM_PUBKEY }}; + Pubkey from = {{FROM_PUBKEY}}; assert(memcmp(&from, cws_info->from, PUBKEY_SIZE) == 0); - Pubkey to = {{ TO_PUBKEY }}; + Pubkey to = {{TO_PUBKEY}}; assert(memcmp(&to, cws_info->to, PUBKEY_SIZE) == 0); - Pubkey base = {{ BASE_PUBKEY }}; + Pubkey base = {{BASE_PUBKEY}}; assert(memcmp(&base, cws_info->base, PUBKEY_SIZE) == 0); SizedString* seed = &cws_info->seed; assert(strncmp("seed", seed->string, seed->length) == 0); @@ -238,25 +206,16 @@ void test_system_create_account_with_seed_instruction() { } void test_process_system_transfer() { - uint8_t message[] = { - 1, 0, 1, - 3, - 171, 88, 202, 32, 185, 160, 182, 116, 130, 185, 73, 48, 13, 216, 170, 71, - 172, 195, 165, 123, 87, 70, 130, 219, 5, 157, 240, 187, 26, 191, 158, 218, - 204, 241, 115, 109, 41, 173, 110, 48, 24, 113, 210, 213, 163, 78, 1, 112, - 146, 114, 235, 220, 96, 185, 184, 85, 163, 27, 124, 48, 54, 250, 233, 54, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1, - 2, - 2, - 0, 1, - 12, - 2, 0, 0, 0, - 42, 0, 0, 0, 0, 0, 0, 0 - }; + uint8_t message[] = {1, 0, 1, 3, 171, 88, 202, 32, 185, 160, 182, 116, 130, 185, 73, + 48, 13, 216, 170, 71, 172, 195, 165, 123, 87, 70, 130, 219, 5, 157, + 240, 187, 26, 191, 158, 218, 204, 241, 115, 109, 41, 173, 110, 48, 24, + 113, 210, 213, 163, 78, 1, 112, 146, 114, 235, 220, 96, 185, 184, 85, + 163, 27, 124, 48, 54, 250, 233, 54, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, + 0, 1, 12, 2, 0, 0, 0, 42, 0, 0, 0, 0, 0, 0, 0}; Parser parser = {message, sizeof(message)}; PrintConfig print_config; print_config.expert_mode = true; diff --git a/libsol/token_info.c b/libsol/token_info.c index d7d72876..026a5d37 100644 --- a/libsol/token_info.c +++ b/libsol/token_info.c @@ -3,21 +3,21 @@ #include "util.h" struct token_info { - const Pubkey* mint_address; - const char* symbol; + const Pubkey* mint_address; + const char* symbol; }; const struct token_info token_infos[] = { - { &spl_token_program_id, "WSOL" }, + {&spl_token_program_id, "WSOL"}, }; const char* get_token_symbol(const Pubkey* mint_address) { - size_t i; - for (i = 0; i < ARRAY_LEN(token_infos); i++) { - const struct token_info* ti = &token_infos[i]; - if (memcmp(ti->mint_address, mint_address, PUBKEY_SIZE) == 0) { - return ti->symbol; + size_t i; + for (i = 0; i < ARRAY_LEN(token_infos); i++) { + const struct token_info* ti = &token_infos[i]; + if (memcmp(ti->mint_address, mint_address, PUBKEY_SIZE) == 0) { + return ti->symbol; + } } - } - return "???"; + return "???"; } diff --git a/libsol/transaction_printers.c b/libsol/transaction_printers.c index 61af85ac..7fab1aaf 100644 --- a/libsol/transaction_printers.c +++ b/libsol/transaction_printers.c @@ -5,269 +5,184 @@ #include "transaction_printers.h" #include "util.h" +const InstructionBrief nonce_brief[] = { + SYSTEM_IX_BRIEF(SystemAdvanceNonceAccount), +}; +#define is_advance_nonce_account(infos) instruction_info_matches_brief(infos, nonce_brief) + const InstructionBrief create_stake_account_brief[] = { SYSTEM_IX_BRIEF(SystemCreateAccount), STAKE_IX_BRIEF(StakeInitialize), }; -#define is_create_stake_account(infos, infos_length)\ - instruction_infos_match_briefs( \ - infos, \ - create_stake_account_brief, \ - infos_length \ - ) +#define is_create_stake_account(infos, infos_length) \ + instruction_infos_match_briefs(infos, create_stake_account_brief, infos_length) const InstructionBrief create_stake_account_checked_brief[] = { SYSTEM_IX_BRIEF(SystemCreateAccount), STAKE_IX_BRIEF(StakeInitializeChecked), }; -#define is_create_stake_account_checked(infos, infos_length)\ - instruction_infos_match_briefs( \ - infos, \ - create_stake_account_checked_brief, \ - infos_length \ - ) +#define is_create_stake_account_checked(infos, infos_length) \ + instruction_infos_match_briefs(infos, create_stake_account_checked_brief, infos_length) const InstructionBrief create_stake_account_with_seed_brief[] = { SYSTEM_IX_BRIEF(SystemCreateAccountWithSeed), STAKE_IX_BRIEF(StakeInitialize), }; -#define is_create_stake_account_with_seed(infos, infos_length) \ - instruction_infos_match_briefs( \ - infos, \ - create_stake_account_with_seed_brief, \ - infos_length \ - ) +#define is_create_stake_account_with_seed(infos, infos_length) \ + instruction_infos_match_briefs(infos, create_stake_account_with_seed_brief, infos_length) const InstructionBrief create_stake_account_with_seed_checked_brief[] = { SYSTEM_IX_BRIEF(SystemCreateAccountWithSeed), STAKE_IX_BRIEF(StakeInitializeChecked), }; -#define is_create_stake_account_with_seed_checked(infos, infos_length) \ - instruction_infos_match_briefs( \ - infos, \ - create_stake_account_with_seed_checked_brief, \ - infos_length \ - ) +#define is_create_stake_account_with_seed_checked(infos, infos_length) \ + instruction_infos_match_briefs(infos, \ + create_stake_account_with_seed_checked_brief, \ + infos_length) const InstructionBrief create_stake_account_and_delegate_brief[] = { SYSTEM_IX_BRIEF(SystemCreateAccount), STAKE_IX_BRIEF(StakeInitialize), STAKE_IX_BRIEF(StakeDelegate), }; -#define is_create_stake_account_and_delegate(infos, infos_length) \ - instruction_infos_match_briefs( \ - infos, \ - create_stake_account_and_delegate_brief, \ - infos_length \ - ) +#define is_create_stake_account_and_delegate(infos, infos_length) \ + instruction_infos_match_briefs(infos, create_stake_account_and_delegate_brief, infos_length) const InstructionBrief create_stake_account_with_seed_and_delegate_brief[] = { SYSTEM_IX_BRIEF(SystemCreateAccountWithSeed), STAKE_IX_BRIEF(StakeInitialize), STAKE_IX_BRIEF(StakeDelegate), }; -#define is_create_stake_account_with_seed_and_delegate(infos, infos_length) \ - instruction_infos_match_briefs( \ - infos, \ - create_stake_account_with_seed_and_delegate_brief, \ - infos_length \ - ) +#define is_create_stake_account_with_seed_and_delegate(infos, infos_length) \ + instruction_infos_match_briefs(infos, \ + create_stake_account_with_seed_and_delegate_brief, \ + infos_length) const InstructionBrief stake_split_brief_v1_1[] = { SYSTEM_IX_BRIEF(SystemAllocate), SYSTEM_IX_BRIEF(SystemAssign), STAKE_IX_BRIEF(StakeSplit), }; -#define is_stake_split_v1_1(infos, infos_length)\ - instruction_infos_match_briefs( \ - infos, \ - stake_split_brief_v1_1, \ - infos_length \ - ) +#define is_stake_split_v1_1(infos, infos_length) \ + instruction_infos_match_briefs(infos, stake_split_brief_v1_1, infos_length) const InstructionBrief stake_split_with_seed_brief_v1_1[] = { SYSTEM_IX_BRIEF(SystemAllocateWithSeed), STAKE_IX_BRIEF(StakeSplit), }; -#define is_stake_split_with_seed_v1_1(infos, infos_length) \ - instruction_infos_match_briefs( \ - infos, \ - stake_split_with_seed_brief_v1_1, \ - infos_length \ - ) +#define is_stake_split_with_seed_v1_1(infos, infos_length) \ + instruction_infos_match_briefs(infos, stake_split_with_seed_brief_v1_1, infos_length) const InstructionBrief stake_split_brief_v1_2[] = { SYSTEM_IX_BRIEF(SystemCreateAccount), STAKE_IX_BRIEF(StakeSplit), }; -#define is_stake_split_v1_2(infos, infos_length)\ - instruction_infos_match_briefs( \ - infos, \ - stake_split_brief_v1_2, \ - infos_length \ - ) +#define is_stake_split_v1_2(infos, infos_length) \ + instruction_infos_match_briefs(infos, stake_split_brief_v1_2, infos_length) const InstructionBrief stake_split_with_seed_brief_v1_2[] = { SYSTEM_IX_BRIEF(SystemCreateAccountWithSeed), STAKE_IX_BRIEF(StakeSplit), }; -#define is_stake_split_with_seed_v1_2(infos, infos_length) \ - instruction_infos_match_briefs( \ - infos, \ - stake_split_with_seed_brief_v1_2, \ - infos_length \ - ) +#define is_stake_split_with_seed_v1_2(infos, infos_length) \ + instruction_infos_match_briefs(infos, stake_split_with_seed_brief_v1_2, infos_length) const InstructionBrief stake_authorize_both_brief[] = { STAKE_IX_BRIEF(StakeAuthorize), STAKE_IX_BRIEF(StakeAuthorize), }; -#define is_stake_authorize_both(infos, infos_length)\ - instruction_infos_match_briefs( \ - infos, \ - stake_authorize_both_brief, \ - infos_length \ - ) +#define is_stake_authorize_both(infos, infos_length) \ + instruction_infos_match_briefs(infos, stake_authorize_both_brief, infos_length) const InstructionBrief stake_authorize_checked_both_brief[] = { STAKE_IX_BRIEF(StakeAuthorizeChecked), STAKE_IX_BRIEF(StakeAuthorizeChecked), }; -#define is_stake_authorize_checked_both(infos, infos_length)\ - instruction_infos_match_briefs( \ - infos, \ - stake_authorize_checked_both_brief, \ - infos_length \ - ) +#define is_stake_authorize_checked_both(infos, infos_length) \ + instruction_infos_match_briefs(infos, stake_authorize_checked_both_brief, infos_length) const InstructionBrief create_nonce_account_brief[] = { SYSTEM_IX_BRIEF(SystemCreateAccount), SYSTEM_IX_BRIEF(SystemInitializeNonceAccount), }; -#define is_create_nonce_account(infos, infos_length) \ - instruction_infos_match_briefs( \ - infos, \ - create_nonce_account_brief, \ - infos_length \ - ) +#define is_create_nonce_account(infos, infos_length) \ + instruction_infos_match_briefs(infos, create_nonce_account_brief, infos_length) const InstructionBrief create_nonce_account_with_seed_brief[] = { SYSTEM_IX_BRIEF(SystemCreateAccountWithSeed), SYSTEM_IX_BRIEF(SystemInitializeNonceAccount), }; -#define is_create_nonce_account_with_seed(infos, infos_length) \ - instruction_infos_match_briefs( \ - infos, \ - create_nonce_account_with_seed_brief, \ - infos_length \ - ) +#define is_create_nonce_account_with_seed(infos, infos_length) \ + instruction_infos_match_briefs(infos, create_nonce_account_with_seed_brief, infos_length) const InstructionBrief create_vote_account_brief[] = { SYSTEM_IX_BRIEF(SystemCreateAccount), VOTE_IX_BRIEF(VoteInitialize), }; #define is_create_vote_account(infos, infos_length) \ - instruction_infos_match_briefs( \ - infos, \ - create_vote_account_brief, \ - infos_length \ - ) + instruction_infos_match_briefs(infos, create_vote_account_brief, infos_length) const InstructionBrief create_vote_account_with_seed_brief[] = { SYSTEM_IX_BRIEF(SystemCreateAccountWithSeed), VOTE_IX_BRIEF(VoteInitialize), }; -#define is_create_vote_account_with_seed(infos, infos_length) \ - instruction_infos_match_briefs( \ - infos, \ - create_vote_account_with_seed_brief, \ - infos_length \ - ) +#define is_create_vote_account_with_seed(infos, infos_length) \ + instruction_infos_match_briefs(infos, create_vote_account_with_seed_brief, infos_length) const InstructionBrief vote_authorize_both_brief[] = { VOTE_IX_BRIEF(VoteAuthorize), VOTE_IX_BRIEF(VoteAuthorize), }; #define is_vote_authorize_both(infos, infos_length) \ - instruction_infos_match_briefs( \ - infos, \ - vote_authorize_both_brief, \ - infos_length \ - ) + instruction_infos_match_briefs(infos, vote_authorize_both_brief, infos_length) const InstructionBrief vote_authorize_checked_both_brief[] = { VOTE_IX_BRIEF(VoteAuthorizeChecked), VOTE_IX_BRIEF(VoteAuthorizeChecked), }; #define is_vote_authorize_checked_both(infos, infos_length) \ - instruction_infos_match_briefs( \ - infos, \ - vote_authorize_checked_both_brief, \ - infos_length \ - ) + instruction_infos_match_briefs(infos, vote_authorize_checked_both_brief, infos_length) const InstructionBrief spl_token_create_mint_brief[] = { SYSTEM_IX_BRIEF(SystemCreateAccount), SPL_TOKEN_IX_BRIEF(SplTokenKind(InitializeMint)), }; -#define is_spl_token_create_mint(infos, infos_length) \ - instruction_infos_match_briefs( \ - infos, \ - spl_token_create_mint_brief, \ - infos_length \ - ) +#define is_spl_token_create_mint(infos, infos_length) \ + instruction_infos_match_briefs(infos, spl_token_create_mint_brief, infos_length) const InstructionBrief spl_token_create_account_brief[] = { SYSTEM_IX_BRIEF(SystemCreateAccount), SPL_TOKEN_IX_BRIEF(SplTokenKind(InitializeAccount)), }; -#define is_spl_token_create_account(infos, infos_length) \ - instruction_infos_match_briefs( \ - infos, \ - spl_token_create_account_brief, \ - infos_length \ - ) +#define is_spl_token_create_account(infos, infos_length) \ + instruction_infos_match_briefs(infos, spl_token_create_account_brief, infos_length) const InstructionBrief spl_token_create_account2_brief[] = { SYSTEM_IX_BRIEF(SystemCreateAccount), SPL_TOKEN_IX_BRIEF(SplTokenKind(InitializeAccount2)), }; -#define is_spl_token_create_account2(infos, infos_length) \ - instruction_infos_match_briefs( \ - infos, \ - spl_token_create_account2_brief, \ - infos_length \ - ) +#define is_spl_token_create_account2(infos, infos_length) \ + instruction_infos_match_briefs(infos, spl_token_create_account2_brief, infos_length) const InstructionBrief spl_token_create_multisig_brief[] = { SYSTEM_IX_BRIEF(SystemCreateAccount), SPL_TOKEN_IX_BRIEF(SplTokenKind(InitializeMultisig)), }; -#define is_spl_token_create_multisig(infos, infos_length) \ - instruction_infos_match_briefs( \ - infos, \ - spl_token_create_multisig_brief, \ - infos_length \ - ) - -const InstructionBrief -spl_associated_token_account_create_with_transfer_brief[] = { +#define is_spl_token_create_multisig(infos, infos_length) \ + instruction_infos_match_briefs(infos, spl_token_create_multisig_brief, infos_length) + +const InstructionBrief spl_associated_token_account_create_with_transfer_brief[] = { SPL_ASSOCIATED_TOKEN_ACCOUNT_IX_BRIEF, SPL_TOKEN_IX_BRIEF(SplTokenKind(TransferChecked)), }; -#define \ -is_spl_associated_token_account_create_with_transfer(infos, infos_length) \ - instruction_infos_match_briefs( \ - infos, \ - spl_associated_token_account_create_with_transfer_brief, \ - infos_length \ - ) - -static int print_create_stake_account( - const PrintConfig* print_config, - InstructionInfo* const * infos, - size_t infos_length -) { +#define is_spl_associated_token_account_create_with_transfer(infos, infos_length) \ + instruction_infos_match_briefs(infos, \ + spl_associated_token_account_create_with_transfer_brief, \ + infos_length) + +static int print_create_stake_account(const PrintConfig* print_config, + InstructionInfo* const* infos, + size_t infos_length) { UNUSED(infos_length); const SystemCreateAccountInfo* ca_info = &infos[0]->system.create_account; @@ -282,33 +197,26 @@ static int print_create_stake_account( return 0; } -static int print_create_stake_account_with_seed( - const PrintConfig* print_config, - InstructionInfo* const * infos, - size_t infos_length -) { +static int print_create_stake_account_with_seed(const PrintConfig* print_config, + InstructionInfo* const* infos, + size_t infos_length) { UNUSED(infos_length); - const SystemCreateAccountWithSeedInfo* cws_info = - &infos[0]->system.create_account_with_seed; + const SystemCreateAccountWithSeedInfo* cws_info = &infos[0]->system.create_account_with_seed; const StakeInitializeInfo* si_info = &infos[1]->stake.initialize; SummaryItem* item = transaction_summary_primary_item(); summary_item_set_pubkey(item, "Create stake acct", cws_info->to); - BAIL_IF( - print_system_create_account_with_seed_info(NULL, cws_info, print_config) - ); + BAIL_IF(print_system_create_account_with_seed_info(NULL, cws_info, print_config)); BAIL_IF(print_stake_initialize_info(NULL, si_info, print_config)); return 0; } -static int print_create_stake_account_and_delegate( - const PrintConfig* print_config, - InstructionInfo* const * infos, - size_t infos_length -) { +static int print_create_stake_account_and_delegate(const PrintConfig* print_config, + InstructionInfo* const* infos, + size_t infos_length) { UNUSED(infos_length); const SystemCreateAccountInfo* ca_info = &infos[0]->system.create_account; @@ -325,51 +233,43 @@ static int print_create_stake_account_and_delegate( return 0; } -static int print_create_stake_account_with_seed_and_delegate( - const PrintConfig* print_config, - InstructionInfo* const * infos, - size_t infos_length -) { +static int print_create_stake_account_with_seed_and_delegate(const PrintConfig* print_config, + InstructionInfo* const* infos, + size_t infos_length) { UNUSED(infos_length); - const SystemCreateAccountWithSeedInfo* cws_info = - &infos[0]->system.create_account_with_seed; + const SystemCreateAccountWithSeedInfo* cws_info = &infos[0]->system.create_account_with_seed; const StakeInitializeInfo* si_info = &infos[1]->stake.initialize; const StakeDelegateInfo* sd_info = &infos[2]->stake.delegate_stake; SummaryItem* item = transaction_summary_primary_item(); summary_item_set_pubkey(item, "Delegate from", cws_info->to); - BAIL_IF( - print_system_create_account_with_seed_info(NULL, cws_info, print_config) - ); + BAIL_IF(print_system_create_account_with_seed_info(NULL, cws_info, print_config)); BAIL_IF(print_stake_initialize_info(NULL, si_info, print_config)); BAIL_IF(print_delegate_stake_info(NULL, sd_info, print_config)); return 0; } -static int print_stake_split_with_seed( - const PrintConfig* print_config, - InstructionInfo* const * infos, - size_t infos_length, - bool legacy -) { +static int print_stake_split_with_seed(const PrintConfig* print_config, + InstructionInfo* const* infos, + size_t infos_length, + bool legacy) { UNUSED(infos_length); const Pubkey* base = NULL; const SizedString* seed = NULL; if (legacy) { - const SystemAllocateWithSeedInfo* aws_info = - &infos[0]->system.allocate_with_seed; - base = aws_info->base; - seed = &aws_info->seed; + const SystemAllocateWithSeedInfo* aws_info = &infos[0]->system.allocate_with_seed; + base = aws_info->base; + seed = &aws_info->seed; } else { - const SystemCreateAccountWithSeedInfo* cws_info = - &infos[0]->system.create_account_with_seed; - base = cws_info->base; - seed = &cws_info->seed; + const SystemCreateAccountWithSeedInfo* cws_info = + &infos[0]->system.create_account_with_seed; + base = cws_info->base; + seed = &cws_info->seed; } const StakeSplitInfo* ss_info = &infos[1]->stake.split; @@ -388,11 +288,9 @@ static int print_stake_split_with_seed( return 0; } -static int print_stake_authorize_both( - const PrintConfig* print_config, - InstructionInfo* const * infos, - size_t infos_length -) { +static int print_stake_authorize_both(const PrintConfig* print_config, + InstructionInfo* const* infos, + size_t infos_length) { UNUSED(infos_length); const StakeAuthorizeInfo* staker_info = &infos[0]->stake.authorize; @@ -408,34 +306,18 @@ static int print_stake_authorize_both( if (staker_info->new_authority == withdrawer_info->new_authority) { item = transaction_summary_general_item(); - summary_item_set_pubkey( - item, - "New authorities", - staker_info->new_authority - ); + summary_item_set_pubkey(item, "New authorities", staker_info->new_authority); } else { item = transaction_summary_general_item(); - summary_item_set_pubkey( - item, - "New stake auth", - staker_info->new_authority - ); + summary_item_set_pubkey(item, "New stake auth", staker_info->new_authority); item = transaction_summary_general_item(); - summary_item_set_pubkey( - item, - "New withdraw auth", - withdrawer_info->new_authority - ); + summary_item_set_pubkey(item, "New withdraw auth", withdrawer_info->new_authority); } if (withdrawer_info->custodian) { item = transaction_summary_general_item(); - summary_item_set_pubkey( - item, - "Custodian", - withdrawer_info->custodian - ); + summary_item_set_pubkey(item, "Custodian", withdrawer_info->custodian); } if (print_config_show_authority(print_config, withdrawer_info->authority)) { @@ -446,16 +328,13 @@ static int print_stake_authorize_both( return 0; } -static int print_create_nonce_account( - const PrintConfig* print_config, - InstructionInfo* const * infos, - size_t infos_length -) { +static int print_create_nonce_account(const PrintConfig* print_config, + InstructionInfo* const* infos, + size_t infos_length) { UNUSED(infos_length); const SystemCreateAccountInfo* ca_info = &infos[0]->system.create_account; - const SystemInitializeNonceInfo* ni_info = - &infos[1]->system.initialize_nonce; + const SystemInitializeNonceInfo* ni_info = &infos[1]->system.initialize_nonce; SummaryItem* item = transaction_summary_primary_item(); summary_item_set_pubkey(item, "Create nonce acct", ca_info->to); @@ -466,17 +345,13 @@ static int print_create_nonce_account( return 0; } -static int print_create_nonce_account_with_seed( - const PrintConfig* print_config, - InstructionInfo* const * infos, - size_t infos_length -) { +static int print_create_nonce_account_with_seed(const PrintConfig* print_config, + InstructionInfo* const* infos, + size_t infos_length) { UNUSED(infos_length); - const SystemCreateAccountWithSeedInfo* ca_info = - &infos[0]->system.create_account_with_seed; - const SystemInitializeNonceInfo* ni_info = - &infos[1]->system.initialize_nonce; + const SystemCreateAccountWithSeedInfo* ca_info = &infos[0]->system.create_account_with_seed; + const SystemInitializeNonceInfo* ni_info = &infos[1]->system.initialize_nonce; SummaryItem* item = transaction_summary_primary_item(); summary_item_set_pubkey(item, "Create nonce acct", ca_info->to); @@ -487,11 +362,9 @@ static int print_create_nonce_account_with_seed( return 0; } -static int print_create_vote_account( - const PrintConfig* print_config, - InstructionInfo* const * infos, - size_t infos_length -) { +static int print_create_vote_account(const PrintConfig* print_config, + InstructionInfo* const* infos, + size_t infos_length) { UNUSED(infos_length); const SystemCreateAccountInfo* ca_info = &infos[0]->system.create_account; @@ -506,15 +379,12 @@ static int print_create_vote_account( return 0; } -static int print_create_vote_account_with_seed( - const PrintConfig* print_config, - InstructionInfo* const * infos, - size_t infos_length -) { +static int print_create_vote_account_with_seed(const PrintConfig* print_config, + InstructionInfo* const* infos, + size_t infos_length) { UNUSED(infos_length); - const SystemCreateAccountWithSeedInfo* ca_info = - &infos[0]->system.create_account_with_seed; + const SystemCreateAccountWithSeedInfo* ca_info = &infos[0]->system.create_account_with_seed; const VoteInitializeInfo* vi_info = &infos[1]->vote.initialize; SummaryItem* item = transaction_summary_primary_item(); @@ -526,11 +396,9 @@ static int print_create_vote_account_with_seed( return 0; } -static int print_vote_authorize_both( - const PrintConfig* print_config, - InstructionInfo* const * infos, - size_t infos_length -) { +static int print_vote_authorize_both(const PrintConfig* print_config, + InstructionInfo* const* infos, + size_t infos_length) { UNUSED(infos_length); const VoteAuthorizeInfo* voter_info = &infos[0]->vote.authorize; @@ -546,25 +414,13 @@ static int print_vote_authorize_both( if (voter_info->new_authority == withdrawer_info->new_authority) { item = transaction_summary_general_item(); - summary_item_set_pubkey( - item, - "New authorities", - voter_info->new_authority - ); + summary_item_set_pubkey(item, "New authorities", voter_info->new_authority); } else { item = transaction_summary_general_item(); - summary_item_set_pubkey( - item, - "New vote auth", - voter_info->new_authority - ); + summary_item_set_pubkey(item, "New vote auth", voter_info->new_authority); item = transaction_summary_general_item(); - summary_item_set_pubkey( - item, - "New withdraw auth", - withdrawer_info->new_authority - ); + summary_item_set_pubkey(item, "New withdraw auth", withdrawer_info->new_authority); } if (print_config_show_authority(print_config, withdrawer_info->authority)) { @@ -575,16 +431,13 @@ static int print_vote_authorize_both( return 0; } -static int print_spl_token_create_mint( - const PrintConfig* print_config, - InstructionInfo* const * infos, - size_t infos_length -) { +static int print_spl_token_create_mint(const PrintConfig* print_config, + InstructionInfo* const* infos, + size_t infos_length) { UNUSED(infos_length); const SystemCreateAccountInfo* ca_info = &infos[0]->system.create_account; - const SplTokenInitializeMintInfo* im_info = - &infos[1]->spl_token.initialize_mint; + const SplTokenInitializeMintInfo* im_info = &infos[1]->spl_token.initialize_mint; SummaryItem* item = transaction_summary_primary_item(); summary_item_set_pubkey(item, "Create token mint", im_info->mint_account); @@ -611,16 +464,13 @@ static int print_spl_token_create_mint( return 0; } -static int print_spl_token_create_account( - const PrintConfig* print_config, - InstructionInfo* const * infos, - size_t infos_length -) { +static int print_spl_token_create_account(const PrintConfig* print_config, + InstructionInfo* const* infos, + size_t infos_length) { UNUSED(infos_length); const SystemCreateAccountInfo* ca_info = &infos[0]->system.create_account; - const SplTokenInitializeAccountInfo* ia_info = - &infos[1]->spl_token.initialize_account; + const SplTokenInitializeAccountInfo* ia_info = &infos[1]->spl_token.initialize_account; SummaryItem* item = transaction_summary_primary_item(); summary_item_set_pubkey(item, "Create token acct", ia_info->token_account); @@ -642,16 +492,13 @@ static int print_spl_token_create_account( return 0; } -static int print_spl_token_create_multisig( - const PrintConfig* print_config, - InstructionInfo* const * infos, - size_t infos_length -) { +static int print_spl_token_create_multisig(const PrintConfig* print_config, + InstructionInfo* const* infos, + size_t infos_length) { UNUSED(infos_length); const SystemCreateAccountInfo* ca_info = &infos[0]->system.create_account; - const SplTokenInitializeMultisigInfo* im_info = - &infos[1]->spl_token.initialize_multisig; + const SplTokenInitializeMultisigInfo* im_info = &infos[1]->spl_token.initialize_multisig; SummaryItem* item = transaction_summary_primary_item(); summary_item_set_pubkey(item, "Create multisig", im_info->multisig_account); @@ -670,11 +517,9 @@ static int print_spl_token_create_multisig( return 0; } -static int print_spl_associated_token_account_create_with_transfer( - const PrintConfig* print_config, - InstructionInfo* const * infos, - size_t infos_length -) { +static int print_spl_associated_token_account_create_with_transfer(const PrintConfig* print_config, + InstructionInfo* const* infos, + size_t infos_length) { UNUSED(infos_length); const SplAssociatedTokenAccountCreateInfo* c_info = @@ -687,151 +532,107 @@ static int print_spl_associated_token_account_create_with_transfer( return 0; } -int print_transaction( - const PrintConfig* print_config, - InstructionInfo* const * infos, - size_t infos_length -) { - if (infos_length > 1) { - InstructionInfo* display_info = infos[0]; - InstructionBrief nonce_brief = - SYSTEM_IX_BRIEF(SystemAdvanceNonceAccount); - if (instruction_info_matches_brief(display_info, &nonce_brief)) { - print_system_nonced_transaction_sentinel(&display_info->system, print_config); - infos++; - infos_length--; - } - } - +static int print_transaction_nonce_processed(const PrintConfig* print_config, + InstructionInfo* const* infos, + size_t infos_length) { switch (infos_length) { - case 1: { - InstructionInfo* display_info = infos[0]; - switch (display_info->kind) { + case 1: + switch (infos[0]->kind) { case ProgramIdSystem: - return print_system_info(&display_info->system, print_config); + return print_system_info(&(infos[0]->system), print_config); case ProgramIdStake: - return print_stake_info(&display_info->stake, print_config); + return print_stake_info(&(infos[0]->stake), print_config); case ProgramIdVote: - return print_vote_info(&display_info->vote, print_config); + return print_vote_info(&(infos[0]->vote), print_config); case ProgramIdSplToken: - return print_spl_token_info(&display_info->spl_token, print_config); + return print_spl_token_info(&(infos[0]->spl_token), print_config); case ProgramIdSplAssociatedTokenAccount: return print_spl_associated_token_account_info( - &display_info->spl_associated_token_account, - print_config - ); + &(infos[0]->spl_associated_token_account), + print_config); case ProgramIdSerumAssertOwner: case ProgramIdSplMemo: case ProgramIdUnknown: break; } break; - } - case 2: { - if (is_create_stake_account(infos, infos_length) - || is_create_stake_account_checked(infos, infos_length)) { + + case 2: + if (is_create_stake_account(infos, infos_length) || + is_create_stake_account_checked(infos, infos_length)) { return print_create_stake_account(print_config, infos, infos_length); - } else if (is_create_stake_account_with_seed(infos, infos_length) - || is_create_stake_account_with_seed_checked(infos, infos_length)) { - return print_create_stake_account_with_seed( - print_config, - infos, - infos_length - ); + } else if (is_create_stake_account_with_seed(infos, infos_length) || + is_create_stake_account_with_seed_checked(infos, infos_length)) { + return print_create_stake_account_with_seed(print_config, infos, infos_length); } else if (is_create_nonce_account(infos, infos_length)) { return print_create_nonce_account(print_config, infos, infos_length); } else if (is_create_nonce_account_with_seed(infos, infos_length)) { - return print_create_nonce_account_with_seed( - print_config, - infos, - infos_length - ); + return print_create_nonce_account_with_seed(print_config, infos, infos_length); } else if (is_create_vote_account(infos, infos_length)) { return print_create_vote_account(print_config, infos, infos_length); } else if (is_create_vote_account_with_seed(infos, infos_length)) { - return print_create_vote_account_with_seed( - print_config, - infos, - infos_length - ); - } else if (is_stake_authorize_both(infos, infos_length) - || is_stake_authorize_checked_both(infos, infos_length)) { + return print_create_vote_account_with_seed(print_config, infos, infos_length); + } else if (is_stake_authorize_both(infos, infos_length) || + is_stake_authorize_checked_both(infos, infos_length)) { return print_stake_authorize_both(print_config, infos, infos_length); - } else if (is_vote_authorize_both(infos, infos_length) - || is_vote_authorize_checked_both(infos, infos_length)) { + } else if (is_vote_authorize_both(infos, infos_length) || + is_vote_authorize_checked_both(infos, infos_length)) { return print_vote_authorize_both(print_config, infos, infos_length); } else if (is_stake_split_with_seed_v1_1(infos, infos_length)) { - return print_stake_split_with_seed( - print_config, - infos, - infos_length, - true - ); + return print_stake_split_with_seed(print_config, infos, infos_length, true); } else if (is_stake_split_v1_2(infos, infos_length)) { // System create account is issued with zero lamports in this // case, so it has no interesting info to add. Print stake // split as if it were a single instruction return print_stake_info(&infos[1]->stake, print_config); } else if (is_stake_split_with_seed_v1_2(infos, infos_length)) { - return print_stake_split_with_seed( - print_config, - infos, - infos_length, - false - ); + return print_stake_split_with_seed(print_config, infos, infos_length, false); } else if (is_spl_token_create_mint(infos, infos_length)) { return print_spl_token_create_mint(print_config, infos, infos_length); - } else if (is_spl_token_create_account(infos, infos_length) - || is_spl_token_create_account2(infos, infos_length) - ) { - return print_spl_token_create_account( - print_config, - infos, - infos_length - ); + } else if (is_spl_token_create_account(infos, infos_length) || + is_spl_token_create_account2(infos, infos_length)) { + return print_spl_token_create_account(print_config, infos, infos_length); } else if (is_spl_token_create_multisig(infos, infos_length)) { - return print_spl_token_create_multisig( - print_config, - infos, - infos_length - ); - } else if (is_spl_associated_token_account_create_with_transfer( - infos, - infos_length - )) { - return print_spl_associated_token_account_create_with_transfer( - print_config, - infos, - infos_length - ); + return print_spl_token_create_multisig(print_config, infos, infos_length); + } else if (is_spl_associated_token_account_create_with_transfer(infos, infos_length)) { + return print_spl_associated_token_account_create_with_transfer(print_config, + infos, + infos_length); } break; - } - case 3: { + + case 3: if (is_create_stake_account_and_delegate(infos, infos_length)) { - return print_create_stake_account_and_delegate( - print_config, - infos, - infos_length - ); - } else if ( - is_create_stake_account_with_seed_and_delegate(infos, infos_length) - ) { - return print_create_stake_account_with_seed_and_delegate( - print_config, - infos, - infos_length - ); + return print_create_stake_account_and_delegate(print_config, infos, infos_length); + } else if (is_create_stake_account_with_seed_and_delegate(infos, infos_length)) { + return print_create_stake_account_with_seed_and_delegate(print_config, + infos, + infos_length); } else if (is_stake_split_v1_1(infos, infos_length)) { // System allocate/assign have no interesting info, print // stake split as if it were a single instruction return print_stake_info(&infos[2]->stake, print_config); } break; - } + default: break; } return 1; } + +int print_transaction(const PrintConfig* print_config, + InstructionInfo* const* infos, + size_t infos_length) { + // Additional nonce info might be present at first position of in info list + if ((infos_length > 1) && is_advance_nonce_account(infos[0])) { + const InstructionInfo* nonce_info = infos[0]; + print_system_nonced_transaction_sentinel(&(nonce_info->system), print_config); + // offset parameters given to print_transaction_nonce_processed() + infos++; + infos_length--; + } + + return print_transaction_nonce_processed(print_config, infos, infos_length); +} diff --git a/libsol/transaction_printers.h b/libsol/transaction_printers.h index 9672573a..c8eb41c9 100644 --- a/libsol/transaction_printers.h +++ b/libsol/transaction_printers.h @@ -2,8 +2,6 @@ #include "sol/print_config.h" -int print_transaction( - const PrintConfig* print_config, - InstructionInfo* const * infos, - size_t infos_length -); +int print_transaction(const PrintConfig* print_config, + InstructionInfo* const* infos, + size_t infos_length); diff --git a/libsol/transaction_summary.c b/libsol/transaction_summary.c index ba0122fe..a30c78a9 100644 --- a/libsol/transaction_summary.c +++ b/libsol/transaction_summary.c @@ -18,23 +18,17 @@ struct SummaryItem { }; }; -void summary_item_set_amount( - SummaryItem* item, - const char* title, - uint64_t value -) { +void summary_item_set_amount(SummaryItem* item, const char* title, uint64_t value) { item->kind = SummaryItemAmount; item->title = title; item->u64 = value; } -void summary_item_set_token_amount( - SummaryItem* item, - const char* title, - uint64_t value, - const char* symbol, - uint8_t decimals -) { +void summary_item_set_token_amount(SummaryItem* item, + const char* title, + uint64_t value, + const char* symbol, + uint8_t decimals) { item->kind = SummaryItemTokenAmount; item->title = title; item->token_amount.value = value; @@ -42,72 +36,44 @@ void summary_item_set_token_amount( item->token_amount.decimals = decimals; } -void summary_item_set_i64( - SummaryItem* item, - const char* title, - int64_t value -) { +void summary_item_set_i64(SummaryItem* item, const char* title, int64_t value) { item->kind = SummaryItemI64; item->title = title; item->i64 = value; } -void summary_item_set_u64( - SummaryItem* item, - const char* title, - uint64_t value -) { +void summary_item_set_u64(SummaryItem* item, const char* title, uint64_t value) { item->kind = SummaryItemU64; item->title = title; item->u64 = value; } -void summary_item_set_pubkey( - SummaryItem* item, - const char* title, - const Pubkey* value -) { +void summary_item_set_pubkey(SummaryItem* item, const char* title, const Pubkey* value) { item->kind = SummaryItemPubkey; item->title = title; item->pubkey = value; } -void summary_item_set_hash( - SummaryItem* item, - const char* title, - const Hash* value -) { +void summary_item_set_hash(SummaryItem* item, const char* title, const Hash* value) { item->kind = SummaryItemHash; item->title = title; item->hash = value; } -void summary_item_set_sized_string( - SummaryItem* item, - const char* title, - const SizedString* value -) { +void summary_item_set_sized_string(SummaryItem* item, const char* title, const SizedString* value) { item->kind = SummaryItemSizedString; item->title = title; item->sized_string.length = value->length; item->sized_string.string = value->string; } -void summary_item_set_string( - SummaryItem* item, - const char* title, - const char* value -) { +void summary_item_set_string(SummaryItem* item, const char* title, const char* value) { item->kind = SummaryItemString; item->title = title; item->string = value; } -void summary_item_set_timestamp( - SummaryItem* item, - const char* title, - int64_t value -) { +void summary_item_set_timestamp(SummaryItem* item, const char* title, int64_t value) { item->kind = SummaryItemTimestamp; item->title = title; item->i64 = value; @@ -132,8 +98,12 @@ void transaction_summary_reset() { explicit_bzero(&G_transaction_summary_text, TEXT_BUFFER_LENGTH); } +static bool is_summary_item_used(const SummaryItem* item) { + return (item->kind != SummaryItemNone); +} + static SummaryItem* summary_item_as_unused(SummaryItem* item) { - if (item->kind == SummaryItemNone) { + if (!is_summary_item_used(item)) { return item; } return NULL; @@ -162,7 +132,7 @@ SummaryItem* transaction_summary_nonce_authority_item() { SummaryItem* transaction_summary_general_item() { for (size_t i = 0; i < NUM_GENERAL_ITEMS; i++) { SummaryItem* item = &G_transaction_summary.general[i]; - if (summary_item_as_unused(item) != NULL) { + if (!is_summary_item_used(item)) { return item; } } @@ -177,153 +147,111 @@ int transaction_summary_set_fee_payer_pubkey(const Pubkey* pubkey) { return 0; } -static int transaction_summary_update_display_for_item( - const SummaryItem* item, - enum DisplayFlags flags -) { +static int transaction_summary_update_display_for_item(const SummaryItem* item, + enum DisplayFlags flags) { switch (item->kind) { case SummaryItemNone: return 1; case SummaryItemAmount: - BAIL_IF( - print_amount( - item->u64, - G_transaction_summary_text, - BASE58_PUBKEY_LENGTH - )); + BAIL_IF(print_amount(item->u64, G_transaction_summary_text, BASE58_PUBKEY_LENGTH)); break; case SummaryItemTokenAmount: - BAIL_IF( - print_token_amount( - item->token_amount.value, - item->token_amount.symbol, - item->token_amount.decimals, - G_transaction_summary_text, - TEXT_BUFFER_LENGTH - )); + BAIL_IF(print_token_amount(item->token_amount.value, + item->token_amount.symbol, + item->token_amount.decimals, + G_transaction_summary_text, + TEXT_BUFFER_LENGTH)); break; case SummaryItemI64: - BAIL_IF( - print_i64( - item->i64, - G_transaction_summary_text, - TEXT_BUFFER_LENGTH - )); + BAIL_IF(print_i64(item->i64, G_transaction_summary_text, TEXT_BUFFER_LENGTH)); break; case SummaryItemU64: - BAIL_IF( - print_u64( - item->u64, - G_transaction_summary_text, - TEXT_BUFFER_LENGTH - )); + BAIL_IF(print_u64(item->u64, G_transaction_summary_text, TEXT_BUFFER_LENGTH)); break; case SummaryItemPubkey: { char tmp_buf[BASE58_PUBKEY_LENGTH]; - BAIL_IF(encode_base58( - item->pubkey, - PUBKEY_SIZE, - tmp_buf, - sizeof(tmp_buf) - )); + BAIL_IF(encode_base58(item->pubkey, PUBKEY_SIZE, tmp_buf, sizeof(tmp_buf))); if (flags & DisplayFlagLongPubkeys) { - BAIL_IF( - print_string( - tmp_buf, - G_transaction_summary_text, - TEXT_BUFFER_LENGTH - )); + BAIL_IF(print_string(tmp_buf, G_transaction_summary_text, TEXT_BUFFER_LENGTH)); } else { - BAIL_IF( - print_summary( - tmp_buf, - G_transaction_summary_text, - BASE58_PUBKEY_SHORT, - SUMMARY_LENGTH, - SUMMARY_LENGTH - )); + BAIL_IF(print_summary(tmp_buf, + G_transaction_summary_text, + BASE58_PUBKEY_SHORT, + SUMMARY_LENGTH, + SUMMARY_LENGTH)); } break; } case SummaryItemHash: - BAIL_IF( - encode_base58( - item->hash, - BLOCKHASH_SIZE, - G_transaction_summary_text, - TEXT_BUFFER_LENGTH - )); + BAIL_IF(encode_base58(item->hash, + BLOCKHASH_SIZE, + G_transaction_summary_text, + TEXT_BUFFER_LENGTH)); break; case SummaryItemString: - print_string( - item->string, - G_transaction_summary_text, - TEXT_BUFFER_LENGTH - ); + print_string(item->string, G_transaction_summary_text, TEXT_BUFFER_LENGTH); break; case SummaryItemSizedString: - print_sized_string( - &item->sized_string, - G_transaction_summary_text, - TEXT_BUFFER_LENGTH - ); + print_sized_string(&item->sized_string, G_transaction_summary_text, TEXT_BUFFER_LENGTH); break; case SummaryItemTimestamp: - BAIL_IF(print_timestamp( - item->i64, - G_transaction_summary_text, - TEXT_BUFFER_LENGTH - )); + BAIL_IF(print_timestamp(item->i64, G_transaction_summary_text, TEXT_BUFFER_LENGTH)); break; } print_string(item->title, G_transaction_summary_title, TITLE_SIZE); return 0; } -int transaction_summary_display_item(size_t item_index, enum DisplayFlags flags) { +// find item_index in G_transaction_summary in the following order: +// summary->primary +// used items of summary->general[] +// used summary->nonce_account +// used summary->nonce_authority +// summary->fee_payer + +static SummaryItem* transaction_summary_find_item(size_t item_index) { struct TransactionSummary* summary = &G_transaction_summary; - SummaryItem* item = NULL; - SummaryItem* maybe_item = &summary->primary; + size_t current_index = 0; - do { - if (item_index-- == 0) { - item = maybe_item; - break; - } - for (size_t i = 0; i < NUM_GENERAL_ITEMS; i++) { - maybe_item = &summary->general[i]; - if (summary_item_as_unused(maybe_item) == NULL) { - if (item_index-- == 0) { - item = maybe_item; - break; - } + if (current_index == item_index) { + return &summary->primary; + } + ++current_index; + + for (size_t i = 0; i < NUM_GENERAL_ITEMS; i++) { + if (is_summary_item_used(&summary->general[i])) { + if (current_index == item_index) { + return &summary->general[i]; } + ++current_index; } - if (item != NULL) { - break; - } - maybe_item = &summary->nonce_account; - if ( - (summary_item_as_unused(maybe_item) == NULL) && - (item_index-- == 0) - ) { - item = maybe_item; - break; - } - maybe_item = &summary->nonce_authority; - if ( - (summary_item_as_unused(maybe_item) == NULL) && - (item_index-- == 0) - ) { - item = maybe_item; - break; + } + + if (is_summary_item_used(&summary->nonce_account)) { + if (current_index == item_index) { + return &summary->nonce_account; } - if (item_index-- == 0) { - item = &summary->fee_payer; - break; + ++current_index; + } + + if (is_summary_item_used(&summary->nonce_authority)) { + if (current_index == item_index) { + return &summary->nonce_authority; } - } while (0); + ++current_index; + } + + if (current_index == item_index) { + return &summary->fee_payer; + } + + return NULL; +} +int transaction_summary_display_item(size_t item_index, enum DisplayFlags flags) { + const SummaryItem* item; + + item = transaction_summary_find_item(item_index); if (item == NULL) { return 1; } @@ -331,17 +259,14 @@ int transaction_summary_display_item(size_t item_index, enum DisplayFlags flags) return transaction_summary_update_display_for_item(item, flags); } -#define SET_IF_USED(item, item_kinds, index) \ - do { \ - if (item.kind != SummaryItemNone) { \ - item_kinds[index++] = item.kind; \ - } \ - } while(0) - -int transaction_summary_finalize( - enum SummaryItemKind* item_kinds, - size_t* item_kinds_len -) { +#define SET_IF_USED(item, item_kinds, index) \ + do { \ + if (item.kind != SummaryItemNone) { \ + item_kinds[index++] = item.kind; \ + } \ + } while (0) + +int transaction_summary_finalize(enum SummaryItemKind* item_kinds, size_t* item_kinds_len) { const TransactionSummary* summary = &G_transaction_summary; size_t index = 0; diff --git a/libsol/transaction_summary_test.c b/libsol/transaction_summary_test.c index 59c3bbee..3acfa5dc 100644 --- a/libsol/transaction_summary_test.c +++ b/libsol/transaction_summary_test.c @@ -28,13 +28,13 @@ void test_summary_item_setters() { assert_string_equal(item.title, "u64"); assert(item.u64 == 4242); - Pubkey pubkey = {{ BYTES32_BS58_2 }}; + Pubkey pubkey = {{BYTES32_BS58_2}}; summary_item_set_pubkey(&item, "pubkey", &pubkey); assert(item.kind == SummaryItemPubkey); assert_string_equal(item.title, "pubkey"); assert(item.pubkey == &pubkey); - Hash hash = {{ BYTES32_BS58_3 }}; + Hash hash = {{BYTES32_BS58_3}}; summary_item_set_hash(&item, "hash", &hash); assert(item.kind == SummaryItemHash); assert_string_equal(item.title, "hash"); @@ -46,7 +46,7 @@ void test_summary_item_setters() { assert_string_equal(item.title, "string"); assert(item.string == string); - uint8_t string_data[4] = { 0x74, 0x65, 0x73, 0x74 }; + uint8_t string_data[4] = {0x74, 0x65, 0x73, 0x74}; SizedString sized_string = { sizeof(string_data), (char*) string_data, @@ -55,9 +55,7 @@ void test_summary_item_setters() { assert(item.kind == SummaryItemSizedString); assert_string_equal(item.title, "sizedString"); assert(item.sized_string.length == sizeof(string_data)); - assert( - strncmp("test", item.sized_string.string, item.sized_string.length) == 0 - ); + assert(strncmp("test", item.sized_string.string, item.sized_string.length) == 0); summary_item_set_timestamp(&item, "timestamp", 42); assert(item.kind == SummaryItemTimestamp); @@ -155,10 +153,10 @@ void test_transaction_summary_item_getters() { assert(transaction_summary_general_item() == NULL); } -#define assert_transaction_summary_display(title, text) \ - do { \ - assert_string_equal(G_transaction_summary_title, title); \ - assert_string_equal(G_transaction_summary_text, text); \ +#define assert_transaction_summary_display(title, text) \ + do { \ + assert_string_equal(G_transaction_summary_title, title); \ + assert_string_equal(G_transaction_summary_text, text); \ } while (0) void test_transaction_summary_update_display_for_item() { @@ -195,13 +193,10 @@ void test_transaction_summary_update_display_for_item() { explicit_bzero(&hash, sizeof(Hash)); summary_item_set_hash(&item, "hash", &hash); assert(transaction_summary_update_display_for_item(&item, DisplayFlagNone) == 0); - assert_transaction_summary_display( - "hash", - "11111111111111111111111111111111" - ); + assert_transaction_summary_display("hash", "11111111111111111111111111111111"); - uint8_t string_data[] = { 0x74, 0x65, 0x73, 0x74 }; - SizedString sized_string = { sizeof(string_data), (char*)string_data }; + uint8_t string_data[] = {0x74, 0x65, 0x73, 0x74}; + SizedString sized_string = {sizeof(string_data), (char*) string_data}; summary_item_set_sized_string(&item, "sizedString", &sized_string); assert(transaction_summary_update_display_for_item(&item, DisplayFlagNone) == 0); assert_transaction_summary_display("sizedString", "test"); @@ -216,33 +211,23 @@ void test_transaction_summary_update_display_for_item() { assert_transaction_summary_display("timestamp", "1970-01-01 00:00:42"); } -#define display_item_test_helper(item, item_index) \ - do { \ - SummaryItem* si; \ - assert((si = transaction_summary_ ## item ## _item()) != NULL); \ - summary_item_set_u64(si, #item, 42); \ - assert( \ - transaction_summary_display_item( \ - item_index, \ - DisplayFlagNone \ - ) == 0 \ - ); \ - assert_transaction_summary_display(#item, "42"); \ +#define display_item_test_helper(item, item_index) \ + do { \ + SummaryItem* si; \ + assert((si = transaction_summary_##item##_item()) != NULL); \ + summary_item_set_u64(si, #item, 42); \ + assert(transaction_summary_display_item(item_index, DisplayFlagNone) == 0); \ + assert_transaction_summary_display(#item, "42"); \ } while (0) -#define display_item_test_helper_general_item(general_index) \ - do { \ - SummaryItem* si; \ - const char* title = "general_" #general_index; \ - assert((si = transaction_summary_general_item()) != NULL); \ - summary_item_set_u64(si, title, 42); \ - assert( \ - transaction_summary_display_item( \ - general_index + 1, \ - DisplayFlagNone \ - ) == 0 \ - ); \ - assert_transaction_summary_display(title, "42"); \ +#define display_item_test_helper_general_item(general_index) \ + do { \ + SummaryItem* si; \ + const char* title = "general_" #general_index; \ + assert((si = transaction_summary_general_item()) != NULL); \ + summary_item_set_u64(si, title, 42); \ + assert(transaction_summary_display_item(general_index + 1, DisplayFlagNone) == 0); \ + assert_transaction_summary_display(title, "42"); \ } while (0) void test_transaction_summary_display_item() { @@ -260,19 +245,17 @@ void test_transaction_summary_display_item() { } #define zero_kinds_array(kinds) \ - explicit_bzero( \ - kinds, \ - MAX_TRANSACTION_SUMMARY_ITEMS * sizeof(enum SummaryItemKind)) - -#define assert_kinds_array(kinds, num_kinds) \ - do { \ - for (size_t k = 0; k < MAX_TRANSACTION_SUMMARY_ITEMS; k++) { \ - if (k < num_kinds) { \ - assert(kinds[k] == SummaryItemU64); \ - } else { \ - assert(kinds[k] == SummaryItemNone); \ - } \ - } \ + explicit_bzero(kinds, MAX_TRANSACTION_SUMMARY_ITEMS * sizeof(enum SummaryItemKind)) + +#define assert_kinds_array(kinds, num_kinds) \ + do { \ + for (size_t k = 0; k < MAX_TRANSACTION_SUMMARY_ITEMS; k++) { \ + if (k < num_kinds) { \ + assert(kinds[k] == SummaryItemU64); \ + } else { \ + assert(kinds[k] == SummaryItemNone); \ + } \ + } \ } while (0) void test_transaction_summary_finalize() { @@ -354,19 +337,14 @@ void test_repro_unrecognized_format_reverse_nav_hash_corruption_bug() { const char* primary_text = "format"; const char* fee_payer_title = FEE_PAYER_TITLE; const char* fee_payer_text = "1111111..1111111"; - Pubkey fee_payer = {{ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }}; + Pubkey fee_payer = {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}; const char* message_hash_title = "Message hash"; - const char* message_hash_text = - "22222222222222222222222222222222222222222222"; - Hash message_hash = {{ - 0x0f, 0x1e, 0x6b, 0x14, 0x21, 0xc0, 0x4a, 0x07, 0x04, 0x31, 0x26, 0x5c, - 0x19, 0xc5, 0xbb, 0xee, 0x19, 0x92, 0xba, 0xe8, 0xaf, 0xd1, 0xcd, 0x07, - 0x8e, 0xf8, 0xaf, 0x70, 0x47, 0xdc, 0x11, 0xf7 - }}; + const char* message_hash_text = "22222222222222222222222222222222222222222222"; + Hash message_hash = {{0x0f, 0x1e, 0x6b, 0x14, 0x21, 0xc0, 0x4a, 0x07, 0x04, 0x31, 0x26, + 0x5c, 0x19, 0xc5, 0xbb, 0xee, 0x19, 0x92, 0xba, 0xe8, 0xaf, 0xd1, + 0xcd, 0x07, 0x8e, 0xf8, 0xaf, 0x70, 0x47, 0xdc, 0x11, 0xf7}}; transaction_summary_reset(); diff --git a/libsol/util.h b/libsol/util.h index ac82f75e..3e041767 100644 --- a/libsol/util.h +++ b/libsol/util.h @@ -2,15 +2,17 @@ #include #define ARRAY_LEN(a) (sizeof(a) / sizeof((a)[0])) -#define BAIL_IF(x) do {int err = x; if (err) return err;} while (0) +#define BAIL_IF(x) \ + do { \ + int err = x; \ + if (err) return err; \ + } while (0) #define MIN(a, b) ((a) < (b) ? (a) : (b)); -#define assert_string_equal(actual, expected) \ - assert(strcmp(actual, expected) == 0) +#define assert_string_equal(actual, expected) assert(strcmp(actual, expected) == 0) -#define assert_pubkey_equal(actual, expected) \ - assert(memcmp(actual, expected, 32) == 0) +#define assert_pubkey_equal(actual, expected) assert(memcmp(actual, expected, 32) == 0) #ifndef UNUSED -#define UNUSED(x) (void)x +#define UNUSED(x) (void) x #endif diff --git a/libsol/vote_instruction.c b/libsol/vote_instruction.c index fcc1ddd3..0106d440 100644 --- a/libsol/vote_instruction.c +++ b/libsol/vote_instruction.c @@ -5,12 +5,9 @@ #include "util.h" #include "vote_instruction.h" -const Pubkey vote_program_id = {{ PROGRAM_ID_VOTE }}; +const Pubkey vote_program_id = {{PROGRAM_ID_VOTE}}; -static int parse_vote_instruction_kind( - Parser* parser, - enum VoteInstructionKind* kind -) { +static int parse_vote_instruction_kind(Parser* parser, enum VoteInstructionKind* kind) { uint32_t maybe_kind; BAIL_IF(parse_u32(parser, &maybe_kind)); switch (maybe_kind) { @@ -28,10 +25,7 @@ static int parse_vote_instruction_kind( return 1; } -static int parse_vote_authorize( - Parser* parser, - enum VoteAuthorize* authorize -) { +static int parse_vote_authorize(Parser* parser, enum VoteAuthorize* authorize) { uint32_t maybe_authorize; BAIL_IF(parse_u32(parser, &maybe_authorize)); switch (maybe_authorize) { @@ -43,12 +37,10 @@ static int parse_vote_authorize( return 1; } -static int parse_vote_initialize_instruction( - Parser* parser, - const Instruction* instruction, - const MessageHeader* header, - VoteInitializeInfo* info -) { +static int parse_vote_initialize_instruction(Parser* parser, + const Instruction* instruction, + const MessageHeader* header, + VoteInitializeInfo* info) { InstructionAccountsIterator it; instruction_accounts_iterator_init(&it, header, instruction); @@ -68,12 +60,10 @@ static int parse_vote_initialize_instruction( return 0; } -static int parse_vote_withdraw_instruction( - Parser* parser, - const Instruction* instruction, - const MessageHeader* header, - VoteWithdrawInfo* info -) { +static int parse_vote_withdraw_instruction(Parser* parser, + const Instruction* instruction, + const MessageHeader* header, + VoteWithdrawInfo* info) { InstructionAccountsIterator it; instruction_accounts_iterator_init(&it, header, instruction); @@ -86,12 +76,10 @@ static int parse_vote_withdraw_instruction( return 0; } -static int parse_vote_authorize_instruction( - Parser* parser, - const Instruction* instruction, - const MessageHeader* header, - VoteAuthorizeInfo* info -) { +static int parse_vote_authorize_instruction(Parser* parser, + const Instruction* instruction, + const MessageHeader* header, + VoteAuthorizeInfo* info) { InstructionAccountsIterator it; instruction_accounts_iterator_init(&it, header, instruction); @@ -106,12 +94,10 @@ static int parse_vote_authorize_instruction( return 0; } -static int parse_vote_authorize_checked_instruction( - Parser* parser, - const Instruction* instruction, - const MessageHeader* header, - VoteAuthorizeInfo* info -) { +static int parse_vote_authorize_checked_instruction(Parser* parser, + const Instruction* instruction, + const MessageHeader* header, + VoteAuthorizeInfo* info) { InstructionAccountsIterator it; instruction_accounts_iterator_init(&it, header, instruction); @@ -126,12 +112,10 @@ static int parse_vote_authorize_checked_instruction( return 0; } -static int parse_vote_update_validator_id_instruction( - Parser* parser, - const Instruction* instruction, - const MessageHeader* header, - VoteUpdateValidatorIdInfo* info -) { +static int parse_vote_update_validator_id_instruction(Parser* parser, + const Instruction* instruction, + const MessageHeader* header, + VoteUpdateValidatorIdInfo* info) { InstructionAccountsIterator it; instruction_accounts_iterator_init(&it, header, instruction); @@ -140,9 +124,7 @@ static int parse_vote_update_validator_id_instruction( // 1.0.8+, 1.1.3+ format // https://github.com/solana-labs/solana/pull/8947 BAIL_IF(instruction_accounts_iterator_next(&it, &info->new_validator_id)); - } else if ( - instruction->data_length == (sizeof(uint32_t) + sizeof(Pubkey)) - ) { + } else if (instruction->data_length == (sizeof(uint32_t) + sizeof(Pubkey))) { // Before 1.0.8 and 1.1.3, the validaotr identity was passed // as an instruction arg BAIL_IF(parse_pubkey(parser, &info->new_validator_id)); @@ -157,12 +139,10 @@ static int parse_vote_update_validator_id_instruction( return 0; } -static int parse_vote_update_commission_instruction( - Parser* parser, - const Instruction* instruction, - const MessageHeader* header, - VoteUpdateCommissionInfo* info -) { +static int parse_vote_update_commission_instruction(Parser* parser, + const Instruction* instruction, + const MessageHeader* header, + VoteUpdateCommissionInfo* info) { InstructionAccountsIterator it; instruction_accounts_iterator_init(&it, header, instruction); @@ -174,58 +154,38 @@ static int parse_vote_update_commission_instruction( return 0; } -int parse_vote_instructions( - const Instruction* instruction, - const MessageHeader* header, - VoteInfo* info -) { +int parse_vote_instructions(const Instruction* instruction, + const MessageHeader* header, + VoteInfo* info) { Parser parser = {instruction->data, instruction->data_length}; BAIL_IF(parse_vote_instruction_kind(&parser, &info->kind)); switch (info->kind) { case VoteInitialize: - return parse_vote_initialize_instruction( - &parser, - instruction, - header, - &info->initialize - ); + return parse_vote_initialize_instruction(&parser, + instruction, + header, + &info->initialize); case VoteWithdraw: - return parse_vote_withdraw_instruction( - &parser, - instruction, - header, - &info->withdraw - ); + return parse_vote_withdraw_instruction(&parser, instruction, header, &info->withdraw); case VoteAuthorize: - return parse_vote_authorize_instruction( - &parser, - instruction, - header, - &info->authorize - ); + return parse_vote_authorize_instruction(&parser, instruction, header, &info->authorize); case VoteAuthorizeChecked: - return parse_vote_authorize_checked_instruction( - &parser, - instruction, - header, - &info->authorize - ); + return parse_vote_authorize_checked_instruction(&parser, + instruction, + header, + &info->authorize); case VoteUpdateValidatorId: - return parse_vote_update_validator_id_instruction( - &parser, - instruction, - header, - &info->update_validator_id - ); + return parse_vote_update_validator_id_instruction(&parser, + instruction, + header, + &info->update_validator_id); case VoteUpdateCommission: - return parse_vote_update_commission_instruction( - &parser, - instruction, - header, - &info->update_commission - ); + return parse_vote_update_commission_instruction(&parser, + instruction, + header, + &info->update_commission); case VoteVote: case VoteSwitchVote: break; @@ -234,10 +194,7 @@ int parse_vote_instructions( return 1; } -static int print_vote_withdraw_info( - const VoteWithdrawInfo* info, - const PrintConfig* print_config -) { +static int print_vote_withdraw_info(const VoteWithdrawInfo* info, const PrintConfig* print_config) { SummaryItem* item; item = transaction_summary_primary_item(); @@ -257,10 +214,8 @@ static int print_vote_withdraw_info( return 0; } -static int print_vote_authorize_info( - const VoteAuthorizeInfo* info, - const PrintConfig* print_config -) { +static int print_vote_authorize_info(const VoteAuthorizeInfo* info, + const PrintConfig* print_config) { const char* new_authority_title = NULL; SummaryItem* item; @@ -287,10 +242,8 @@ static int print_vote_authorize_info( return 0; } -static int print_vote_update_validator_id_info( - const VoteUpdateValidatorIdInfo* info, - const PrintConfig* print_config -) { +static int print_vote_update_validator_id_info(const VoteUpdateValidatorIdInfo* info, + const PrintConfig* print_config) { SummaryItem* item; item = transaction_summary_primary_item(); @@ -307,10 +260,8 @@ static int print_vote_update_validator_id_info( return 0; } -static int print_vote_update_commission_info( - const VoteUpdateCommissionInfo* info, - const PrintConfig* print_config -) { +static int print_vote_update_commission_info(const VoteUpdateCommissionInfo* info, + const PrintConfig* print_config) { SummaryItem* item; item = transaction_summary_primary_item(); @@ -330,32 +281,16 @@ static int print_vote_update_commission_info( int print_vote_info(const VoteInfo* info, const PrintConfig* print_config) { switch (info->kind) { case VoteInitialize: - return print_vote_initialize_info( - "Init vote acct", - &info->initialize, - print_config - ); + return print_vote_initialize_info("Init vote acct", &info->initialize, print_config); case VoteWithdraw: - return print_vote_withdraw_info( - &info->withdraw, - print_config - ); + return print_vote_withdraw_info(&info->withdraw, print_config); case VoteAuthorize: case VoteAuthorizeChecked: - return print_vote_authorize_info( - &info->authorize, - print_config - ); + return print_vote_authorize_info(&info->authorize, print_config); case VoteUpdateValidatorId: - return print_vote_update_validator_id_info( - &info->update_validator_id, - print_config - ); + return print_vote_update_validator_id_info(&info->update_validator_id, print_config); case VoteUpdateCommission: - return print_vote_update_commission_info( - &info->update_commission, - print_config - ); + return print_vote_update_commission_info(&info->update_commission, print_config); case VoteVote: case VoteSwitchVote: break; @@ -364,11 +299,9 @@ int print_vote_info(const VoteInfo* info, const PrintConfig* print_config) { return 1; } -int print_vote_initialize_info( - const char* primary_title, - const VoteInitializeInfo* info, - const PrintConfig* print_config -) { +int print_vote_initialize_info(const char* primary_title, + const VoteInitializeInfo* info, + const PrintConfig* print_config) { UNUSED(print_config); SummaryItem* item; @@ -381,18 +314,10 @@ int print_vote_initialize_info( summary_item_set_pubkey(item, "Validator ID", info->vote_init.validator_id); item = transaction_summary_general_item(); - summary_item_set_pubkey( - item, - "New vote auth", - info->vote_init.vote_authority - ); + summary_item_set_pubkey(item, "New vote auth", info->vote_init.vote_authority); item = transaction_summary_general_item(); - summary_item_set_pubkey( - item, - "New withdraw auth", - info->vote_init.withdraw_authority - ); + summary_item_set_pubkey(item, "New withdraw auth", info->vote_init.withdraw_authority); item = transaction_summary_general_item(); summary_item_set_u64(item, "Commission", info->vote_init.commission); diff --git a/libsol/vote_instruction.h b/libsol/vote_instruction.h index 9440e205..dbbdb279 100644 --- a/libsol/vote_instruction.h +++ b/libsol/vote_instruction.h @@ -70,14 +70,10 @@ typedef struct VoteInfo { }; } VoteInfo; -int parse_vote_instructions( - const Instruction* instruction, - const MessageHeader* header, - VoteInfo* info -); +int parse_vote_instructions(const Instruction* instruction, + const MessageHeader* header, + VoteInfo* info); int print_vote_info(const VoteInfo* info, const PrintConfig* print_config); -int print_vote_initialize_info( - const char* primary_title, - const VoteInitializeInfo* info, - const PrintConfig* print_config -); +int print_vote_initialize_info(const char* primary_title, + const VoteInitializeInfo* info, + const PrintConfig* print_config); diff --git a/sonar-project.properties b/sonar-project.properties index a058804d..88742c9d 100644 --- a/sonar-project.properties +++ b/sonar-project.properties @@ -5,7 +5,8 @@ sonar.organization=ledger sonar.projectName=app-solana # Path is relative to the sonar-project.properties file. Replace "\" by "/" on Windows. -sonar.sources=. +sonar.sources=./src,./libsol +sonar.tests=./tests # Encoding of the source code. Default is default system encoding sonar.sourceEncoding=UTF-8 diff --git a/src/apdu.c b/src/apdu.c new file mode 100644 index 00000000..5ed1c88f --- /dev/null +++ b/src/apdu.c @@ -0,0 +1,196 @@ +#include "apdu.h" +#include "utils.h" + +/** + * Deserialize APDU into ApduCommand structure. + * + * @param[in] apdu_message + * Pointer to raw APDU buffer. + * @param[in] apdu_message_len + * Size of the APDU buffer. + * @param[out] apdu_command + * Pointer to ApduCommand structure. + * + * @return zero on success, ApduReply error code otherwise. + * + */ +int apdu_handle_message(const uint8_t* apdu_message, + size_t apdu_message_len, + ApduCommand* apdu_command) { + if (!apdu_command || !apdu_message) { + return ApduReplySdkInvalidParameter; + } + + // parse header + ApduHeader header = {0}; + + // must at least hold the class and instruction + if (apdu_message_len <= OFFSET_INS) { + return ApduReplySolanaInvalidMessageSize; + } + + header.class = apdu_message[OFFSET_CLA]; + if (header.class != CLA) { + return ApduReplySolanaInvalidMessageHeader; + } + + header.instruction = apdu_message[OFFSET_INS]; + switch (header.instruction) { + case InsDeprecatedGetAppConfiguration: + case InsDeprecatedGetPubkey: + case InsDeprecatedSignMessage: { + // must at least hold a full deprecated header + if (apdu_message_len < DEPRECATED_OFFSET_CDATA) { + return ApduReplySolanaInvalidMessageSize; + } + + // deprecated data may be up to 64KiB + if (apdu_message_len > UINT16_MAX) { + return ApduReplySolanaInvalidMessageSize; + } + + header.data_length = apdu_message ? U2BE(apdu_message, OFFSET_LC) : 0; + if (apdu_message_len != header.data_length + DEPRECATED_OFFSET_CDATA) { + return ApduReplySolanaInvalidMessageSize; + } + + if (header.data_length > 0) { + header.data = apdu_message + DEPRECATED_OFFSET_CDATA; + } + + header.deprecated_host = true; + + break; + } + case InsGetAppConfiguration: + case InsGetPubkey: + case InsSignMessage: + case InsSignOffchainMessage: { + // must at least hold a full modern header + if (apdu_message_len < OFFSET_CDATA) { + return ApduReplySolanaInvalidMessageSize; + } + // modern data may be up to 255B + if (apdu_message_len > UINT8_MAX + OFFSET_CDATA) { + return ApduReplySolanaInvalidMessageSize; + } + + header.data_length = apdu_message[OFFSET_LC]; + if (apdu_message_len != header.data_length + OFFSET_CDATA) { + return ApduReplySolanaInvalidMessageSize; + } + + if (header.data_length > 0) { + header.data = apdu_message + OFFSET_CDATA; + } + + header.deprecated_host = false; + + break; + } + default: + return ApduReplyUnimplementedInstruction; + } + + header.p1 = apdu_message[OFFSET_P1]; + header.p2 = apdu_message[OFFSET_P2]; + // P2_EXTEND is set to signal that this APDU buffer extends, rather + // than replaces, the current message buffer + const bool first_data_chunk = !(header.p2 & P2_EXTEND); + + if (header.instruction == InsDeprecatedGetAppConfiguration || + header.instruction == InsGetAppConfiguration) { + // return early if no data is expected for the command + explicit_bzero(apdu_command, sizeof(ApduCommand)); + apdu_command->state = ApduStatePayloadComplete; + apdu_command->instruction = header.instruction; + apdu_command->non_confirm = (header.p1 == P1_NON_CONFIRM); + apdu_command->deprecated_host = header.deprecated_host; + return 0; + } else if (header.instruction == InsDeprecatedSignMessage || + header.instruction == InsSignMessage || + header.instruction == InsSignOffchainMessage) { + if (!first_data_chunk) { + // validate the command in progress + if (apdu_command->state != ApduStatePayloadInProgress || + apdu_command->instruction != header.instruction || + apdu_command->non_confirm != (header.p1 == P1_NON_CONFIRM) || + apdu_command->deprecated_host != header.deprecated_host || + apdu_command->num_derivation_paths != 1) { + return ApduReplySolanaInvalidMessage; + } + } else { + explicit_bzero(apdu_command, sizeof(ApduCommand)); + } + } else { + explicit_bzero(apdu_command, sizeof(ApduCommand)); + } + + // read derivation path + if (first_data_chunk) { + if (!header.deprecated_host && header.instruction != InsGetPubkey) { + if (!header.data_length) { + return ApduReplySolanaInvalidMessageSize; + } + apdu_command->num_derivation_paths = header.data[0]; + header.data++; + header.data_length--; + // We only support one derivation path ATM + if (apdu_command->num_derivation_paths != 1) { + return ApduReplySolanaInvalidMessage; + } + } else { + apdu_command->num_derivation_paths = 1; + } + const int ret = read_derivation_path(header.data, + header.data_length, + apdu_command->derivation_path, + &apdu_command->derivation_path_length); + if (ret) { + return ret; + } + header.data += 1 + apdu_command->derivation_path_length * 4; + header.data_length -= 1 + apdu_command->derivation_path_length * 4; + } + + apdu_command->state = ApduStatePayloadInProgress; + apdu_command->instruction = header.instruction; + apdu_command->non_confirm = (header.p1 == P1_NON_CONFIRM); + apdu_command->deprecated_host = header.deprecated_host; + + // copy data to the buffer + if (header.instruction == InsDeprecatedSignMessage) { + // deprecated signmessage had a u16 data length prefix... deal with that + if (header.data_length < 2) { + return ApduReplySolanaInvalidMessageSize; + } + const size_t data_len = header.data ? U2BE(header.data, 0) : 0; + header.data += 2; + header.data_length -= 2; + if (header.data_length != data_len) { + return ApduReplySolanaInvalidMessageSize; + } + } + + if (header.data) { + if (apdu_command->message_length + header.data_length > MAX_MESSAGE_LENGTH) { + return ApduReplySolanaInvalidMessageSize; + } + + memcpy(apdu_command->message + apdu_command->message_length, + header.data, + header.data_length); + apdu_command->message_length += header.data_length; + } else if (header.instruction != InsDeprecatedGetPubkey && header.instruction != InsGetPubkey) { + return ApduReplySolanaInvalidMessageSize; + } + + // check if more data is expected + if (header.p2 & P2_MORE) { + return 0; + } + + apdu_command->state = ApduStatePayloadComplete; + + return 0; +} \ No newline at end of file diff --git a/src/apdu.h b/src/apdu.h new file mode 100644 index 00000000..2499e753 --- /dev/null +++ b/src/apdu.h @@ -0,0 +1,82 @@ +#pragma once + +#include +#include +#include +#include "globals.h" +#include "sol/parser.h" + +typedef enum ApduState { + ApduStateUninitialized = 0, + ApduStatePayloadInProgress, + ApduStatePayloadComplete, +} ApduState; + +typedef enum ApduReply { + /* ApduReplySdk* come from nanos-secure-sdk/include/os.h. Here we add the + * 0x68__ prefix that app_main() ORs into those values before sending them + * over the wire + */ + ApduReplySdkException = 0x6801, + ApduReplySdkInvalidParameter = 0x6802, + ApduReplySdkExceptionOverflow = 0x6803, + ApduReplySdkExceptionSecurity = 0x6804, + ApduReplySdkInvalidCrc = 0x6805, + ApduReplySdkInvalidChecksum = 0x6806, + ApduReplySdkInvalidCounter = 0x6807, + ApduReplySdkNotSupported = 0x6808, + ApduReplySdkInvalidState = 0x6809, + ApduReplySdkTimeout = 0x6810, + ApduReplySdkExceptionPIC = 0x6811, + ApduReplySdkExceptionAppExit = 0x6812, + ApduReplySdkExceptionIoOverflow = 0x6813, + ApduReplySdkExceptionIoHeader = 0x6814, + ApduReplySdkExceptionIoState = 0x6815, + ApduReplySdkExceptionIoReset = 0x6816, + ApduReplySdkExceptionCxPort = 0x6817, + ApduReplySdkExceptionSystem = 0x6818, + ApduReplySdkNotEnoughSpace = 0x6819, + + ApduReplyNoApduReceived = 0x6982, + + ApduReplySolanaInvalidMessage = 0x6a80, + ApduReplySolanaInvalidMessageHeader = 0x6a81, + ApduReplySolanaInvalidMessageFormat = 0x6a82, + ApduReplySolanaInvalidMessageSize = 0x6a83, + ApduReplySolanaSummaryFinalizeFailed = 0x6f00, + ApduReplySolanaSummaryUpdateFailed = 0x6f01, + + ApduReplyUnimplementedInstruction = 0x6d00, + ApduReplyInvalidCla = 0x6e00, + + ApduReplySuccess = 0x9000, +} ApduReply; + +typedef struct ApduHeader { + uint8_t class; + uint8_t instruction; + uint8_t p1; + uint8_t p2; + const uint8_t* data; + size_t data_length; + bool deprecated_host; +} ApduHeader; + +typedef struct ApduCommand { + ApduState state; + InstructionCode instruction; + uint8_t num_derivation_paths; + uint32_t derivation_path[MAX_BIP32_PATH_LENGTH]; + uint32_t derivation_path_length; + bool non_confirm; + bool deprecated_host; + uint8_t message[MAX_MESSAGE_LENGTH]; + int message_length; + Hash message_hash; +} ApduCommand; + +extern ApduCommand G_command; + +int apdu_handle_message(const uint8_t* apdu_message, + size_t apdu_message_len, + ApduCommand* apdu_command); \ No newline at end of file diff --git a/src/getPubkey.c b/src/getPubkey.c index 7a37a91d..5cb6bb2c 100644 --- a/src/getPubkey.c +++ b/src/getPubkey.c @@ -1,104 +1,63 @@ +#include "apdu.h" #include "getPubkey.h" #include "os.h" #include "ux.h" #include "utils.h" #include "sol/printer.h" -static uint8_t publicKey[PUBKEY_LENGTH]; -static char publicKeyStr[BASE58_PUBKEY_LENGTH]; +static uint8_t G_publicKey[PUBKEY_LENGTH]; +static char G_publicKeyStr[BASE58_PUBKEY_LENGTH]; -int read_derivation_path( - const uint8_t *dataBuffer, - size_t size, - uint32_t *derivationPath -) { - if (size == 0) { - THROW(ApduReplySolanaInvalidMessage); - } - size_t len = dataBuffer[0]; - dataBuffer += 1; - if (len < 0x01 || len > BIP32_PATH) { - THROW(ApduReplySolanaInvalidMessage); - } - if (1 + 4 * len > size) { - THROW(ApduReplySolanaInvalidMessage); - } - - for (unsigned int i = 0; i < len; i++) { - derivationPath[i] = ( - (dataBuffer[0] << 24u) | (dataBuffer[1] << 16u) | - (dataBuffer[2] << 8u) | (dataBuffer[3]) - ); - dataBuffer += 4; - } - return len; +void reset_getpubkey_globals(void) { + MEMCLEAR(G_publicKey); + MEMCLEAR(G_publicKeyStr); } static uint8_t set_result_get_pubkey() { - uint8_t tx = 32; - - memcpy(G_io_apdu_buffer, publicKey, 32); - return tx; + memcpy(G_io_apdu_buffer, G_publicKey, PUBKEY_LENGTH); + return PUBKEY_LENGTH; } ////////////////////////////////////////////////////////////////////// -UX_STEP_NOCB( - ux_display_public_flow_5_step, - bnnn_paging, - { - .title = "Pubkey", - .text = publicKeyStr, - }); -UX_STEP_VALID( - ux_display_public_flow_6_step, - pb, - sendResponse(set_result_get_pubkey(), true), - { - &C_icon_validate_14, - "Approve", - }); -UX_STEP_VALID( - ux_display_public_flow_7_step, - pb, - sendResponse(0, false), - { - &C_icon_crossmark, - "Reject", - }); +UX_STEP_NOCB(ux_display_public_flow_5_step, + bnnn_paging, + { + .title = "Pubkey", + .text = G_publicKeyStr, + }); +UX_STEP_CB(ux_display_public_flow_6_step, + pb, + sendResponse(set_result_get_pubkey(), true), + { + &C_icon_validate_14, + "Approve", + }); +UX_STEP_CB(ux_display_public_flow_7_step, + pb, + sendResponse(0, false), + { + &C_icon_crossmark, + "Reject", + }); UX_FLOW(ux_display_public_flow, - &ux_display_public_flow_5_step, - &ux_display_public_flow_6_step, - &ux_display_public_flow_7_step -); + &ux_display_public_flow_5_step, + &ux_display_public_flow_6_step, + &ux_display_public_flow_7_step); -void handleGetPubkey( - uint8_t p1, - uint8_t p2, - uint8_t *dataBuffer, - uint16_t dataLength, - volatile unsigned int *flags, - volatile unsigned int *tx -) { - UNUSED(p2); - - uint32_t derivationPath[BIP32_PATH]; - int pathLength = read_derivation_path( - dataBuffer, - dataLength, - derivationPath - ); +void handle_get_pubkey(volatile unsigned int *flags, volatile unsigned int *tx) { + if (!flags || !tx || + (G_command.instruction != InsDeprecatedGetPubkey && + G_command.instruction != InsGetPubkey) || + G_command.state != ApduStatePayloadComplete) { + THROW(ApduReplySdkInvalidParameter); + } - getPublicKey(derivationPath, publicKey, pathLength); - encode_base58( - publicKey, - PUBKEY_LENGTH, - publicKeyStr, - BASE58_PUBKEY_LENGTH - ); + get_public_key(G_publicKey, G_command.derivation_path, G_command.derivation_path_length); + encode_base58(G_publicKey, PUBKEY_LENGTH, G_publicKeyStr, BASE58_PUBKEY_LENGTH); - if (p1 == P1_NON_CONFIRM) { + if (G_command.non_confirm) { *tx = set_result_get_pubkey(); THROW(ApduReplySuccess); } else { diff --git a/src/getPubkey.h b/src/getPubkey.h index 29512d0b..59e0e1fa 100644 --- a/src/getPubkey.h +++ b/src/getPubkey.h @@ -5,18 +5,8 @@ #ifndef _GET_PUBKEY_H_ #define _GET_PUBKEY_H_ -int read_derivation_path( - const uint8_t *dataBuffer, - size_t size, - uint32_t *derivationPath -); -void handleGetPubkey( - uint8_t p1, - uint8_t p2, - uint8_t *dataBuffer, - uint16_t dataLength, - volatile unsigned int *flags, - volatile unsigned int *tx -); +void reset_getpubkey_globals(void); + +void handle_get_pubkey(volatile unsigned int *flags, volatile unsigned int *tx); #endif diff --git a/src/globals.h b/src/globals.h index 46ac61f3..727505ba 100644 --- a/src/globals.h +++ b/src/globals.h @@ -5,62 +5,53 @@ #ifndef _GLOBALS_H_ #define _GLOBALS_H_ -#define P1_CONFIRM 0x01 +#define CLA 0xE0 + +// header offsets +#define OFFSET_CLA 0 +#define OFFSET_INS 1 +#define OFFSET_P1 2 +#define OFFSET_P2 3 +#define OFFSET_LC 4 +#define OFFSET_CDATA 5 +#define DEPRECATED_OFFSET_CDATA 6 + +#define P1_CONFIRM 0x01 #define P1_NON_CONFIRM 0x00 #define P2_EXTEND 0x01 -#define P2_MORE 0x02 +#define P2_MORE 0x02 -#define ROUND_TO_NEXT(x, next) \ - (((x) == 0) ? 0 : ((((x - 1) / (next)) + 1) * (next))) +#define ROUND_TO_NEXT(x, next) (((x) == 0) ? 0 : ((((x - 1) / (next)) + 1) * (next))) /* See constant by same name in sdk/src/packet.rs */ #define PACKET_DATA_SIZE (1280 - 40 - 8) -#define MAX_MESSAGE_LENGTH ROUND_TO_NEXT(PACKET_DATA_SIZE, USB_SEGMENT_SIZE) -#define SIGNATURE_LENGTH 64 -#define HASH_LENGTH 32 -#define PUBKEY_LENGTH HASH_LENGTH -#define BIP32_PATH 5 - -enum ApduReply { - /* ApduReplySdk* come from nanos-secure-sdk/include/os.h. Here we add the - * 0x68__ prefix that app_main() ORs into those values before sending them - * over the wire - */ - ApduReplySdkException = 0x6801, - ApduReplySdkInvalidParameter = 0x6802, - ApduReplySdkExceptionOverflow = 0x6803, - ApduReplySdkExceptionSecurity = 0x6804, - ApduReplySdkInvalidCrc = 0x6805, - ApduReplySdkInvalidChecksum = 0x6806, - ApduReplySdkInvalidCounter = 0x6807, - ApduReplySdkNotSupported = 0x6808, - ApduReplySdkInvalidState = 0x6809, - ApduReplySdkTimeout = 0x6810, - ApduReplySdkExceptionPIC = 0x6811, - ApduReplySdkExceptionAppExit = 0x6812, - ApduReplySdkExceptionIoOverflow = 0x6813, - ApduReplySdkExceptionIoHeader = 0x6814, - ApduReplySdkExceptionIoState = 0x6815, - ApduReplySdkExceptionIoReset = 0x6816, - ApduReplySdkExceptionCxPort = 0x6817, - ApduReplySdkExceptionSystem = 0x6818, - ApduReplySdkNotEnoughSpace = 0x6819, - - ApduReplyNoApduReceived = 0x6982, - - ApduReplySolanaInvalidMessage = 0x6a80, - ApduReplySolanaSummaryFinalizeFailed = 0x6f00, - ApduReplySolanaSummaryUpdateFailed = 0x6f01, - - ApduReplyUnimplementedInstruction = 0x6d00, - ApduReplyInvalidCla = 0x6e00, - - ApduReplySuccess = 0x9000, -}; +#define MAX_BIP32_PATH_LENGTH 5 +#define MAX_DERIVATION_PATH_BUFFER_LENGTH (1 + MAX_BIP32_PATH_LENGTH * 4) +#define TOTAL_SIGN_MESSAGE_BUFFER_LENGTH (PACKET_DATA_SIZE + MAX_DERIVATION_PATH_BUFFER_LENGTH) + +#define MAX_MESSAGE_LENGTH ROUND_TO_NEXT(TOTAL_SIGN_MESSAGE_BUFFER_LENGTH, USB_SEGMENT_SIZE) +#define SIGNATURE_LENGTH 64 +#define HASH_LENGTH 32 +#define PUBKEY_LENGTH HASH_LENGTH +#define PRIVATEKEY_LENGTH HASH_LENGTH + +#define MAX_OFFCHAIN_MESSAGE_LENGTH (MAX_MESSAGE_LENGTH - 1 > 1212 ? 1212 : MAX_MESSAGE_LENGTH - 1) +#define OFFCHAIN_MESSAGE_HEADER_LENGTH 20 + +typedef enum InstructionCode { + // DEPRECATED - Use non "16" suffixed variants below + InsDeprecatedGetAppConfiguration = 0x01, + InsDeprecatedGetPubkey = 0x02, + InsDeprecatedSignMessage = 0x03, + // END DEPRECATED + InsGetAppConfiguration = 0x04, + InsGetPubkey = 0x05, + InsSignMessage = 0x06, + InsSignOffchainMessage = 0x07 +} InstructionCode; -extern ux_state_t ux; // display stepped screens extern unsigned int ux_step; extern unsigned int ux_step_count; @@ -93,4 +84,4 @@ typedef struct internalStorage_t { extern const internalStorage_t N_storage_real; #define N_storage (*(volatile internalStorage_t*) PIC(&N_storage_real)) -#endif +#endif \ No newline at end of file diff --git a/src/main.c b/src/main.c index e7b1b9ab..60c00aed 100644 --- a/src/main.c +++ b/src/main.c @@ -1,153 +1,81 @@ /******************************************************************************* -* Ledger Blue -* (c) 2016 Ledger -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -********************************************************************************/ + * Ledger Blue + * (c) 2016 Ledger + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ********************************************************************************/ #include "utils.h" #include "getPubkey.h" #include "signMessage.h" +#include "signOffchainMessage.h" +#include "apdu.h" #include "menu.h" -#include +ApduCommand G_command; unsigned char G_io_seproxyhal_spi_buffer[IO_SEPROXYHAL_BUFFER_SIZE_B]; -#define CLA 0xE0 - -// DEPRECATED - Use non "16" suffixed variants below -#define INS_GET_APP_CONFIGURATION16 0x01 -#define INS_GET_PUBKEY16 0x02 -#define INS_SIGN_MESSAGE16 0x03 -#define OFFSET_CDATA16 6 -// END DEPRECATED +static void reset_main_globals(void) { + MEMCLEAR(G_command); + MEMCLEAR(G_io_seproxyhal_spi_buffer); +} -#define INS_GET_APP_CONFIGURATION 0x04 -#define INS_GET_PUBKEY 0x05 -#define INS_SIGN_MESSAGE 0x06 +void handleApdu(volatile unsigned int *flags, volatile unsigned int *tx, int rx) { + if (!flags || !tx) { + THROW(ApduReplySdkInvalidParameter); + } -#define OFFSET_CLA 0 -#define OFFSET_INS 1 -#define OFFSET_P1 2 -#define OFFSET_P2 3 -#define OFFSET_LC 4 -#define OFFSET_CDATA 5 + if (rx < 0) { + THROW(ApduReplySdkExceptionIoOverflow); + } -void handleApdu(volatile unsigned int *flags, volatile unsigned int *tx, int rx) { - unsigned short sw = 0; + const int ret = apdu_handle_message(G_io_apdu_buffer, rx, &G_command); + if (ret != 0) { + THROW(ret); + } + if (G_command.state == ApduStatePayloadInProgress) { + THROW(ApduReplySuccess); + } - assert(rx >= 0 && rx <= UINT16_MAX); + switch (G_command.instruction) { + case InsDeprecatedGetAppConfiguration: + case InsGetAppConfiguration: + G_io_apdu_buffer[0] = N_storage.settings.allow_blind_sign; + G_io_apdu_buffer[1] = N_storage.settings.pubkey_display; + G_io_apdu_buffer[2] = MAJOR_VERSION; + G_io_apdu_buffer[3] = MINOR_VERSION; + G_io_apdu_buffer[4] = PATCH_VERSION; + *tx = 5; + THROW(ApduReplySuccess); + + case InsDeprecatedGetPubkey: + case InsGetPubkey: + handle_get_pubkey(flags, tx); + break; - BEGIN_TRY { - TRY { - if (G_io_apdu_buffer[OFFSET_CLA] != CLA) { - THROW(ApduReplyInvalidCla); - } + case InsDeprecatedSignMessage: + case InsSignMessage: + handle_sign_message_parse_message(tx); + handle_sign_message_ui(flags); + break; - int dataLength; - uint8_t* dataBuffer; - switch (G_io_apdu_buffer[OFFSET_INS]) { - // Handle deprecated instructions expecting a 16bit dataLength - case INS_GET_APP_CONFIGURATION16: - case INS_GET_PUBKEY16: - case INS_SIGN_MESSAGE16: - if ( rx < OFFSET_CDATA16 - || ((uint16_t)rx != U2BE(G_io_apdu_buffer, OFFSET_LC) + OFFSET_CDATA16) - ) { - THROW(ApduReplySdkExceptionOverflow); - } - dataLength = U2BE(G_io_apdu_buffer, OFFSET_LC); - dataBuffer = &G_io_apdu_buffer[OFFSET_CDATA16]; - break; - // Modern instructions use 8bit dataLength - // as per Ledger convention - default: - if ( rx < OFFSET_CDATA - || (rx != G_io_apdu_buffer[OFFSET_LC] + OFFSET_CDATA) - ) { - THROW(ApduReplySdkExceptionOverflow); - } - dataLength = G_io_apdu_buffer[OFFSET_LC]; - dataBuffer = &G_io_apdu_buffer[OFFSET_CDATA]; - break; - } + case InsSignOffchainMessage: + handle_sign_offchain_message(flags, tx); + break; - switch (G_io_apdu_buffer[OFFSET_INS]) { - case INS_GET_APP_CONFIGURATION: - case INS_GET_APP_CONFIGURATION16: - G_io_apdu_buffer[0] = N_storage.settings.allow_blind_sign; - G_io_apdu_buffer[1] = N_storage.settings.pubkey_display; - G_io_apdu_buffer[2] = LEDGER_MAJOR_VERSION; - G_io_apdu_buffer[3] = LEDGER_MINOR_VERSION; - G_io_apdu_buffer[4] = LEDGER_PATCH_VERSION; - *tx = 5; - THROW(ApduReplySuccess); - - case INS_GET_PUBKEY: - case INS_GET_PUBKEY16: - handleGetPubkey( - G_io_apdu_buffer[OFFSET_P1], - G_io_apdu_buffer[OFFSET_P2], - dataBuffer, - dataLength, - flags, - tx - ); - break; - - case INS_SIGN_MESSAGE16: - dataLength |= DATA_HAS_LENGTH_PREFIX; - // Fall through - case INS_SIGN_MESSAGE: - handleSignMessage( - G_io_apdu_buffer[OFFSET_P1], - G_io_apdu_buffer[OFFSET_P2], - dataBuffer, - dataLength, - flags,tx - ); - break; - - default: - THROW(ApduReplyUnimplementedInstruction); - } - } - CATCH(ApduReplySdkExceptionIoReset) { - THROW(ApduReplySdkExceptionIoReset); - } - CATCH_OTHER(e) { - switch (e & 0xF000) { - case 0x6000: - sw = e; - break; - case 0x9000: - // All is well - sw = e; - break; - default: - // Internal error - sw = 0x6800 | (e & 0x7FF); - break; - } - // Unexpected exception => report - G_io_apdu_buffer[*tx] = sw >> 8; - G_io_apdu_buffer[*tx + 1] = sw; - *tx += 2; - } - FINALLY { - } + default: + THROW(ApduReplyUnimplementedInstruction); } - END_TRY; } void app_main(void) { @@ -155,9 +83,10 @@ void app_main(void) { volatile unsigned int tx = 0; volatile unsigned int flags = 0; - // Initialize derivation path count so we can accurately track the message - // buffer handling state - G_numDerivationPaths = 0; + // Stores the information about the current command. Some commands expect + // multiple APDUs before they become complete and executed. + reset_getpubkey_globals(); + reset_main_globals(); // DESIGN NOTE: the bootloader ignores the way APDU are fetched. The only // goal is to retrieve APDU. @@ -171,8 +100,8 @@ void app_main(void) { BEGIN_TRY { TRY { rx = tx; - tx = 0; // ensure no race in catch_other if io_exchange throws - // an error + tx = 0; // ensure no race in catch_other if io_exchange throws + // an error rx = io_exchange(CHANNEL_APDU | flags, rx); flags = 0; @@ -220,7 +149,7 @@ void app_main(void) { // override point, but nothing more to do void io_seproxyhal_display(const bagl_element_t *element) { - io_seproxyhal_display_default((bagl_element_t*)element); + io_seproxyhal_display_default((bagl_element_t *) element); } unsigned char io_event(unsigned char channel) { @@ -242,8 +171,7 @@ unsigned char io_event(unsigned char channel) { case SEPROXYHAL_TAG_STATUS_EVENT: if (G_io_apdu_media == IO_APDU_MEDIA_USB_HID && !(U4BE(G_io_seproxyhal_spi_buffer, 3) & - SEPROXYHAL_TAG_STATUS_EVENT_FLAG_USB_POWERED) - ) { + SEPROXYHAL_TAG_STATUS_EVENT_FLAG_USB_POWERED)) { THROW(ApduReplySdkExceptionIoReset); } // no break is intentional @@ -256,18 +184,17 @@ unsigned char io_event(unsigned char channel) { break; case SEPROXYHAL_TAG_TICKER_EVENT: - UX_TICKER_EVENT(G_io_seproxyhal_spi_buffer, - { + UX_TICKER_EVENT(G_io_seproxyhal_spi_buffer, { #if !defined(TARGET_NANOX) && !defined(TARGET_NANOS2) if (UX_ALLOWED) { if (ux_step_count) { - // prepare next screen - ux_step = (ux_step+1)%ux_step_count; - // redisplay screen - UX_REDISPLAY(); + // prepare next screen + ux_step = (ux_step + 1) % ux_step_count; + // redisplay screen + UX_REDISPLAY(); } } -#endif // TARGET_NANOX +#endif // TARGET_NANOX }); break; } @@ -281,7 +208,6 @@ unsigned char io_event(unsigned char channel) { return 1; } - unsigned short io_exchange_al(unsigned char channel, unsigned short tx_len) { switch (channel & ~(IO_FLAGS)) { case CHANNEL_KEYBOARD: @@ -296,11 +222,10 @@ unsigned short io_exchange_al(unsigned char channel, unsigned short tx_len) { if (channel & IO_RESET_AFTER_REPLIED) { reset(); } - return 0; // nothing received from the master so far - // (it's a tx transaction) + return 0; // nothing received from the master so far + // (it's a tx transaction) } else { - return io_seproxyhal_spi_recv(G_io_apdu_buffer, - sizeof(G_io_apdu_buffer), 0); + return io_seproxyhal_spi_recv(G_io_apdu_buffer, sizeof(G_io_apdu_buffer), 0); } default: @@ -309,21 +234,18 @@ unsigned short io_exchange_al(unsigned char channel, unsigned short tx_len) { return 0; } - void app_exit(void) { - BEGIN_TRY_L(exit) { TRY_L(exit) { os_sched_exit(-1); } FINALLY_L(exit) { - } } END_TRY_L(exit); } -void nv_app_state_init(){ +void nv_app_state_init() { if (N_storage.initialized != 0x01) { internalStorage_t storage; storage.settings.allow_blind_sign = BlindSignDisabled; @@ -334,11 +256,7 @@ void nv_app_state_init(){ #endif storage.settings.display_mode = DisplayModeUser; storage.initialized = 0x01; - nvm_write( - (internalStorage_t*)&N_storage, - (void*)&storage, - sizeof(internalStorage_t) - ); + nvm_write((void *) &N_storage, (void *) &storage, sizeof(internalStorage_t)); } } @@ -365,14 +283,14 @@ __attribute__((section(".boot"))) int main(void) { // Grab the current plane mode setting. os_settings_get() is enabled by // appFlags bit #9 set to 1 in Makefile (i.e. "--appFlags 0x2xx") G_io_app.plane_mode = os_setting_get(OS_SETTING_PLANEMODE, NULL, 0); -#endif // HAVE_BLE +#endif // HAVE_BLE ui_idle(); #ifdef HAVE_BLE BLE_power(0, NULL); BLE_power(1, "Nano X"); -#endif // HAVE_BLE +#endif // HAVE_BLE app_main(); } diff --git a/src/menu.c b/src/menu.c index 534204b6..7c148e53 100644 --- a/src/menu.c +++ b/src/menu.c @@ -53,30 +53,24 @@ const char* settings_submenu_getter(unsigned int idx) { } void settings_submenu_selector(unsigned int idx) { - switch(idx) { + switch (idx) { case 0: - ux_menulist_init_select( - 0, - allow_blind_sign_data_getter, - allow_blind_sign_data_selector, - N_storage.settings.allow_blind_sign - ); + ux_menulist_init_select(0, + allow_blind_sign_data_getter, + allow_blind_sign_data_selector, + N_storage.settings.allow_blind_sign); break; case 1: - ux_menulist_init_select( - 0, - pubkey_display_data_getter, - pubkey_display_data_selector, - N_storage.settings.pubkey_display - ); + ux_menulist_init_select(0, + pubkey_display_data_getter, + pubkey_display_data_selector, + N_storage.settings.pubkey_display); break; case 2: - ux_menulist_init_select( - 0, - display_mode_data_getter, - display_mode_data_selector, - N_storage.settings.display_mode - ); + ux_menulist_init_select(0, + display_mode_data_getter, + display_mode_data_selector, + N_storage.settings.display_mode); break; default: ui_idle(); @@ -92,38 +86,33 @@ static void allow_blind_sign_data_change(enum BlindSign blind_sign) { case BlindSignDisabled: case BlindSignEnabled: value = (uint8_t) blind_sign; - nvm_write((void *)&N_storage.settings.allow_blind_sign, &value, sizeof(value)); + nvm_write((void*) &N_storage.settings.allow_blind_sign, &value, sizeof(value)); break; } } -const char * const no_yes_data_getter_values[] = { - "No", - "Yes", - "Back" -}; +const char* const no_yes_data_getter_values[] = {"No", "Yes", "Back"}; static const char* allow_blind_sign_data_getter(unsigned int idx) { - if (idx < ARRAYLEN(no_yes_data_getter_values)) { - return no_yes_data_getter_values[idx]; - } - return NULL; + if (idx < ARRAYLEN(no_yes_data_getter_values)) { + return no_yes_data_getter_values[idx]; + } + return NULL; } void allow_blind_sign_data_selector(unsigned int idx) { - switch(idx) { - case 0: - allow_blind_sign_data_change(BlindSignDisabled); - break; - case 1: - allow_blind_sign_data_change(BlindSignEnabled); - break; - default: - break; - } - unsigned int select_item = - settings_submenu_option_index(SettingsMenuOptionAllowBlindSign); - ux_menulist_init_select(0, settings_submenu_getter, settings_submenu_selector, select_item); + switch (idx) { + case 0: + allow_blind_sign_data_change(BlindSignDisabled); + break; + case 1: + allow_blind_sign_data_change(BlindSignEnabled); + break; + default: + break; + } + unsigned int select_item = settings_submenu_option_index(SettingsMenuOptionAllowBlindSign); + ux_menulist_init_select(0, settings_submenu_getter, settings_submenu_selector, select_item); } ////////////////////////////////////////////////////////////////////////////////////// @@ -135,38 +124,33 @@ void pubkey_display_data_change(enum PubkeyDisplay pubkey_display) { case PubkeyDisplayLong: case PubkeyDisplayShort: value = (uint8_t) pubkey_display; - nvm_write((void *)&N_storage.settings.pubkey_display, &value, sizeof(value)); + nvm_write((void*) &N_storage.settings.pubkey_display, &value, sizeof(value)); break; } } -const char* const pubkey_display_data_getter_values[] = { - "Long", - "Short", - "Back" -}; +const char* const pubkey_display_data_getter_values[] = {"Long", "Short", "Back"}; static const char* pubkey_display_data_getter(unsigned int idx) { - if (idx < ARRAYLEN(pubkey_display_data_getter_values)) { - return pubkey_display_data_getter_values[idx]; - } - return NULL; + if (idx < ARRAYLEN(pubkey_display_data_getter_values)) { + return pubkey_display_data_getter_values[idx]; + } + return NULL; } static void pubkey_display_data_selector(unsigned int idx) { - switch(idx) { - case 0: - pubkey_display_data_change(PubkeyDisplayLong); - break; - case 1: - pubkey_display_data_change(PubkeyDisplayShort); - break; - default: - break; - } - unsigned int select_item = - settings_submenu_option_index(SettingsMenuOptionPubkeyLength); - ux_menulist_init_select(0, settings_submenu_getter, settings_submenu_selector, select_item); + switch (idx) { + case 0: + pubkey_display_data_change(PubkeyDisplayLong); + break; + case 1: + pubkey_display_data_change(PubkeyDisplayShort); + break; + default: + break; + } + unsigned int select_item = settings_submenu_option_index(SettingsMenuOptionPubkeyLength); + ux_menulist_init_select(0, settings_submenu_getter, settings_submenu_selector, select_item); } ////////////////////////////////////////////////////////////////////////////////////// @@ -178,16 +162,12 @@ void display_mode_data_change(enum DisplayMode display_mode) { case DisplayModeUser: case DisplayModeExpert: value = (uint8_t) display_mode; - nvm_write((void *)&N_storage.settings.display_mode, &value, sizeof(value)); + nvm_write((void*) &N_storage.settings.display_mode, &value, sizeof(value)); break; } } -const char* const display_mode_data_getter_values[] = { - "User", - "Expert", - "Back" -}; +const char* const display_mode_data_getter_values[] = {"User", "Expert", "Back"}; static const char* display_mode_data_getter(unsigned int idx) { if (idx < ARRAYLEN(display_mode_data_getter_values)) { @@ -207,55 +187,49 @@ static void display_mode_data_selector(unsigned int idx) { default: break; } - unsigned int select_item = - settings_submenu_option_index(SettingsMenuOptionDisplayMode); + unsigned int select_item = settings_submenu_option_index(SettingsMenuOptionDisplayMode); ux_menulist_init_select(0, settings_submenu_getter, settings_submenu_selector, select_item); } ////////////////////////////////////////////////////////////////////// -UX_STEP_NOCB( - ux_idle_flow_1_step, - pnn, - { - &C_solana_logo, - "Application", - "is ready", - }); -UX_STEP_VALID( - ux_idle_flow_2_step, - pb, - ux_menulist_init(0, settings_submenu_getter, settings_submenu_selector), - { - &C_icon_coggle, - "Settings", - }); -UX_STEP_NOCB( - ux_idle_flow_3_step, - bn, - { - "Version", - APPVERSION, - }); -UX_STEP_VALID( - ux_idle_flow_4_step, - pb, - os_sched_exit(-1), - { - &C_icon_dashboard_x, - "Quit", - }); +UX_STEP_NOCB(ux_idle_flow_1_step, + pnn, + { + &C_solana_logo, + "Application", + "is ready", + }); +UX_STEP_CB(ux_idle_flow_2_step, + pb, + ux_menulist_init(0, settings_submenu_getter, settings_submenu_selector), + { + &C_icon_coggle, + "Settings", + }); +UX_STEP_NOCB(ux_idle_flow_3_step, + bn, + { + "Version", + APPVERSION, + }); +UX_STEP_CB(ux_idle_flow_4_step, + pb, + os_sched_exit(-1), + { + &C_icon_dashboard_x, + "Quit", + }); UX_FLOW(ux_idle_flow, - &ux_idle_flow_1_step, - &ux_idle_flow_2_step, - &ux_idle_flow_3_step, - &ux_idle_flow_4_step, - FLOW_LOOP -); + &ux_idle_flow_1_step, + &ux_idle_flow_2_step, + &ux_idle_flow_3_step, + &ux_idle_flow_4_step, + FLOW_LOOP); void ui_idle(void) { - // reserve a display stack slot if none yet - if(G_ux.stack_count == 0) { - ux_stack_push(); - } - ux_flow_init(0, ux_idle_flow, NULL); + // reserve a display stack slot if none yet + if (G_ux.stack_count == 0) { + ux_stack_push(); + } + ux_flow_init(0, ux_idle_flow, NULL); } diff --git a/src/signMessage.c b/src/signMessage.c index 496d4978..2bc3d380 100644 --- a/src/signMessage.c +++ b/src/signMessage.c @@ -9,260 +9,170 @@ #include "sol/print_config.h" #include "sol/message.h" #include "sol/transaction_summary.h" - -static uint8_t G_message[MAX_MESSAGE_LENGTH]; -static int G_messageLength; -uint8_t G_numDerivationPaths; -static uint32_t G_derivationPath[BIP32_PATH]; -static int G_derivationPathLength; - -void derive_private_key( - cx_ecfp_private_key_t *privateKey, - uint32_t *derivationPath, - uint8_t derivationPathLength -) { - uint8_t privateKeyData[32]; - BEGIN_TRY { - TRY { - os_perso_derive_node_bip32_seed_key( - HDW_ED25519_SLIP10, - CX_CURVE_Ed25519, - derivationPath, - derivationPathLength, - privateKeyData, - NULL, - (unsigned char*) "ed25519 seed", - 12 - ); - cx_ecfp_init_private_key(CX_CURVE_Ed25519, privateKeyData, 32, privateKey); - } - FINALLY { - MEMCLEAR(privateKeyData); - } - } - END_TRY; -} +#include "globals.h" +#include "apdu.h" static uint8_t set_result_sign_message() { - uint8_t tx = 64; uint8_t signature[SIGNATURE_LENGTH]; cx_ecfp_private_key_t privateKey; BEGIN_TRY { TRY { - derive_private_key(&privateKey, G_derivationPath, G_derivationPathLength); - cx_eddsa_sign( - &privateKey, - CX_LAST, - CX_SHA512, - G_message, - G_messageLength, - NULL, - 0, - signature, - SIGNATURE_LENGTH, - NULL - ); - memcpy(G_io_apdu_buffer, signature, 64); + get_private_key_with_seed(&privateKey, + G_command.derivation_path, + G_command.derivation_path_length); + cx_eddsa_sign(&privateKey, + CX_LAST, + CX_SHA512, + G_command.message, + G_command.message_length, + NULL, + 0, + signature, + SIGNATURE_LENGTH, + NULL); + memcpy(G_io_apdu_buffer, signature, SIGNATURE_LENGTH); + } + CATCH_OTHER(e) { + MEMCLEAR(privateKey); + THROW(e); } FINALLY { MEMCLEAR(privateKey); } } END_TRY; - return tx; + return SIGNATURE_LENGTH; } -////////////////////////////////////////////////////////////////////// - -UX_STEP_VALID( - ux_approve_step, - pb, - sendResponse(set_result_sign_message(), true), - { - &C_icon_validate_14, - "Approve", - }); -UX_STEP_VALID( - ux_reject_step, - pb, - sendResponse(0, false), - { - &C_icon_crossmark, - "Reject", - }); -UX_STEP_NOCB_INIT( - ux_summary_step, - bnnn_paging, - { - size_t step_index = G_ux.flow_stack[stack_slot].index; - enum DisplayFlags flags = DisplayFlagNone; - if (N_storage.settings.pubkey_display == PubkeyDisplayLong) { - flags |= DisplayFlagLongPubkeys; - } - if (transaction_summary_display_item(step_index, flags)) { - THROW(ApduReplySolanaSummaryUpdateFailed); - } - }, - { - .title = G_transaction_summary_title, - .text = G_transaction_summary_text, - } -); - -#define MAX_FLOW_STEPS ( \ - MAX_TRANSACTION_SUMMARY_ITEMS \ - + 1 /* approve */ \ - + 1 /* reject */ \ - + 1 /* FLOW_END_STEP */ \ -) -ux_flow_step_t const * flow_steps[MAX_FLOW_STEPS]; - -Hash UnrecognizedMessageHash; - -void handleSignMessage( - uint8_t p1, - uint8_t p2, - uint8_t *dataBuffer, - uint16_t dataLength, - volatile unsigned int *flags, - volatile unsigned int *tx -) { - UNUSED(tx); - - if (dataLength == 0) { - THROW(ApduReplySolanaInvalidMessage); - } - - int deprecated_host = ((dataLength & DATA_HAS_LENGTH_PREFIX) != 0); - - if (deprecated_host) { - dataLength &= ~DATA_HAS_LENGTH_PREFIX; - } - - if ((p2 & P2_EXTEND) == 0) { - MEMCLEAR(G_derivationPath); - MEMCLEAR(G_message); - G_messageLength = 0; - G_numDerivationPaths = 1; - - if (!deprecated_host) { - G_numDerivationPaths = dataBuffer[0]; - dataBuffer++; - dataLength--; - // We only support one derivation path ATM - if (G_numDerivationPaths != 1) { - THROW(ApduReplySdkExceptionOverflow); - } - } +static void send_result_sign_message(void) { + sendResponse(set_result_sign_message(), true); +} - G_derivationPathLength = read_derivation_path( - dataBuffer, - dataLength, - G_derivationPath - ); - dataBuffer += 1 + G_derivationPathLength * 4; - dataLength -= 1 + G_derivationPathLength * 4; - } else { - // P2_EXTEND is set to signal that this APDU buffer extends, rather - // than replaces, the current message buffer. Asserting it with the - // first APDU buffer is an error, since we haven't yet received a - // derivation path. - if (G_numDerivationPaths == 0) { - THROW(ApduReplySolanaInvalidMessage); - } - } +////////////////////////////////////////////////////////////////////// - int messageLength; - if (deprecated_host) { - messageLength = U2BE(dataBuffer, 0); - dataBuffer += 2; - if (messageLength != (dataLength - 2)) { - THROW(ApduReplySolanaInvalidMessage); +UX_STEP_CB(ux_approve_step, + pb, + send_result_sign_message(), + { + &C_icon_validate_14, + "Approve", + }); +UX_STEP_CB(ux_reject_step, + pb, + sendResponse(0, false), + { + &C_icon_crossmark, + "Reject", + }); +UX_STEP_NOCB_INIT(ux_summary_step, + bnnn_paging, + { + size_t step_index = G_ux.flow_stack[stack_slot].index; + enum DisplayFlags flags = DisplayFlagNone; + if (N_storage.settings.pubkey_display == PubkeyDisplayLong) { + flags |= DisplayFlagLongPubkeys; + } + if (transaction_summary_display_item(step_index, flags)) { + THROW(ApduReplySolanaSummaryUpdateFailed); + } + }, + { + .title = G_transaction_summary_title, + .text = G_transaction_summary_text, + }); + +#define MAX_FLOW_STEPS \ + (MAX_TRANSACTION_SUMMARY_ITEMS + 1 /* approve */ \ + + 1 /* reject */ \ + + 1 /* FLOW_END_STEP */ \ + ) +ux_flow_step_t const *flow_steps[MAX_FLOW_STEPS]; + +static int scan_header_for_signer(const uint32_t *derivation_path, + uint32_t derivation_path_length, + size_t *signer_index, + const MessageHeader *header) { + uint8_t signer_pubkey[PUBKEY_SIZE]; + get_public_key(signer_pubkey, derivation_path, derivation_path_length); + for (size_t i = 0; i < header->pubkeys_header.num_required_signatures; ++i) { + const Pubkey *current_pubkey = &(header->pubkeys[i]); + if (memcmp(current_pubkey, signer_pubkey, PUBKEY_SIZE) == 0) { + *signer_index = i; + return 0; } - } else { - messageLength = dataLength; - } - - if (G_messageLength + messageLength > MAX_MESSAGE_LENGTH) { - THROW(ApduReplySdkExceptionOverflow); } - memcpy(G_message + G_messageLength, dataBuffer, messageLength); - G_messageLength += messageLength; + return -1; +} - if (p2 & P2_MORE) { - THROW(ApduReplySuccess); +void handle_sign_message_parse_message(volatile unsigned int *tx) { + if (!tx || + (G_command.instruction != InsDeprecatedSignMessage && + G_command.instruction != InsSignMessage) || + G_command.state != ApduStatePayloadComplete) { + THROW(ApduReplySdkInvalidParameter); } - - // Host has signaled that the message is complete. We won't be receiving - // any more extending APDU buffers. Clear the derivation path count so we - // can detect P2_EXTEND misuse at the start of the next exchange - G_numDerivationPaths = 0; - - Parser parser = {G_message, G_messageLength}; + // Handle the transaction message signing + Parser parser = {G_command.message, G_command.message_length}; PrintConfig print_config; print_config.expert_mode = (N_storage.settings.display_mode == DisplayModeExpert); print_config.signer_pubkey = NULL; - MessageHeader* header = &print_config.header; - if (parse_message_header(&parser, header)) { + MessageHeader *header = &print_config.header; + size_t signer_index; + + if (parse_message_header(&parser, header) != 0) { // This is not a valid Solana message THROW(ApduReplySolanaInvalidMessage); - } else { - uint8_t signer_pubkey[32]; - getPublicKey(G_derivationPath, signer_pubkey, G_derivationPathLength); - size_t signer_count = header->pubkeys_header.num_required_signatures; - size_t i; - for (i = 0; i < signer_count; i++) { - const Pubkey* pubkey = &header->pubkeys[i]; - if (memcmp(pubkey, signer_pubkey, PUBKEY_SIZE) == 0) { - break; - } - } - if (i >= signer_count) { - THROW(ApduReplySdkInvalidParameter); - } - print_config.signer_pubkey = &header->pubkeys[i]; } - if (p1 == P1_NON_CONFIRM) { - // Uncomment this to allow blind signing. - //*tx = set_result_sign_message(); - //THROW(ApduReplySuccess); + // Ensure the requested signer is present in the header + if (scan_header_for_signer(G_command.derivation_path, + G_command.derivation_path_length, + &signer_index, + header) != 0) { + THROW(ApduReplySolanaInvalidMessageHeader); + } + print_config.signer_pubkey = &header->pubkeys[signer_index]; - sendResponse(0, false); + if (G_command.non_confirm) { + // Uncomment this to allow unattended signing. + //*tx = set_result_sign_message(); + // THROW(ApduReplySuccess); + UNUSED(tx); + THROW(ApduReplySdkNotSupported); } + // Set the transaction summary transaction_summary_reset(); - if (process_message_body(parser.buffer, parser.buffer_length, &print_config)) { + if (process_message_body(parser.buffer, parser.buffer_length, &print_config) != 0) { + // Message not processed, throw if blind signing is not enabled if (N_storage.settings.allow_blind_sign == BlindSignEnabled) { - SummaryItem* item = transaction_summary_primary_item(); + SummaryItem *item = transaction_summary_primary_item(); summary_item_set_string(item, "Unrecognized", "format"); - cx_hash_sha256( - G_message, - G_messageLength, - (uint8_t*) &UnrecognizedMessageHash, - HASH_LENGTH - ); + cx_hash_sha256(G_command.message, + G_command.message_length, + (uint8_t *) &G_command.message_hash, + HASH_LENGTH); item = transaction_summary_general_item(); - summary_item_set_hash(item, "Message Hash", &UnrecognizedMessageHash); + summary_item_set_hash(item, "Message Hash", &G_command.message_hash); } else { THROW(ApduReplySdkNotSupported); } } - const Pubkey* fee_payer = &header->pubkeys[0]; + // Add fee payer to summary if needed + const Pubkey *fee_payer = &header->pubkeys[0]; if (print_config_show_authority(&print_config, fee_payer)) { transaction_summary_set_fee_payer_pubkey(fee_payer); } +} - enum SummaryItemKind summary_step_kinds[MAX_TRANSACTION_SUMMARY_ITEMS]; +void handle_sign_message_ui(volatile unsigned int *flags) { + // Display the transaction summary + SummaryItemKind_t summary_step_kinds[MAX_TRANSACTION_SUMMARY_ITEMS]; size_t num_summary_steps = 0; - if (transaction_summary_finalize( - summary_step_kinds, - &num_summary_steps - ) == 0 - ) { + if (transaction_summary_finalize(summary_step_kinds, &num_summary_steps) == 0) { size_t num_flow_steps = 0; for (size_t i = 0; i < num_summary_steps; i++) { diff --git a/src/signMessage.h b/src/signMessage.h index 2359f7cf..40eed74d 100644 --- a/src/signMessage.h +++ b/src/signMessage.h @@ -5,15 +5,8 @@ #ifndef _SIGN_MESSAGE_H_ #define _SIGN_MESSAGE_H_ -extern uint8_t G_numDerivationPaths; +void handle_sign_message_parse_message(volatile unsigned int *tx); -void handleSignMessage( - uint8_t p1, - uint8_t p2, - uint8_t *dataBuffer, - uint16_t dataLength, - volatile unsigned int *flags, - volatile unsigned int *tx -); +void handle_sign_message_ui(volatile unsigned int *flags); #endif diff --git a/src/signOffchainMessage.c b/src/signOffchainMessage.c new file mode 100644 index 00000000..286930dd --- /dev/null +++ b/src/signOffchainMessage.c @@ -0,0 +1,253 @@ +#include "getPubkey.h" +#include "os.h" +#include "ux.h" +#include "cx.h" +#include "menu.h" +#include "utils.h" +#include "sol/parser.h" +#include "sol/printer.h" +#include "sol/print_config.h" +#include "sol/message.h" +#include "sol/transaction_summary.h" +#include "globals.h" +#include "apdu.h" + +/** + * Checks if data is in UTF-8 format. + * Adapted from: https://www.cl.cam.ac.uk/~mgk25/ucs/utf8_check.c + */ +bool is_data_utf8(const uint8_t *data, size_t length) { + if (!data) { + return false; + } + size_t i = 0; + while (i < length) { + if (data[i] < 0x80) { + /* 0xxxxxxx */ + ++i; + } else if ((data[i] & 0xe0) == 0xc0) { + /* 110XXXXx 10xxxxxx */ + if (i + 1 >= length || (data[i + 1] & 0xc0) != 0x80 || + (data[i] & 0xfe) == 0xc0) /* overlong? */ { + return false; + } else { + i += 2; + } + } else if ((data[i] & 0xf0) == 0xe0) { + /* 1110XXXX 10Xxxxxx 10xxxxxx */ + if (i + 2 >= length || (data[i + 1] & 0xc0) != 0x80 || (data[i + 2] & 0xc0) != 0x80 || + (data[i] == 0xe0 && (data[i + 1] & 0xe0) == 0x80) || /* overlong? */ + (data[i] == 0xed && (data[i + 1] & 0xe0) == 0xa0) || /* surrogate? */ + (data[i] == 0xef && data[i + 1] == 0xbf && + (data[i + 2] & 0xfe) == 0xbe)) /* U+FFFE or U+FFFF? */ { + return false; + } else { + i += 3; + } + } else if ((data[i] & 0xf8) == 0xf0) { + /* 11110XXX 10XXxxxx 10xxxxxx 10xxxxxx */ + if (i + 3 >= length || (data[i + 1] & 0xc0) != 0x80 || (data[i + 2] & 0xc0) != 0x80 || + (data[i + 3] & 0xc0) != 0x80 || + (data[i] == 0xf0 && (data[i + 1] & 0xf0) == 0x80) || /* overlong? */ + (data[i] == 0xf4 && data[i + 1] > 0x8f) || data[i] > 0xf4) /* > U+10FFFF? */ { + return false; + } else { + i += 4; + } + } else { + return false; + } + } + return true; +} + +/* + * Checks if data is in ASCII format + */ +static bool is_data_ascii(const uint8_t *data, size_t length) { + if (!data) { + return false; + } + for (size_t i = 0; i < length; ++i) { + if (data[i] < 0x20 || data[i] > 0x7e) { + return false; + } + } + return true; +} + +static uint8_t set_result_sign_message() { + uint8_t signature[SIGNATURE_LENGTH]; + cx_ecfp_private_key_t privateKey; + BEGIN_TRY { + TRY { + get_private_key_with_seed(&privateKey, + G_command.derivation_path, + G_command.derivation_path_length); + cx_eddsa_sign(&privateKey, + CX_LAST, + CX_SHA512, + G_command.message, + G_command.message_length, + NULL, + 0, + signature, + SIGNATURE_LENGTH, + NULL); + memcpy(G_io_apdu_buffer, signature, SIGNATURE_LENGTH); + } + CATCH_OTHER(e) { + MEMCLEAR(privateKey); + THROW(e); + } + FINALLY { + MEMCLEAR(privateKey); + } + } + END_TRY; + return SIGNATURE_LENGTH; +} + +////////////////////////////////////////////////////////////////////// + +UX_STEP_NOCB(ux_sign_msg_text_step, + bnnn_paging, + { + .title = "Message", + .text = (const char *) G_command.message + OFFCHAIN_MESSAGE_HEADER_LENGTH, + }); +UX_STEP_CB(ux_sign_msg_approve_step, + pb, + sendResponse(set_result_sign_message(), true), + { + &C_icon_validate_14, + "Approve", + }); +UX_STEP_CB(ux_sign_msg_reject_step, + pb, + sendResponse(0, false), + { + &C_icon_crossmark, + "Reject", + }); +UX_STEP_NOCB_INIT(ux_sign_msg_summary_step, + bnnn_paging, + { + size_t step_index = G_ux.flow_stack[stack_slot].index; + enum DisplayFlags flags = DisplayFlagNone; + if (N_storage.settings.pubkey_display == PubkeyDisplayLong) { + flags |= DisplayFlagLongPubkeys; + } + if (transaction_summary_display_item(step_index, flags)) { + THROW(ApduReplySolanaSummaryUpdateFailed); + } + }, + { + .title = G_transaction_summary_title, + .text = G_transaction_summary_text, + }); + +/* +UX Steps: +- Sign Message + +if expert mode: +- Version +- Format +- Size +- Hash +- Signer +else if utf8: +- Hash + +if ascii: +- message text +*/ +static ux_flow_step_t const *flow_steps[8]; + +void handle_sign_offchain_message(volatile unsigned int *flags, volatile unsigned int *tx) { + if (!tx || G_command.instruction != InsSignOffchainMessage || + G_command.state != ApduStatePayloadComplete) { + THROW(ApduReplySdkInvalidParameter); + } + + if (G_command.non_confirm) { + // Uncomment this to allow unattended signing. + //*tx = set_result_sign_message(); + // THROW(ApduReplySuccess); + UNUSED(tx); + THROW(ApduReplySdkNotSupported); + } + + // parse header + Parser parser = {G_command.message, G_command.message_length}; + OffchainMessageHeader header; + if (parse_offchain_message_header(&parser, &header)) { + THROW(ApduReplySolanaInvalidMessageHeader); + } + + // validate message + if (header.version != 0 || header.format > 1 || header.length > MAX_OFFCHAIN_MESSAGE_LENGTH || + header.length + OFFCHAIN_MESSAGE_HEADER_LENGTH != G_command.message_length) { + THROW(ApduReplySolanaInvalidMessageHeader); + } + const bool is_ascii = + is_data_ascii(G_command.message + OFFCHAIN_MESSAGE_HEADER_LENGTH, header.length); + const bool is_utf8 = + is_ascii ? true + : is_data_utf8(G_command.message + OFFCHAIN_MESSAGE_HEADER_LENGTH, header.length); + if (!is_ascii && (!is_utf8 || header.format == 0)) { + THROW(ApduReplySolanaInvalidMessageFormat); + } else if (!is_ascii && N_storage.settings.allow_blind_sign != BlindSignEnabled) { + THROW(ApduReplySdkNotSupported); + } + + // compute message hash if needed + if (!is_ascii || N_storage.settings.display_mode == DisplayModeExpert) { + cx_hash_sha256(G_command.message, + G_command.message_length, + (uint8_t *) &G_command.message_hash, + HASH_LENGTH); + } + + // fill out UX steps + transaction_summary_reset(); + SummaryItem *item = transaction_summary_primary_item(); + summary_item_set_string(item, "Sign", "Off-Chain Message"); + + if (N_storage.settings.display_mode == DisplayModeExpert) { + summary_item_set_u64(transaction_summary_general_item(), "Version", header.version); + summary_item_set_u64(transaction_summary_general_item(), "Format", header.format); + summary_item_set_u64(transaction_summary_general_item(), "Size", header.length); + summary_item_set_hash(transaction_summary_general_item(), "Hash", &G_command.message_hash); + + Pubkey signer_pubkey; + get_public_key(signer_pubkey.data, + G_command.derivation_path, + G_command.derivation_path_length); + summary_item_set_pubkey(transaction_summary_general_item(), "Signer", &signer_pubkey); + } else if (!is_ascii) { + summary_item_set_hash(transaction_summary_general_item(), "Hash", &G_command.message_hash); + } + + enum SummaryItemKind summary_step_kinds[MAX_TRANSACTION_SUMMARY_ITEMS]; + size_t num_flow_steps = 0; + size_t num_summary_steps = 0; + if (transaction_summary_finalize(summary_step_kinds, &num_summary_steps)) { + THROW(ApduReplySolanaSummaryFinalizeFailed); + } + for (size_t i = 0; i < num_summary_steps; i++) { + flow_steps[num_flow_steps++] = &ux_sign_msg_summary_step; + } + + if (is_ascii) { + flow_steps[num_flow_steps++] = &ux_sign_msg_text_step; + } + flow_steps[num_flow_steps++] = &ux_sign_msg_approve_step; + flow_steps[num_flow_steps++] = &ux_sign_msg_reject_step; + flow_steps[num_flow_steps++] = FLOW_END_STEP; + + ux_flow_init(0, flow_steps, NULL); + + *flags |= IO_ASYNCH_REPLY; +} diff --git a/src/signOffchainMessage.h b/src/signOffchainMessage.h new file mode 100644 index 00000000..dbfd23f4 --- /dev/null +++ b/src/signOffchainMessage.h @@ -0,0 +1,10 @@ +#include "os.h" +#include "cx.h" +#include "globals.h" + +#ifndef _SIGN_OFFCHAIN_MESSAGE_H_ +#define _SIGN_OFFCHAIN_MESSAGE_H_ + +void handle_sign_offchain_message(volatile unsigned int *flags, volatile unsigned int *tx); + +#endif diff --git a/src/utils.c b/src/utils.c index 3c85b46b..7ea9b056 100644 --- a/src/utils.c +++ b/src/utils.c @@ -5,57 +5,130 @@ #include "utils.h" #include "menu.h" -void getPublicKey( - uint32_t *derivationPath, - uint8_t *publicKeyArray, - uint8_t pathLength -) { +void get_public_key(uint8_t *publicKeyArray, const uint32_t *derivationPath, size_t pathLength) { cx_ecfp_private_key_t privateKey; cx_ecfp_public_key_t publicKey; - getPrivateKey(derivationPath, &privateKey, pathLength); - cx_ecfp_generate_pair(CX_CURVE_Ed25519, &publicKey, &privateKey, 1); - explicit_bzero(&privateKey, sizeof(privateKey)); + get_private_key(&privateKey, derivationPath, pathLength); + BEGIN_TRY { + TRY { + cx_ecfp_generate_pair(CX_CURVE_Ed25519, &publicKey, &privateKey, 1); + } + CATCH_OTHER(e) { + MEMCLEAR(privateKey); + THROW(e); + } + FINALLY { + MEMCLEAR(privateKey); + } + } + END_TRY; - for (int i = 0; i < 32; i++) { - publicKeyArray[i] = publicKey.W[64 - i]; + for (int i = 0; i < PUBKEY_LENGTH; i++) { + publicKeyArray[i] = publicKey.W[PUBKEY_LENGTH + PRIVATEKEY_LENGTH - i]; } - if ((publicKey.W[32] & 1) != 0) { - publicKeyArray[31] |= 0x80; + if ((publicKey.W[PUBKEY_LENGTH] & 1) != 0) { + publicKeyArray[PUBKEY_LENGTH - 1] |= 0x80; } } uint32_t readUint32BE(uint8_t *buffer) { - return ( - (buffer[0] << 24) | (buffer[1] << 16) | - (buffer[2] << 8) | (buffer[3]) - ); + return ((buffer[0] << 24) | (buffer[1] << 16) | (buffer[2] << 8) | (buffer[3])); +} + +void get_private_key(cx_ecfp_private_key_t *privateKey, + const uint32_t *derivationPath, + size_t pathLength) { + uint8_t privateKeyData[PRIVATEKEY_LENGTH]; + BEGIN_TRY { + TRY { + os_perso_derive_node_bip32_seed_key(HDW_ED25519_SLIP10, + CX_CURVE_Ed25519, + derivationPath, + pathLength, + privateKeyData, + NULL, + NULL, + 0); + cx_ecfp_init_private_key(CX_CURVE_Ed25519, + privateKeyData, + PRIVATEKEY_LENGTH, + privateKey); + } + CATCH_OTHER(e) { + MEMCLEAR(privateKeyData); + THROW(e); + } + FINALLY { + MEMCLEAR(privateKeyData); + } + } + END_TRY; +} + +void get_private_key_with_seed(cx_ecfp_private_key_t *privateKey, + const uint32_t *derivationPath, + uint8_t pathLength) { + uint8_t privateKeyData[PRIVATEKEY_LENGTH]; + BEGIN_TRY { + TRY { + os_perso_derive_node_bip32_seed_key(HDW_ED25519_SLIP10, + CX_CURVE_Ed25519, + derivationPath, + pathLength, + privateKeyData, + NULL, + (unsigned char *) "ed25519 seed", + 12); + cx_ecfp_init_private_key(CX_CURVE_Ed25519, + privateKeyData, + PRIVATEKEY_LENGTH, + privateKey); + } + CATCH_OTHER(e) { + MEMCLEAR(privateKeyData); + THROW(e); + } + FINALLY { + MEMCLEAR(privateKeyData); + } + } + END_TRY; } -void getPrivateKey( - uint32_t *derivationPath, - cx_ecfp_private_key_t *privateKey, - uint8_t pathLength -) { - uint8_t privateKeyData[32]; +int read_derivation_path(const uint8_t *data_buffer, + size_t data_size, + uint32_t *derivation_path, + uint32_t *derivation_path_length) { + if (!data_buffer || !derivation_path || !derivation_path_length) { + return ApduReplySdkInvalidParameter; + } + if (!data_size) { + return ApduReplySolanaInvalidMessageSize; + } + const size_t len = data_buffer[0]; + data_buffer += 1; + if (len < 1 || len > MAX_BIP32_PATH_LENGTH) { + return ApduReplySolanaInvalidMessage; + } + if (1 + 4 * len > data_size) { + return ApduReplySolanaInvalidMessageSize; + } + + for (size_t i = 0; i < len; i++) { + derivation_path[i] = ((data_buffer[0] << 24u) | (data_buffer[1] << 16u) | + (data_buffer[2] << 8u) | (data_buffer[3])); + data_buffer += 4; + } + + *derivation_path_length = len; - os_perso_derive_node_bip32_seed_key( - HDW_ED25519_SLIP10, - CX_CURVE_Ed25519, - derivationPath, - pathLength, - privateKeyData, - NULL, - NULL, - 0 - ); - cx_ecfp_init_private_key(CX_CURVE_Ed25519, privateKeyData, 32, privateKey); - explicit_bzero(privateKeyData, sizeof(privateKeyData)); + return 0; } void sendResponse(uint8_t tx, bool approve) { - G_io_apdu_buffer[tx++] = approve? 0x90 : 0x69; - G_io_apdu_buffer[tx++] = approve? 0x00 : 0x85; + G_io_apdu_buffer[tx++] = approve ? 0x90 : 0x69; + G_io_apdu_buffer[tx++] = approve ? 0x00 : 0x85; // Send back the response, do not restart the event loop io_exchange(CHANNEL_APDU | IO_RETURN_AFTER_TX, tx); // Display back the original UX @@ -69,13 +142,9 @@ unsigned int ui_prepro(const bagl_element_t *element) { if (display) { if (element->component.userid == 1) { UX_CALLBACK_SET_INTERVAL(2000); - } - else { + } else { UX_CALLBACK_SET_INTERVAL( - MAX( - 3000, - 1000 + bagl_label_roundtrip_duration_ms(element, 7) - )); + MAX(3000, 1000 + bagl_label_roundtrip_duration_ms(element, 7))); } } } diff --git a/src/utils.h b/src/utils.h index f7ae97f8..af8f2889 100644 --- a/src/utils.h +++ b/src/utils.h @@ -2,12 +2,13 @@ #include "cx.h" #include "globals.h" #include +#include "apdu.h" #ifndef _UTILS_H_ #define _UTILS_H_ // Marker flag for DEPRECATED ADPU exchange format -#define DATA_HAS_LENGTH_PREFIX (1 << 15) +#define DATA_HAS_LENGTH_PREFIX (1 << 15) typedef enum rlpTxType { TX_LENGTH = 0, @@ -20,51 +21,102 @@ typedef enum rlpTxType { unsigned int ui_prepro(const bagl_element_t *element); -void getPublicKey(uint32_t *derivationPath, uint8_t *publicKeyArray, uint8_t pathLength); +void get_public_key(uint8_t *publicKeyArray, const uint32_t *derivationPath, size_t pathLength); uint32_t readUint32BE(uint8_t *buffer); -void getPrivateKey(uint32_t *derivationPath, cx_ecfp_private_key_t *privateKey, uint8_t pathLength); +void get_private_key(cx_ecfp_private_key_t *privateKey, + const uint32_t *derivationPath, + size_t pathLength); + +void get_private_key_with_seed(cx_ecfp_private_key_t *privateKey, + const uint32_t *derivationPath, + uint8_t pathLength); + +/** + * Deserialize derivation path from raw bytes. + * + * @param[in] data_buffer + * Pointer to serialized bytes. + * @param[in] data_size + * Size of the data_buffer. + * @param[out] derivation_path + * Pointer to the target array to store deserialized data into. + * @param[out] derivation_path_length + * Pointer to the variable that will hold derivation path length. + * + * @return zero on success, ApduReply error code otherwise. + * + */ +int read_derivation_path(const uint8_t *data_buffer, + size_t data_size, + uint32_t *derivation_path, + uint32_t *derivation_path_length); void sendResponse(uint8_t tx, bool approve); - // type userid x y w h str rad fill fg bg fid iid txt touchparams... ] -#define UI_BUTTONS \ - {{BAGL_RECTANGLE , 0x00, 0, 0, 128, 32, 0, 0, BAGL_FILL, 0x000000, 0xFFFFFF, 0, 0}, NULL, 0, 0, 0, NULL, NULL, NULL},\ - {{BAGL_ICON , 0x00, 3, 12, 7, 7, 0, 0, 0 , 0xFFFFFF, 0x000000, 0, BAGL_GLYPH_ICON_CROSS }, NULL, 0, 0, 0, NULL, NULL, NULL },\ - {{BAGL_ICON , 0x00, 117, 13, 8, 6, 0, 0, 0 , 0xFFFFFF, 0x000000, 0, BAGL_GLYPH_ICON_CHECK }, NULL, 0, 0, 0, NULL, NULL, NULL } +// type userid x y w h str rad fill fg bg fid iid txt +// touchparams... ] +#define UI_BUTTONS \ + {{BAGL_RECTANGLE, 0x00, 0, 0, 128, 32, 0, 0, BAGL_FILL, 0x000000, 0xFFFFFF, 0, 0}, \ + NULL, \ + 0, \ + 0, \ + 0, \ + NULL, \ + NULL, \ + NULL}, \ + {{BAGL_ICON, 0x00, 3, 12, 7, 7, 0, 0, 0, 0xFFFFFF, 0x000000, 0, BAGL_GLYPH_ICON_CROSS}, \ + NULL, \ + 0, \ + 0, \ + 0, \ + NULL, \ + NULL, \ + NULL}, \ + { \ + {BAGL_ICON, 0x00, 117, 13, 8, 6, 0, 0, 0, 0xFFFFFF, 0x000000, 0, BAGL_GLYPH_ICON_CHECK}, \ + NULL, 0, 0, 0, NULL, NULL, NULL \ + } -#define UI_FIRST 1 +#define UI_FIRST 1 #define UI_SECOND 0 -#define UI_LABELINE(userId, text, isFirst, font, horizontalScrollSpeed) \ - { \ - { \ - BAGL_LABELINE, \ - (userId), \ - 23, \ - (isFirst) ? 12 : 26, \ - 82, \ - 12, \ - (horizontalScrollSpeed) ? BAGL_STROKE_FLAG_ONESHOT | 10 : 0, \ - 0, 0, 0xFFFFFF, 0x000000, \ - (font)|BAGL_FONT_ALIGNMENT_CENTER, \ - horizontalScrollSpeed \ - }, \ - (text), 0, 0, 0, NULL, NULL, NULL \ +#define UI_LABELINE(userId, text, isFirst, font, horizontalScrollSpeed) \ + { \ + {BAGL_LABELINE, \ + (userId), \ + 23, \ + (isFirst) ? 12 : 26, \ + 82, \ + 12, \ + (horizontalScrollSpeed) ? BAGL_STROKE_FLAG_ONESHOT | 10 : 0, \ + 0, \ + 0, \ + 0xFFFFFF, \ + 0x000000, \ + (font) | BAGL_FONT_ALIGNMENT_CENTER, \ + horizontalScrollSpeed}, \ + (text), 0, 0, 0, NULL, NULL, NULL \ } #endif #ifdef TEST #include -#define THROW(code) do { printf("error: %d", code); } while (0) +#define THROW(code) \ + do { \ + printf("error: %d", code); \ + } while (0) #define PRINTF(msg, arg) printf(msg, arg) -#define PIC(code) code +#define PIC(code) code //#define TARGET_NANOS 1 -#define TARGET_BLUE 1 +#define TARGET_BLUE 1 #define MEMCLEAR(dest) explicit_bzero(&dest, sizeof(dest)); #else -#define MEMCLEAR(dest) do { explicit_bzero(&dest, sizeof(dest)); } while (0) +#define MEMCLEAR(dest) \ + do { \ + explicit_bzero(&dest, sizeof(dest)); \ + } while (0) #include "bolos_target.h" -#endif // TEST +#endif // TEST diff --git a/tests/Cargo.lock b/tests/Cargo.lock index 87b2c959..866d59fc 100644 --- a/tests/Cargo.lock +++ b/tests/Cargo.lock @@ -2,84 +2,234 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + +[[package]] +name = "aead" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b613b8e1e3cf911a086f53f03bf286f52fd7a7258e4fa606f0ef220d39d8877" +dependencies = [ + "generic-array", +] + +[[package]] +name = "aes" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e8b47f52ea9bae42228d07ec09eb676433d7c4ed1ebdf0f1d1c29ed446f1ab8" +dependencies = [ + "cfg-if", + "cipher 0.3.0", + "cpufeatures", + "opaque-debug", +] + +[[package]] +name = "aes-gcm-siv" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589c637f0e68c877bbd59a4599bbe849cac8e5f3e4b5a3ebae8f528cd218dcdc" +dependencies = [ + "aead", + "aes", + "cipher 0.3.0", + "ctr", + "polyval", + "subtle", + "zeroize", +] + [[package]] name = "ahash" -version = "0.4.7" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "739f4a8db6605981345c5654f3a85b056ce52f37a39d34da03f25bf2151ea16e" +checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47" +dependencies = [ + "getrandom 0.2.8", + "once_cell", + "version_check", +] [[package]] name = "aho-corasick" -version = "0.7.9" +version = "0.7.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5e63fd144e18ba274ae7095c0197a870a7b9468abc801dd62f190d80817d2ec" +checksum = "cc936419f96fa211c1b9166887b38e5e40b19958e5b895be7c1f93adec7071ac" dependencies = [ "memchr", ] [[package]] -name = "arrayref" -version = "0.3.6" +name = "alloc-no-stdlib" +version = "2.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4c527152e37cf757a3f78aae5a06fbeefdb07ccc535c980a3208ee3060dd544" +checksum = "cc7bb162ec39d46ab1ca8c77bf72e890535becd1751bb45f64c597edb4c8c6b3" [[package]] -name = "arrayvec" -version = "0.5.1" +name = "alloc-stdlib" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cff77d8686867eceff3105329d4698d96c2391c176d5d03adc90c7389162b5b8" +checksum = "94fb8275041c72129eb51b7d0322c29b8387a0386127718b096429201a5d6ece" +dependencies = [ + "alloc-no-stdlib", +] [[package]] -name = "assert_matches" -version = "1.3.0" +name = "anyhow" +version = "1.0.66" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7deb0a829ca7bcfaf5da70b073a8d128619259a7be8216a355e23f00763059e5" +checksum = "216261ddc8289130e551ddcd5ce8a064710c0d064a4d2895c67151c92b5443f6" [[package]] -name = "atty" -version = "0.2.14" +name = "ark-bn254" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" +checksum = "ea691771ebbb28aea556c044e2e5c5227398d840cee0c34d4d20fa8eb2689e8c" dependencies = [ - "hermit-abi", - "libc", - "winapi 0.3.8", + "ark-ec", + "ark-ff", + "ark-std", ] [[package]] -name = "autocfg" -version = "1.0.0" +name = "ark-ec" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d" +checksum = "dea978406c4b1ca13c2db2373b05cc55429c3575b8b21f1b9ee859aa5b03dd42" +dependencies = [ + "ark-ff", + "ark-serialize", + "ark-std", + "derivative", + "num-traits", + "zeroize", +] [[package]] -name = "backtrace" -version = "0.3.45" +name = "ark-ff" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad235dabf00f36301792cfe82499880ba54c6486be094d1047b02bacb67c14e8" +checksum = "6b3235cc41ee7a12aaaf2c575a2ad7b46713a8a50bda2fc3b003a04845c05dd6" dependencies = [ - "backtrace-sys", - "cfg-if 0.1.10", - "libc", - "rustc-demangle", - "serde", + "ark-ff-asm", + "ark-ff-macros", + "ark-serialize", + "ark-std", + "derivative", + "num-bigint", + "num-traits", + "paste", + "rustc_version 0.3.3", + "zeroize", ] [[package]] -name = "backtrace-sys" -version = "0.1.33" +name = "ark-ff-asm" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e17b52e737c40a7d75abca20b29a19a0eb7ba9fc72c5a72dd282a0a3c2c0dc35" +checksum = "db02d390bf6643fb404d3d22d31aee1c4bc4459600aef9113833d17e786c6e44" dependencies = [ - "cc", + "quote", + "syn", +] + +[[package]] +name = "ark-ff-macros" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db2fd794a08ccb318058009eefdf15bcaaaaf6f8161eb3345f907222bac38b20" +dependencies = [ + "num-bigint", + "num-traits", + "quote", + "syn", +] + +[[package]] +name = "ark-serialize" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d6c2b318ee6e10f8c2853e73a83adc0ccb88995aa978d8a3408d492ab2ee671" +dependencies = [ + "ark-std", + "digest 0.9.0", +] + +[[package]] +name = "ark-std" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1df2c09229cbc5a028b1d70e00fdb2acee28b1055dfb5ca73eea49c5a25c4e7c" +dependencies = [ + "num-traits", + "rand 0.8.5", +] + +[[package]] +name = "array-bytes" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ad284aeb45c13f2fb4f084de4a420ebf447423bdf9386c0540ce33cb3ef4b8c" + +[[package]] +name = "arrayref" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4c527152e37cf757a3f78aae5a06fbeefdb07ccc535c980a3208ee3060dd544" + +[[package]] +name = "arrayvec" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8da52d66c7071e2e3fa2a1e5c6d088fec47b593032b254f5e980de8ea54454d6" + +[[package]] +name = "ascii" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eab1c04a571841102f5345a8fc0f6bb3d31c315dec879b5c6e42e40ce7ffa34e" + +[[package]] +name = "assert_matches" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b34d609dfbaf33d6889b2b7106d3ca345eacad44200913df5ba02bfd31d2ba9" + +[[package]] +name = "async-compression" +version = "0.3.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "942c7cd7ae39e91bde4820d74132e9862e62c2f386c3aa90ccf55949f5bad63a" +dependencies = [ + "brotli", + "flate2", + "futures-core", + "memchr", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "atty" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" +dependencies = [ + "hermit-abi", "libc", + "winapi", ] [[package]] -name = "base32" -version = "0.4.0" +name = "autocfg" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23ce669cd6c8588f79e15cf450314f9638f967fc5770ff1c7c1deb0925ea7cfa" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "base64" @@ -89,39 +239,46 @@ checksum = "3441f0f7b02788e948e47f457ca01f1d7e6d92c693bc132c22b087d3141c03ff" [[package]] name = "base64" -version = "0.13.0" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd" +checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" [[package]] name = "bincode" -version = "1.3.1" +version = "1.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f30d3a39baa26f9651f17b375061f3233dde33424a8b72b0dbe93a68a0bc896d" +checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" dependencies = [ - "byteorder", "serde", ] [[package]] name = "bitflags" -version = "1.2.1" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bitmaps" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" +checksum = "031043d04099746d8db04daf1fa424b2bc8bd69d92b25962dcde24da39ab64a2" +dependencies = [ + "typenum", +] [[package]] name = "blake3" -version = "0.3.8" +version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b64485778c4f16a6a5a9d335e80d449ac6c70cdd6a06d2af18a6f6f775a125b3" +checksum = "895adc16c8b3273fbbc32685a7d55227705eda08c01e77704020f3491924b44b" dependencies = [ "arrayref", "arrayvec", "cc", - "cfg-if 0.1.10", + "cfg-if", "constant_time_eq", - "crypto-mac 0.8.0", - "digest 0.9.0", + "digest 0.10.6", ] [[package]] @@ -131,7 +288,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" dependencies = [ "block-padding", - "generic-array 0.14.4", + "generic-array", +] + +[[package]] +name = "block-buffer" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69cce20737498f97b993470a6e536b8523f0af7892a4f928cceb1ac5e52ebe7e" +dependencies = [ + "generic-array", ] [[package]] @@ -142,60 +308,81 @@ checksum = "8d696c370c750c948ada61c69a0ee2cbbb9c50b1019ddb86d9317157a99c2cae" [[package]] name = "borsh" -version = "0.9.1" +version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18dda7dc709193c0d86a1a51050a926dc3df1cf262ec46a23a25dba421ea1924" +checksum = "15bf3650200d8bffa99015595e10f1fbd17de07abbc25bb067da79e769939bfa" dependencies = [ "borsh-derive", - "hashbrown", + "hashbrown 0.11.2", ] [[package]] name = "borsh-derive" -version = "0.9.1" +version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "684155372435f578c0fa1acd13ebbb182cc19d6b38b64ae7901da4393217d264" +checksum = "6441c552f230375d18e3cc377677914d2ca2b0d36e52129fe15450a2dce46775" dependencies = [ "borsh-derive-internal", "borsh-schema-derive-internal", - "proc-macro-crate", - "proc-macro2 1.0.24", - "syn 1.0.62", + "proc-macro-crate 0.1.5", + "proc-macro2", + "syn", ] [[package]] name = "borsh-derive-internal" -version = "0.9.1" +version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2102f62f8b6d3edeab871830782285b64cc1830168094db05c8e458f209bc5c3" +checksum = "5449c28a7b352f2d1e592a8a28bf139bc71afb0764a14f3c02500935d8c44065" dependencies = [ - "proc-macro2 1.0.24", - "quote 1.0.7", - "syn 1.0.62", + "proc-macro2", + "quote", + "syn", ] [[package]] name = "borsh-schema-derive-internal" -version = "0.9.1" +version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "196c978c4c9b0b142d446ef3240690bf5a8a33497074a113ff9a337ccb750483" +checksum = "cdbd5696d8bfa21d53d9fe39a714a18538bad11492a42d066dbbc395fb1951c0" dependencies = [ - "proc-macro2 1.0.24", - "quote 1.0.7", - "syn 1.0.62", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "brotli" +version = "3.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1a0b1dbcc8ae29329621f8d4f0d835787c1c38bb1401979b49d13b0b305ff68" +dependencies = [ + "alloc-no-stdlib", + "alloc-stdlib", + "brotli-decompressor", +] + +[[package]] +name = "brotli-decompressor" +version = "2.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59ad2d4653bf5ca36ae797b1f4bb4dbddb60ce49ca4aed8a2ce4829f60425b80" +dependencies = [ + "alloc-no-stdlib", + "alloc-stdlib", ] [[package]] name = "bs58" -version = "0.3.1" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "476e9cd489f9e121e02ffa6014a8ef220ecb15c05ed23fc34cca13925dc283fb" +checksum = "771fe0050b883fcc3ea2359b1a96bcfbc090b7116eae7c3c512c7a083fdf23d3" [[package]] name = "bumpalo" -version = "3.2.0" +version = "3.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f359dc14ff8911330a51ef78022d376f25ed00248912803b58f00cb1c27f742" +checksum = "572f695136211188308f16ad2ca5c851a712c464060ae6974944458eb83880ba" [[package]] name = "bv" @@ -208,49 +395,46 @@ dependencies = [ ] [[package]] -name = "byteorder" -version = "1.3.4" +name = "bytemuck" +version = "1.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de" +checksum = "aaa3a8d9a1ca92e282c96a32d6511b695d7d994d1d102ba85d279f9b2756947f" +dependencies = [ + "bytemuck_derive", +] [[package]] -name = "bytes" -version = "0.4.12" +name = "bytemuck_derive" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "206fdffcfa2df7cbe15601ef46c813fce0965eb3286db6b56c583b814b51c81c" +checksum = "5fe233b960f12f8007e3db2d136e3cb1c291bfd7396e384ee76025fc1a3932b4" dependencies = [ - "byteorder", - "either", - "iovec", + "proc-macro2", + "quote", + "syn", ] [[package]] -name = "bytes" -version = "0.5.4" +name = "byteorder" +version = "1.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "130aac562c0dd69c56b3b1cc8ffd2e17be31d0b6c25b61c96b76231aa23e39e1" +checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" [[package]] name = "bytes" -version = "1.0.1" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b700ce4376041dcd0a327fd0097c41095743c4c8af8887265942faf1100bd040" +checksum = "dfb24e866b15a1af2a1b663f10c6b6b8f397a84aadb828f12e5b289ec23a3a3c" [[package]] name = "cc" -version = "1.0.69" +version = "1.0.77" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e70cc2f62c6ce1868963827bd677764c62d07c3d9a3e1fb1177ee1a9ab199eb2" +checksum = "e9f73505338f7d905b19d18738976aae232eb46b8efc15554ffc56deb5d9ebe4" dependencies = [ "jobserver", ] -[[package]] -name = "cfg-if" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" - [[package]] name = "cfg-if" version = "1.0.0" @@ -259,114 +443,145 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "chrono" -version = "0.4.11" +version = "0.4.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80094f509cf8b5ae86a4966a39b3ff66cd7e2a3e594accec3743ff3fabeab5b2" +checksum = "16b0a3d9ed01224b22057780a37bb8c5dbfe1be8ba48678e7bf57ec4b385411f" dependencies = [ "num-integer", "num-traits", - "serde", - "time", ] [[package]] -name = "cloudabi" -version = "0.0.3" +name = "cipher" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" +checksum = "7ee52072ec15386f770805afd189a01c8841be8696bed250fa2f13c4c0d6dfb7" dependencies = [ - "bitflags", + "generic-array", ] [[package]] -name = "console" -version = "0.11.3" +name = "cipher" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c0994e656bba7b922d8dd1245db90672ffb701e684e45be58f20719d69abc5a" +checksum = "d1873270f8f7942c191139cb8a40fd228da6c3fd2fc376d7e92d47aa14aeb59e" dependencies = [ - "encode_unicode", - "lazy_static", - "libc", - "regex", - "terminal_size", - "termios", - "unicode-width", - "winapi 0.3.8", - "winapi-util", + "crypto-common", + "inout", +] + +[[package]] +name = "combine" +version = "3.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da3da6baa321ec19e1cc41d31bf599f00c783d0517095cdaf0332e3fe8d20680" +dependencies = [ + "ascii", + "byteorder", + "either", + "memchr", + "unreachable", ] [[package]] name = "console" -version = "0.14.1" +version = "0.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3993e6445baa160675931ec041a5e03ca84b9c6e32a056150d3aa2bdda0a1f45" +checksum = "c050367d967ced717c04b65d8c619d863ef9292ce0c5760028655a2fb298718c" dependencies = [ "encode_unicode", "lazy_static", "libc", - "regex", "terminal_size", "unicode-width", - "winapi 0.3.8", + "winapi", +] + +[[package]] +name = "console_error_panic_hook" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a06aeb73f470f66dcdbf7223caeebb85984942f22f1adb2a088cf9668146bbbc" +dependencies = [ + "cfg-if", + "wasm-bindgen", +] + +[[package]] +name = "console_log" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "501a375961cef1a0d44767200e66e4a559283097e91d0730b1d75dfb2f8a1494" +dependencies = [ + "log", + "web-sys", ] [[package]] name = "constant_time_eq" -version = "0.1.5" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" +checksum = "f3ad85c1f65dc7b37604eb0e89748faf0b9653065f2a8ef69f96a687ec1e9279" [[package]] -name = "cpuid-bool" -version = "0.1.2" +name = "cpufeatures" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8aebca1129a03dc6dc2b127edd729435bbc4a37e1d5f4d7513165089ceb02634" +checksum = "28d997bd5e24a5928dd43e46dc529867e207907fe0b239c3477d924f7f2ca320" +dependencies = [ + "libc", +] [[package]] -name = "crossbeam-deque" -version = "0.7.3" +name = "crc32fast" +version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f02af974daeee82218205558e51ec8768b48cf524bd01d550abe5573a608285" +checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" dependencies = [ - "crossbeam-epoch", + "cfg-if", +] + +[[package]] +name = "crossbeam-channel" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2dd04ddaf88237dc3b8d8f9a3c1004b506b54b3313403944054d23c0870c521" +dependencies = [ + "cfg-if", "crossbeam-utils", - "maybe-uninit", ] [[package]] -name = "crossbeam-epoch" +name = "crossbeam-deque" version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "058ed274caafc1f60c4997b5fc07bf7dc7cca454af7c6e81edffe5f33f70dace" +checksum = "715e8152b692bba2d374b53d4875445368fdf21a94751410af607a5ac677d1fc" dependencies = [ - "autocfg", - "cfg-if 0.1.10", + "cfg-if", + "crossbeam-epoch", "crossbeam-utils", - "lazy_static", - "maybe-uninit", - "memoffset", - "scopeguard", ] [[package]] -name = "crossbeam-queue" -version = "0.2.1" +name = "crossbeam-epoch" +version = "0.9.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c695eeca1e7173472a32221542ae469b3e9aac3a4fc81f7696bcad82029493db" +checksum = "01a9af1f4c2ef74bb8aa1f7e19706bc72d03598c8a570bb5de72243c7a9d9d5a" dependencies = [ - "cfg-if 0.1.10", + "autocfg", + "cfg-if", "crossbeam-utils", + "memoffset 0.7.1", + "scopeguard", ] [[package]] name = "crossbeam-utils" -version = "0.7.2" +version = "0.8.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3c7c73a2d1e9fc0886a08b93e98eb643461230d5f1925e4036204d5f2e261a8" +checksum = "4fb766fa798726286dbbb842f174001dab8abc7b627a1dd86e0b7222a95d929f" dependencies = [ - "autocfg", - "cfg-if 0.1.10", - "lazy_static", + "cfg-if", ] [[package]] @@ -376,117 +591,108 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" [[package]] -name = "crypto-mac" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b584a330336237c1eecd3e94266efb216c56ed91225d634cb2991c5f3fd1aeab" -dependencies = [ - "generic-array 0.14.4", - "subtle", -] - -[[package]] -name = "crypto-mac" -version = "0.9.1" +name = "crypto-common" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58bcd97a54c7ca5ce2f6eb16f6bede5b0ab5f0055fedc17d2f0b4466e21671ca" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" dependencies = [ - "generic-array 0.14.4", - "subtle", + "generic-array", + "typenum", ] [[package]] name = "crypto-mac" -version = "0.10.0" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4857fd85a0c34b3c3297875b747c1e02e06b6a0ea32dd892d8192b9ce0813ea6" +checksum = "b584a330336237c1eecd3e94266efb216c56ed91225d634cb2991c5f3fd1aeab" dependencies = [ - "generic-array 0.14.4", + "generic-array", "subtle", ] [[package]] -name = "curve25519-dalek" -version = "2.1.0" +name = "ctr" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d85653f070353a16313d0046f173f70d1aadd5b42600a14de626f0dfb3473a5" -dependencies = [ - "byteorder", - "digest 0.8.1", - "rand_core 0.5.1", - "subtle", - "zeroize", +checksum = "049bb91fb4aaf0e3c7efa6cd5ef877dbbbd15b39dad06d9948de4ec8a75761ea" +dependencies = [ + "cipher 0.3.0", ] [[package]] name = "curve25519-dalek" -version = "3.0.2" +version = "3.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f627126b946c25a4638eec0ea634fc52506dea98db118aae985118ce7c3d723f" +checksum = "90f9d052967f590a76e62eb387bd0bbb1b000182c3cefe5364db6b7211651bc0" dependencies = [ "byteorder", "digest 0.9.0", "rand_core 0.5.1", + "serde", "subtle", "zeroize", ] [[package]] name = "derivation-path" -version = "0.1.3" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "193388a8c8c75a490b604ff61775e236541b8975e98e5ca1f6ea97d122b7e2db" -dependencies = [ - "failure", -] +checksum = "6e5c37193a1db1d8ed868c03ec7b152175f26160a5b740e5e484143877e0adf0" [[package]] name = "derivative" -version = "2.1.1" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb582b60359da160a9477ee80f15c8d784c477e69c217ef2cdd4169c24ea380f" +checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" dependencies = [ - "proc-macro2 1.0.24", - "quote 1.0.7", - "syn 1.0.62", + "proc-macro2", + "quote", + "syn", ] [[package]] name = "dialoguer" -version = "0.6.2" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4aa86af7b19b40ef9cbef761ed411a49f0afa06b7b6dcd3dfe2f96a3c546138" +checksum = "a92e7e37ecef6857fdc0c0c5d42fd5b0938e46590c2183cc92dd310a6d078eb1" dependencies = [ - "console 0.11.3", - "lazy_static", + "console", "tempfile", + "zeroize", ] [[package]] name = "digest" -version = "0.8.1" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5" +checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" dependencies = [ - "generic-array 0.12.3", + "generic-array", ] [[package]] name = "digest" -version = "0.9.0" +version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" +checksum = "8168378f4e5023e7218c89c891c0fd8ecdb5e5e4f18cb78f38cf245dd021e76f" dependencies = [ - "generic-array 0.14.4", + "block-buffer 0.10.3", + "crypto-common", + "subtle", ] +[[package]] +name = "eager" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "abe71d579d1812060163dff96056261deb5bf6729b100fa2e36a68b9649ba3d3" + [[package]] name = "ed25519" -version = "1.0.1" +version = "1.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf038a7b6fd7ef78ad3348b63f3a17550877b0e28f8d68bcc94894d1412158bc" +checksum = "1e9c280362032ea4203659fc489832d0204ef09f247a0506f170dafcac08c369" dependencies = [ - "serde", "signature", ] @@ -496,33 +702,31 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c762bae6dcaf24c4c84667b8579785430908723d5c889f469d76a41d59cc7a9d" dependencies = [ - "curve25519-dalek 3.0.2", + "curve25519-dalek", "ed25519", - "rand", + "rand 0.7.3", "serde", - "serde_bytes", - "sha2", + "sha2 0.9.9", "zeroize", ] [[package]] name = "ed25519-dalek-bip32" -version = "0.1.1" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "057f328f31294b5ab432e6c39642f54afd1531677d6d4ba2905932844cc242f3" +checksum = "9d2be62a4061b872c8c0873ee4fc6f101ce7b889d039f019c5fa2af471a59908" dependencies = [ "derivation-path", "ed25519-dalek", - "failure", - "hmac 0.9.0", - "sha2", + "hmac 0.12.1", + "sha2 0.10.6", ] [[package]] name = "either" -version = "1.5.3" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb1f6b1ce1c140482ea30ddd3335fc0024ac7ee112895426e0a629a6c20adfe3" +checksum = "90e5c1c8368803113bf0c9584fc495a58b86dc8a29edbf8fe877d21d9507e797" [[package]] name = "encode_unicode" @@ -532,18 +736,38 @@ checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" [[package]] name = "encoding_rs" -version = "0.8.22" +version = "0.8.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9852635589dc9f9ea1b6fe9f05b50ef208c85c834a562f0c6abb1c475736ec2b" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "enum-iterator" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91a4ec26efacf4aeff80887a175a419493cb6f8b5480d26387eb0bd038976187" +dependencies = [ + "enum-iterator-derive", +] + +[[package]] +name = "enum-iterator-derive" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd8d03faa7fe0c1431609dfad7bbe827af30f82e1e2ae6f7ee4fca6bd764bc28" +checksum = "828de45d0ca18782232dfb8f3ea9cc428e8ced380eb26a520baaacfc70de39ce" dependencies = [ - "cfg-if 0.1.10", + "proc-macro2", + "quote", + "syn", ] [[package]] name = "env_logger" -version = "0.8.3" +version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17392a012ea30ef05a610aa97dfb49496e71c9f676b27879922ea5bdf60d9d3f" +checksum = "a12e6657c4c97ebab115a42dcee77225f7f482cdd841cf7088c657a42e9e00e7" dependencies = [ "atty", "humantime", @@ -553,25 +777,12 @@ dependencies = [ ] [[package]] -name = "failure" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d32e9bd16cc02eae7db7ef620b392808b89f6a5e16bb3497d159c6b92a0f4f86" -dependencies = [ - "backtrace", - "failure_derive", -] - -[[package]] -name = "failure_derive" -version = "0.1.7" +name = "fastrand" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "030a733c8287d6213886dd487564ff5c8f6aae10278b3588ed177f9d18f8d231" +checksum = "a7a407cfaa3385c4ae6b23e84623d48c2798d06e3e6a1878f7f59f17b3f86499" dependencies = [ - "proc-macro2 1.0.24", - "quote 1.0.7", - "syn 1.0.62", - "synstructure", + "instant", ] [[package]] @@ -580,6 +791,16 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "835a3dc7d1ec9e75e2b5fb4ba75396837112d2060b03f7d43bc1897c7f7211da" +[[package]] +name = "flate2" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f82b0f4c27ad9f8bfd1f3208d882da2b09c301bc1c828fd3a00d0216d2fbbff6" +dependencies = [ + "crc32fast", + "miniz_oxide", +] + [[package]] name = "fnv" version = "1.0.7" @@ -588,147 +809,126 @@ checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" [[package]] name = "form_urlencoded" -version = "1.0.1" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fc25a87fa4fd2094bffb06925852034d90a17f0d1e05197d4956d3555752191" +checksum = "a9c384f161156f5260c24a097c56119f9be8c798586aecc13afbcbe7b7e26bf8" dependencies = [ - "matches", "percent-encoding", ] -[[package]] -name = "fuchsia-zircon" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" -dependencies = [ - "bitflags", - "fuchsia-zircon-sys", -] - -[[package]] -name = "fuchsia-zircon-sys" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" - -[[package]] -name = "futures" -version = "0.1.29" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b980f2816d6ee8673b6517b52cb0e808a180efc92e5c19d02cdda79066703ef" - [[package]] name = "futures-channel" -version = "0.3.13" +version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c2dd2df839b57db9ab69c2c9d8f3e8c81984781937fe2807dc6dcf3b2ad2939" +checksum = "52ba265a92256105f45b719605a571ffe2d1f0fea3807304b522c1d778f79eed" dependencies = [ "futures-core", ] [[package]] name = "futures-core" -version = "0.3.13" +version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15496a72fabf0e62bdc3df11a59a3787429221dd0710ba8ef163d6f7a9112c94" +checksum = "04909a7a7e4633ae6c4a9ab280aeb86da1236243a77b694a49eacd659a4bd3ac" [[package]] name = "futures-io" -version = "0.3.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d71c2c65c57704c32f5241c1223167c2c3294fd34ac020c807ddbe6db287ba59" - -[[package]] -name = "futures-macro" -version = "0.3.13" +version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea405816a5139fb39af82c2beb921d52143f556038378d6db21183a5c37fbfb7" -dependencies = [ - "proc-macro-hack", - "proc-macro2 1.0.24", - "quote 1.0.7", - "syn 1.0.62", -] +checksum = "00f5fb52a06bdcadeb54e8d3671f8888a39697dcb0b81b23b55174030427f4eb" [[package]] name = "futures-sink" -version = "0.3.13" +version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85754d98985841b7d4f5e8e6fbfa4a4ac847916893ec511a2917ccd8525b8bb3" +checksum = "39c15cf1a4aa79df40f1bb462fb39676d0ad9e366c2a33b590d7c66f4f81fcf9" [[package]] name = "futures-task" -version = "0.3.13" +version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa189ef211c15ee602667a6fcfe1c1fd9e07d42250d2156382820fba33c9df80" +checksum = "2ffb393ac5d9a6eaa9d3fdf37ae2776656b706e200c8e16b1bdb227f5198e6ea" [[package]] name = "futures-util" -version = "0.3.13" +version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1812c7ab8aedf8d6f2701a43e1243acdbcc2b36ab26e2ad421eb99ac963d96d1" +checksum = "197676987abd2f9cadff84926f410af1c183608d36641465df73ae8211dc65d6" dependencies = [ "futures-core", "futures-io", - "futures-macro", "futures-task", "memchr", "pin-project-lite", "pin-utils", - "proc-macro-hack", - "proc-macro-nested", "slab", ] [[package]] name = "generic-array" -version = "0.12.3" +version = "0.14.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c68f0274ae0e023facc3c97b2e00f076be70e254bc851d972503b328db79b2ec" +checksum = "bff49e947297f3312447abdca79f45f4738097cc82b06e72054d2223f601f1b9" dependencies = [ + "serde", "typenum", + "version_check", ] [[package]] -name = "generic-array" -version = "0.14.4" +name = "gethostname" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "501466ecc8a30d1d3b7fc9229b122b2ce8ed6e9d9223f1138d4babb253e51817" +checksum = "c1ebd34e35c46e00bb73e81363248d627782724609fe1b6396f553f68fe3862e" dependencies = [ - "serde", - "typenum", - "version_check", + "libc", + "winapi", ] [[package]] -name = "gethostname" -version = "0.2.1" +name = "getrandom" +version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e692e296bfac1d2533ef168d0b60ff5897b8b70a4009276834014dd8924cc028" +checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" dependencies = [ + "cfg-if", + "js-sys", "libc", - "winapi 0.3.8", + "wasi 0.9.0+wasi-snapshot-preview1", + "wasm-bindgen", ] [[package]] name = "getrandom" -version = "0.1.14" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7abc8dd8451921606d809ba32e95b6111925cd2906060d2dcc29c070220503eb" +checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31" dependencies = [ - "cfg-if 0.1.10", + "cfg-if", + "js-sys", "libc", - "wasi", + "wasi 0.11.0+wasi-snapshot-preview1", + "wasm-bindgen", +] + +[[package]] +name = "goblin" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7666983ed0dd8d21a6f6576ee00053ca0926fb281a5522577a4dbd0f1b54143" +dependencies = [ + "log", + "plain", + "scroll", ] [[package]] name = "h2" -version = "0.3.2" +version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc018e188373e2777d0ef2467ebff62a08e66c3f5857b23c8fbec3018210dc00" +checksum = "5f9f29bc9dda355256b2916cf526ab02ce0aeaaaf2bad60d65ef3f12f11dd0f4" dependencies = [ - "bytes 1.0.1", + "bytes", "fnv", "futures-core", "futures-sink", @@ -736,44 +936,63 @@ dependencies = [ "http", "indexmap", "slab", - "tokio 1.4.0", + "tokio", "tokio-util", "tracing", ] +[[package]] +name = "hash32" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0c35f58762feb77d74ebe43bdbc3210f09be9fe6742234d573bacc26ed92b67" +dependencies = [ + "byteorder", +] + [[package]] name = "hashbrown" -version = "0.9.1" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" +dependencies = [ + "ahash", +] + +[[package]] +name = "hashbrown" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7afe4a420e3fe79967a00898cc1f4db7c8a49a9333a29f8a4bd76a253d5cd04" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" dependencies = [ "ahash", ] [[package]] name = "hermit-abi" -version = "0.1.8" +version = "0.1.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1010591b26bbfe835e9faeabeb11866061cc7dcebffd56ad7d0942d0e61aefd8" +checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" dependencies = [ "libc", ] [[package]] name = "hex" -version = "0.4.2" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "644f9158b2f133fd50f5fb3242878846d9eb792e445c893805ff0e3824006e35" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" [[package]] name = "hidapi" -version = "1.2.5" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76c352a18370f7e7e47bcbfcbdc5432b8c80c705b5d751a25232c659fcf5c775" +checksum = "798154e4b6570af74899d71155fb0072d5b17e6aa12f39c8ef22c60fb8ec99e7" dependencies = [ "cc", "libc", "pkg-config", + "winapi", ] [[package]] @@ -782,28 +1001,17 @@ version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "126888268dcc288495a26bf004b38c5fdbb31682f992c84ceb046a1f0fe38840" dependencies = [ - "crypto-mac 0.8.0", - "digest 0.9.0", -] - -[[package]] -name = "hmac" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "deae6d9dbb35ec2c502d62b8f7b1c000a0822c3b0794ba36b3149c0a1c840dff" -dependencies = [ - "crypto-mac 0.9.1", + "crypto-mac", "digest 0.9.0", ] [[package]] name = "hmac" -version = "0.10.1" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1441c6b1e930e2817404b5046f1f989899143a12bf92de603b69f4e0aee1e15" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" dependencies = [ - "crypto-mac 0.10.0", - "digest 0.9.0", + "digest 0.10.6", ] [[package]] @@ -813,57 +1021,57 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "17ea0a1394df5b6574da6e0c1ade9e78868c9fb0a4e5ef4428e32da4676b85b1" dependencies = [ "digest 0.9.0", - "generic-array 0.14.4", + "generic-array", "hmac 0.8.1", ] [[package]] name = "http" -version = "0.2.0" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b708cc7f06493459026f53b9a61a7a121a5d1ec6238dee58ea4941132b30156b" +checksum = "75f43d41e26995c17e71ee126451dd3941010b0514a81a9d11f3b341debc2399" dependencies = [ - "bytes 0.5.4", + "bytes", "fnv", "itoa", ] [[package]] name = "http-body" -version = "0.4.1" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5dfb77c123b4e2f72a2069aeae0b4b4949cc7e966df277813fc16347e7549737" +checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1" dependencies = [ - "bytes 1.0.1", + "bytes", "http", "pin-project-lite", ] [[package]] name = "httparse" -version = "1.3.4" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd179ae861f0c2e53da70d892f5f3029f9594be0c41dc5269cd371691b1dc2f9" +checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" [[package]] name = "httpdate" -version = "0.3.2" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "494b4d60369511e7dea41cf646832512a94e542f68bb9c49e54518e0f468eb47" +checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421" [[package]] name = "humantime" -version = "2.0.1" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c1ad908cc71012b7bea4d0c53ba96a8cba9962f048fa68d143376143d863b7a" +checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" [[package]] name = "hyper" -version = "0.14.4" +version = "0.14.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8e946c2b1349055e0b72ae281b238baf1a3ea7307c7e9f9d64673bdd9c26ac7" +checksum = "034711faac9d2166cb1baf1a2fb0b60b1f277f8492fd72176c17f3515e1abd3c" dependencies = [ - "bytes 1.0.1", + "bytes", "futures-channel", "futures-core", "futures-util", @@ -873,9 +1081,9 @@ dependencies = [ "httparse", "httpdate", "itoa", - "pin-project", + "pin-project-lite", "socket2", - "tokio 1.4.0", + "tokio", "tower-service", "tracing", "want", @@ -883,102 +1091,117 @@ dependencies = [ [[package]] name = "hyper-rustls" -version = "0.22.1" +version = "0.23.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f9f7a97316d44c0af9b0301e65010573a853a9fc97046d7331d7f6bc0fd5a64" +checksum = "59df7c4e19c950e6e0e868dcc0a300b09a9b88e9ec55bd879ca819087a77355d" dependencies = [ - "futures-util", + "http", "hyper", - "log", "rustls", - "tokio 1.4.0", + "tokio", "tokio-rustls", - "webpki", ] [[package]] name = "idna" -version = "0.2.0" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02e2673c30ee86b5b96a9cb52ad15718aa1f966f5ab9ad54a8b95d5ca33120a9" +checksum = "e14ddfc70884202db2244c223200c204c2bda1bc6e0998d11b5e024d657209e6" dependencies = [ - "matches", "unicode-bidi", "unicode-normalization", ] +[[package]] +name = "im" +version = "15.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0acd33ff0285af998aaf9b57342af478078f53492322fafc47450e09397e0e9" +dependencies = [ + "bitmaps", + "rand_core 0.6.4", + "rand_xoshiro", + "rayon", + "serde", + "sized-chunks", + "typenum", + "version_check", +] + [[package]] name = "indexmap" -version = "1.6.2" +version = "1.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "824845a0bf897a9042383849b02c1bc219c2383772efcd5c6f9766fa4b81aef3" +checksum = "1885e79c1fc4b10f0e172c475f458b7f7b93061064d98c3293e98c5ba0c8b399" dependencies = [ "autocfg", - "hashbrown", + "hashbrown 0.12.3", ] [[package]] -name = "iovec" -version = "0.1.4" +name = "inout" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2b3ea6ff95e175473f8ffe6a7eb7c00d054240321b84c57051175fe3c1e075e" +checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5" dependencies = [ - "libc", + "generic-array", +] + +[[package]] +name = "instant" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" +dependencies = [ + "cfg-if", ] [[package]] name = "ipnet" -version = "2.3.0" +version = "2.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47be2f14c678be2fdcab04ab1171db51b2762ce6f0a8ee87c8dd4a04ed216135" +checksum = "f88c5561171189e69df9d98bcf18fd5f9558300f7ea7b801eb8a0fd748bd8745" [[package]] name = "itertools" -version = "0.9.0" +version = "0.10.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "284f18f85651fe11e8a991b2adb42cb078325c996ed026d994719efcfca1d54b" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" dependencies = [ "either", ] [[package]] name = "itoa" -version = "0.4.5" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8b7a7c0c47db5545ed3fef7468ee7bb5b74691498139e4b3f6a20685dc6dd8e" +checksum = "4217ad341ebadf8d8e724e264f13e593e0648f5b3e94b3896a5df283be015ecc" [[package]] name = "jobserver" -version = "0.1.21" +version = "0.1.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c71313ebb9439f74b00d9d2dcec36440beaf57a6aa0623068441dd7cd81a7f2" +checksum = "068b1ee6743e4d11fb9c6a1e6064b3693a1b600e7f5f5988047d98b3dc9fb90b" dependencies = [ "libc", ] [[package]] name = "js-sys" -version = "0.3.48" +version = "0.3.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc9f84f9b115ce7843d60706df1422a916680bfdfcbdb0447c5614ff9d7e4d78" +checksum = "49409df3e3bf0856b916e2ceaca09ee28e6871cf7d9ce97a692cacfdb2a25a47" dependencies = [ "wasm-bindgen", ] [[package]] name = "keccak" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67c21572b4949434e4fc1e1978b99c5f77064153c59d998bf13ecd96fb5ecba7" - -[[package]] -name = "kernel32-sys" -version = "0.2.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" +checksum = "3afef3b6eff9ce9d8ff9b3601125eec7f0c8cbac7abd14f355d053fa56c98768" dependencies = [ - "winapi 0.2.8", - "winapi-build", + "cpufeatures", ] [[package]] @@ -986,20 +1209,16 @@ name = "lazy_static" version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" -dependencies = [ - "spin", -] [[package]] name = "ledger-app-solana-tests" -version = "0.1.0" +version = "0.2.0" dependencies = [ "hex", - "rand", + "rand 0.7.3", "solana-logger", "solana-remote-wallet", "solana-sdk", - "solana-stake-program", "solana-vote-program", "spl-associated-token-account", "spl-memo", @@ -1008,15 +1227,25 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.88" +version = "0.2.137" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc7fcc620a3bff7cdd7a365be3376c97191aeaccc2a603e600951e452615bf89" + +[[package]] +name = "libloading" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03b07a082330a35e43f63177cc01689da34fbffa0105e1246cf0311472cac73a" +checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f" +dependencies = [ + "cfg-if", + "winapi", +] [[package]] name = "libsecp256k1" -version = "0.5.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd1137239ab33b41aa9637a88a28249e5e70c40a42ccc92db7f12cc356c1fcd7" +checksum = "c9d220bc1feda2ac231cb78c3d26f27676b8cf82c96971f7aeef3d0cf2797c73" dependencies = [ "arrayref", "base64 0.12.3", @@ -1025,17 +1254,17 @@ dependencies = [ "libsecp256k1-core", "libsecp256k1-gen-ecmult", "libsecp256k1-gen-genmult", - "rand", + "rand 0.7.3", "serde", - "sha2", + "sha2 0.9.9", "typenum", ] [[package]] name = "libsecp256k1-core" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ee11012b293ea30093c129173cac4335513064094619f4639a25b310fd33c11" +checksum = "d0f6ab710cec28cef759c5f18671a27dae2a5f952cdaaee1d8e2908cb2478a80" dependencies = [ "crunchy", "digest 0.9.0", @@ -1044,183 +1273,140 @@ dependencies = [ [[package]] name = "libsecp256k1-gen-ecmult" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32239626ffbb6a095b83b37a02ceb3672b2443a87a000a884fc3c4d16925c9c0" +checksum = "ccab96b584d38fac86a83f07e659f0deafd0253dc096dab5a36d53efe653c5c3" dependencies = [ "libsecp256k1-core", ] [[package]] name = "libsecp256k1-gen-genmult" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76acb433e21d10f5f9892b1962c2856c58c7f39a9e4bd68ac82b9436a0ffd5b9" +checksum = "67abfe149395e3aa1c48a2beb32b068e2334402df8181f818d3aee2b304c4f5d" dependencies = [ "libsecp256k1-core", ] [[package]] name = "lock_api" -version = "0.3.3" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79b2de95ecb4691949fea4716ca53cdbcfccb2c612e19644a8bad05edcf9f47b" +checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df" dependencies = [ + "autocfg", "scopeguard", ] [[package]] name = "log" -version = "0.4.14" +version = "0.4.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710" +checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", ] -[[package]] -name = "matches" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" - -[[package]] -name = "maybe-uninit" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00" - [[package]] name = "memchr" -version = "2.3.3" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3728d817d99e5ac407411fa471ff9800a778d88a24685968b36824eaf4bee400" +checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" [[package]] name = "memmap2" -version = "0.1.0" +version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9b70ca2a6103ac8b665dc150b142ef0e4e89df640c9e6cf295d189c3caebe5a" +checksum = "4b182332558b18d807c4ce1ca8ca983b34c3ee32765e47b3f0f69b90355cc1dc" dependencies = [ "libc", ] [[package]] name = "memoffset" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75189eb85871ea5c2e2c15abbdd541185f63b408415e5051f5cac122d8c774b9" -dependencies = [ - "rustc_version", -] - -[[package]] -name = "mime" -version = "0.3.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d" - -[[package]] -name = "mio" -version = "0.6.21" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "302dec22bcf6bae6dfb69c647187f4b4d0fb6f535521f7bc022430ce8e12008f" +checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce" dependencies = [ - "cfg-if 0.1.10", - "fuchsia-zircon", - "fuchsia-zircon-sys", - "iovec", - "kernel32-sys", - "libc", - "log", - "miow 0.2.1", - "net2", - "slab", - "winapi 0.2.8", + "autocfg", ] [[package]] -name = "mio" -version = "0.7.9" +name = "memoffset" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5dede4e2065b3842b8b0af444119f3aa331cc7cc2dd20388bfb0f5d5a38823a" +checksum = "5de893c32cde5f383baa4c04c5d6dbdd735cfd4a794b0debdb2bb1b421da5ff4" dependencies = [ - "libc", - "log", - "miow 0.3.6", - "ntapi", - "winapi 0.3.8", + "autocfg", ] [[package]] -name = "mio-uds" -version = "0.6.7" +name = "merlin" +version = "3.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "966257a94e196b11bb43aca423754d87429960a768de9414f3691d6957abf125" +checksum = "58c38e2799fc0978b65dfff8023ec7843e2330bb462f19198840b34b6582397d" dependencies = [ - "iovec", - "libc", - "mio 0.6.21", + "byteorder", + "keccak", + "rand_core 0.6.4", + "zeroize", ] [[package]] -name = "miow" -version = "0.2.1" +name = "mime" +version = "0.3.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919" -dependencies = [ - "kernel32-sys", - "net2", - "winapi 0.2.8", - "ws2_32-sys", -] +checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d" [[package]] -name = "miow" -version = "0.3.6" +name = "miniz_oxide" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a33c1b55807fbed163481b5ba66db4b2fa6cde694a5027be10fb724206c5897" +checksum = "96590ba8f175222643a85693f33d26e9c8a015f599c216509b1a6894af675d34" dependencies = [ - "socket2", - "winapi 0.3.8", + "adler", ] [[package]] -name = "net2" -version = "0.2.37" +name = "mio" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "391630d12b68002ae1e25e8f974306474966550ad82dac6886fb8910c19568ae" +checksum = "e5d732bc30207a6423068df043e3d02e0735b155ad7ce1a6f76fe2baa5b158de" dependencies = [ - "cfg-if 0.1.10", "libc", - "winapi 0.3.8", + "log", + "wasi 0.11.0+wasi-snapshot-preview1", + "windows-sys", ] [[package]] -name = "ntapi" -version = "0.3.4" +name = "num-bigint" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a31937dea023539c72ddae0e3571deadc1414b300483fa7aaec176168cfa9d2" +checksum = "f93ab6289c7b344a8a9f60f88d80aa20032336fe78da341afc91c8a2341fc75f" dependencies = [ - "winapi 0.3.8", + "autocfg", + "num-integer", + "num-traits", ] [[package]] name = "num-derive" -version = "0.3.0" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c8b15b261814f992e33760b1fca9fe8b693d8a65299f20c9901688636cfb746" +checksum = "876a53fff98e03a936a674b29568b0e605f06b29372c2489ff4de23f1949743d" dependencies = [ - "proc-macro2 1.0.24", - "quote 1.0.7", - "syn 1.0.62", + "proc-macro2", + "quote", + "syn", ] [[package]] name = "num-integer" -version = "0.1.42" +version = "0.1.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f6ea62e9d81a77cd3ee9a2a5b9b609447857f3d358704331e4ef39eb247fcba" +checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" dependencies = [ "autocfg", "num-traits", @@ -1228,18 +1414,18 @@ dependencies = [ [[package]] name = "num-traits" -version = "0.2.11" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c62be47e61d1842b9170f0fdeec8eba98e60e90e5446449a0545e5152acd7096" +checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" dependencies = [ "autocfg", ] [[package]] name = "num_cpus" -version = "1.13.0" +version = "1.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05499f3756671c15885fee9034446956fff3f243d6077b91e5767df161f766b3" +checksum = "f6058e64324c71e02bc2b150e4f3bc8286db6c83092132ffa3f6b1eab0f9def5" dependencies = [ "hermit-abi", "libc", @@ -1247,31 +1433,30 @@ dependencies = [ [[package]] name = "num_enum" -version = "0.5.1" +version = "0.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "226b45a5c2ac4dd696ed30fa6b94b057ad909c7b7fc2e0d0808192bced894066" +checksum = "cf5395665662ef45796a4ff5486c5d41d29e0c09640af4c5f17fd94ee2c119c9" dependencies = [ - "derivative", "num_enum_derive", ] [[package]] name = "num_enum_derive" -version = "0.5.1" +version = "0.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c0fd9eba1d5db0994a239e09c1be402d35622277e35468ba891aa5e3188ce7e" +checksum = "3b0498641e53dd6ac1a4f22547548caa6864cc4933784319cd1775271c5a46ce" dependencies = [ - "proc-macro-crate", - "proc-macro2 1.0.24", - "quote 1.0.7", - "syn 1.0.62", + "proc-macro-crate 1.2.1", + "proc-macro2", + "quote", + "syn", ] [[package]] name = "once_cell" -version = "1.7.2" +version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af8b08b04175473088b46763e51ee54da5f9a164bc162f615b91bc179dbf15a3" +checksum = "86f0b0d4bf799edbc74508c1e8bf170ff5f41238e5f8225603ca7caaae2b7860" [[package]] name = "opaque-debug" @@ -1281,94 +1466,72 @@ checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" [[package]] name = "parking_lot" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f842b1982eb6c2fe34036a4fbfb06dd185a3f5c8edfaacdf7d1ea10b07de6252" -dependencies = [ - "lock_api", - "parking_lot_core 0.6.2", - "rustc_version", -] - -[[package]] -name = "parking_lot" -version = "0.10.0" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92e98c49ab0b7ce5b222f2cc9193fc4efe11c6d0bd4f648e374684a6857b1cfc" +checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" dependencies = [ "lock_api", - "parking_lot_core 0.7.0", -] - -[[package]] -name = "parking_lot_core" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b876b1b9e7ac6e1a74a6da34d25c42e17e8862aa409cbbbdcfc8d86c6f3bc62b" -dependencies = [ - "cfg-if 0.1.10", - "cloudabi", - "libc", - "redox_syscall", - "rustc_version", - "smallvec 0.6.13", - "winapi 0.3.8", + "parking_lot_core", ] [[package]] name = "parking_lot_core" -version = "0.7.0" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7582838484df45743c8434fbff785e8edf260c28748353d44bc0da32e0ceabf1" +checksum = "4dc9e0dc2adc1c69d09143aff38d3d30c5c3f0df0dad82e6d25547af174ebec0" dependencies = [ - "cfg-if 0.1.10", - "cloudabi", + "cfg-if", "libc", "redox_syscall", - "smallvec 1.6.1", - "winapi 0.3.8", + "smallvec", + "windows-sys", ] +[[package]] +name = "paste" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1de2e551fb905ac83f73f7aedf2f0cb4a0da7e35efa24a202a936269f1f18e1" + [[package]] name = "pbkdf2" -version = "0.6.0" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3b8c0d71734018084da0c0354193a5edfb81b20d2d57a92c5b154aefc554a4a" +checksum = "216eaa586a190f0a738f2f918511eecfa90f13295abec0e457cdebcceda80cbd" dependencies = [ - "crypto-mac 0.10.0", + "crypto-mac", ] [[package]] -name = "percent-encoding" -version = "2.1.0" +name = "pbkdf2" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" +checksum = "83a0692ec44e4cf1ef28ca317f14f8f07da2d95ec3fa01f86e4467b725e60917" +dependencies = [ + "digest 0.10.6", +] [[package]] -name = "pin-project" -version = "1.0.6" +name = "percent-encoding" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc174859768806e91ae575187ada95c91a29e96a98dc5d2cd9a1fed039501ba6" -dependencies = [ - "pin-project-internal", -] +checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e" [[package]] -name = "pin-project-internal" -version = "1.0.6" +name = "pest" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a490329918e856ed1b083f244e3bfe2d8c4f336407e4ea9e1a9f479ff09049e5" +checksum = "a528564cc62c19a7acac4d81e01f39e53e25e17b934878f4c6d25cc2836e62f8" dependencies = [ - "proc-macro2 1.0.24", - "quote 1.0.7", - "syn 1.0.62", + "thiserror", + "ucd-trie", ] [[package]] name = "pin-project-lite" -version = "0.2.6" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc0e1f259c92177c30a4c9d177246edd0a3568b25756a977d0632cf8fa37e905" +checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" [[package]] name = "pin-utils" @@ -1378,53 +1541,61 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "pkg-config" -version = "0.3.17" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05da548ad6865900e60eaba7f589cc0783590a92e940c26953ff81ddbab2d677" +checksum = "6ac9a59f73473f1b8d852421e59e64809f025994837ef743615c6d0c5b305160" [[package]] -name = "ppv-lite86" -version = "0.2.6" +name = "plain" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74490b50b9fbe561ac330df47c08f3f33073d2d00c150f719147d7c54522fa1b" +checksum = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6" [[package]] -name = "proc-macro-crate" -version = "0.1.5" +name = "polyval" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d6ea3c4595b96363c13943497db34af4460fb474a95c43f4446ad341b8c9785" +checksum = "8419d2b623c7c0896ff2d5d96e2cb4ede590fed28fcc34934f4c33c036e620a1" dependencies = [ - "toml", + "cfg-if", + "cpufeatures", + "opaque-debug", + "universal-hash", ] [[package]] -name = "proc-macro-hack" -version = "0.5.19" +name = "ppv-lite86" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5" +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" [[package]] -name = "proc-macro-nested" -version = "0.1.3" +name = "proc-macro-crate" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "369a6ed065f249a159e06c45752c780bda2fb53c995718f9e484d08daa9eb42e" +checksum = "1d6ea3c4595b96363c13943497db34af4460fb474a95c43f4446ad341b8c9785" +dependencies = [ + "toml", +] [[package]] -name = "proc-macro2" -version = "0.4.30" +name = "proc-macro-crate" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759" +checksum = "eda0fc3b0fb7c975631757e14d9049da17374063edb6ebbcbc54d880d4fe94e9" dependencies = [ - "unicode-xid 0.1.0", + "once_cell", + "thiserror", + "toml", ] [[package]] name = "proc-macro2" -version = "1.0.24" +version = "1.0.47" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e0704ee1a7e00d7bb417d0770ea303c1bccbabf0ef1667dae92b5967f5f8a71" +checksum = "5ea3d908b0e36316caf9e9e2c4625cdde190a7e6f440d794667ed17a1855e725" dependencies = [ - "unicode-xid 0.2.0", + "unicode-ident", ] [[package]] @@ -1438,33 +1609,35 @@ dependencies = [ [[package]] name = "quote" -version = "0.6.13" +version = "1.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1" +checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179" dependencies = [ - "proc-macro2 0.4.30", + "proc-macro2", ] [[package]] -name = "quote" -version = "1.0.7" +name = "rand" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa563d17ecb180e500da1cfd2b028310ac758de548efdd203e18f283af693f37" +checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" dependencies = [ - "proc-macro2 1.0.24", + "getrandom 0.1.16", + "libc", + "rand_chacha 0.2.2", + "rand_core 0.5.1", + "rand_hc", ] [[package]] name = "rand" -version = "0.7.3" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ - "getrandom", "libc", - "rand_chacha", - "rand_core 0.5.1", - "rand_hc", + "rand_chacha 0.3.1", + "rand_core 0.6.4", ] [[package]] @@ -1477,20 +1650,33 @@ dependencies = [ "rand_core 0.5.1", ] +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core 0.6.4", +] + [[package]] name = "rand_core" version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" dependencies = [ - "getrandom", + "getrandom 0.1.16", ] [[package]] name = "rand_core" -version = "0.6.2" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34cf66eb183df1c5876e2dcf6b13d57340741e8dc255b48e40a26de954d06ae7" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom 0.2.8", +] [[package]] name = "rand_hc" @@ -1501,17 +1687,52 @@ dependencies = [ "rand_core 0.5.1", ] +[[package]] +name = "rand_xoshiro" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f97cdb2a36ed4183de61b2f824cc45c9f1037f28afe0a322e9fff4c108b5aaa" +dependencies = [ + "rand_core 0.6.4", +] + +[[package]] +name = "rayon" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e060280438193c554f654141c9ea9417886713b7acd75974c85b18a69a88e0b" +dependencies = [ + "crossbeam-deque", + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cac410af5d00ab6884528b4ab69d1e8e146e8d471201800fa1b4524126de6ad3" +dependencies = [ + "crossbeam-channel", + "crossbeam-deque", + "crossbeam-utils", + "num_cpus", +] + [[package]] name = "redox_syscall" -version = "0.1.56" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84" +checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" +dependencies = [ + "bitflags", +] [[package]] name = "regex" -version = "1.4.6" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a26af418b574bd56588335b3a3659a65725d4e636eb1016c2f9e3b38c7cc759" +checksum = "e076559ef8e241f2ae3479e36f97bd5741c0330689e217ad51ce2c76808b868a" dependencies = [ "aho-corasick", "memchr", @@ -1520,47 +1741,52 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.6.25" +version = "0.6.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b" +checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848" [[package]] name = "remove_dir_all" -version = "0.5.0" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfc5b3ce5d5ea144bb04ebd093a9e14e9765bcfec866aecda9b6dec43b3d1e24" +checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7" dependencies = [ - "winapi 0.3.8", + "winapi", ] [[package]] name = "reqwest" -version = "0.11.2" +version = "0.11.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf12057f289428dbf5c591c74bf10392e4a8003f993405a902f20117019022d4" +checksum = "68cc60575865c7831548863cc02356512e3f1dc2f3f82cb837d7fc4cc8f3c97c" dependencies = [ - "base64 0.13.0", - "bytes 1.0.1", + "async-compression", + "base64 0.13.1", + "bytes", "encoding_rs", "futures-core", "futures-util", + "h2", "http", "http-body", "hyper", "hyper-rustls", "ipnet", "js-sys", - "lazy_static", "log", "mime", + "once_cell", "percent-encoding", "pin-project-lite", "rustls", + "rustls-pemfile", "serde", "serde_json", "serde_urlencoded", - "tokio 1.4.0", + "tokio", "tokio-rustls", + "tokio-util", + "tower-service", "url", "wasm-bindgen", "wasm-bindgen-futures", @@ -1581,48 +1807,71 @@ dependencies = [ "spin", "untrusted", "web-sys", - "winapi 0.3.8", + "winapi", ] [[package]] name = "rustc-demangle" -version = "0.1.16" +version = "0.1.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342" + +[[package]] +name = "rustc-hash" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c691c0e608126e00913e33f0ccf3727d5fc84573623b8d65b2df340b5201783" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" [[package]] name = "rustc_version" -version = "0.2.3" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0dfe2087c51c460008730de8b57e6a320782fbfb312e1f4d520e6c6fae155ee" +dependencies = [ + "semver 0.11.0", +] + +[[package]] +name = "rustc_version" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" +checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" dependencies = [ - "semver", + "semver 1.0.14", ] [[package]] name = "rustls" -version = "0.19.0" +version = "0.20.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "064fd21ff87c6e87ed4506e68beb42459caa4a0e2eb144932e6776768556980b" +checksum = "539a2bfe908f471bfa933876bd1eb6a19cf2176d375f82ef7f99530a40e48c2c" dependencies = [ - "base64 0.13.0", "log", "ring", "sct", "webpki", ] +[[package]] +name = "rustls-pemfile" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0864aeff53f8c05aa08d86e5ef839d3dfcf07aeba2db32f12db0ef716e87bd55" +dependencies = [ + "base64 0.13.1", +] + [[package]] name = "rustversion" -version = "1.0.4" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb5d2a036dc6d2d8fd16fde3498b04306e29bd193bf306a57427019b823d5acd" +checksum = "97477e48b4cf8603ad5f7aaf897467cf42ab4218a38ef76fb14c2d6773a6d6a8" [[package]] name = "ryu" -version = "1.0.2" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa8506c1de11c9c4e4c38863ccbe02a305c8188e85a05a784c9e11e1c3910c8" +checksum = "4501abdff3ae82a1c1b477a17252eb69cee9e66eb915c1abaa4f44d873df9f09" [[package]] name = "scopeguard" @@ -1630,11 +1879,31 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" +[[package]] +name = "scroll" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04c565b551bafbef4157586fa379538366e4385d42082f255bfd96e4fe8519da" +dependencies = [ + "scroll_derive", +] + +[[package]] +name = "scroll_derive" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bdbda6ac5cd1321e724fa9cee216f3a61885889b896f073b8f82322789c5250e" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "sct" -version = "0.6.0" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3042af939fca8c3453b7af0f1c66e533a15a86169e39de2657310ade8f98d3c" +checksum = "d53dcdb7c9f8158937a7981b48accfd39a43af418591a5d008c7b22b5e1b7ca4" dependencies = [ "ring", "untrusted", @@ -1642,53 +1911,62 @@ dependencies = [ [[package]] name = "semver" -version = "0.9.0" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" +checksum = "f301af10236f6df4160f7c3f04eec6dbc70ace82d23326abad5edee88801c6b6" dependencies = [ "semver-parser", ] +[[package]] +name = "semver" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e25dfac463d778e353db5be2449d1cce89bd6fd23c9f1ea21310ce6e5a1b29c4" + [[package]] name = "semver-parser" -version = "0.7.0" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" +checksum = "00b0bef5b7f9e0df16536d3961cfb6e84331c065b4066afb39768d0e319411f7" +dependencies = [ + "pest", +] [[package]] name = "serde" -version = "1.0.124" +version = "1.0.147" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd761ff957cb2a45fbb9ab3da6512de9de55872866160b23c25f1a841e99d29f" +checksum = "d193d69bae983fc11a79df82342761dfbf28a99fc8d203dca4c3c1b590948965" dependencies = [ "serde_derive", ] [[package]] name = "serde_bytes" -version = "0.11.3" +version = "0.11.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "325a073952621257820e7a3469f55ba4726d8b28657e7e36653d1c36dc2c84ae" +checksum = "cfc50e8183eeeb6178dcb167ae34a8051d63535023ae38b5d8d12beae193d37b" dependencies = [ "serde", ] [[package]] name = "serde_derive" -version = "1.0.124" +version = "1.0.147" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1800f7693e94e186f5e25a28291ae1570da908aff7d97a095dec1e56ff99069b" +checksum = "4f1d362ca8fc9c3e3a7484440752472d68a6caa98f1ab81d99b5dfe517cec852" dependencies = [ - "proc-macro2 1.0.24", - "quote 1.0.7", - "syn 1.0.62", + "proc-macro2", + "quote", + "syn", ] [[package]] name = "serde_json" -version = "1.0.57" +version = "1.0.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "164eacbdb13512ec2745fb09d51fd5b22b0d65ed294a1dcf7285a360c80a675c" +checksum = "020ff22c755c2ed3f8cf162dbb41a7268d934702f3ed3631656ea597e08fc3db" dependencies = [ "itoa", "ryu", @@ -1697,9 +1975,9 @@ dependencies = [ [[package]] name = "serde_urlencoded" -version = "0.7.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edfa57a7f8d9c1d260a549e7224100f6c43d43f9103e06dd8b4095a9b2b43ce9" +checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" dependencies = [ "form_urlencoded", "itoa", @@ -1709,157 +1987,155 @@ dependencies = [ [[package]] name = "sha2" -version = "0.9.3" +version = "0.9.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa827a14b29ab7f44778d14a88d3cb76e949c45083f7dbfa507d0cb699dc12de" +checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800" dependencies = [ - "block-buffer", - "cfg-if 1.0.0", - "cpuid-bool", + "block-buffer 0.9.0", + "cfg-if", + "cpufeatures", "digest 0.9.0", "opaque-debug", ] +[[package]] +name = "sha2" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82e6b795fe2e3b1e845bafcb27aa35405c4d47cdfc92af5fc8d3002f76cebdc0" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest 0.10.6", +] + [[package]] name = "sha3" version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f81199417d4e5de3f04b1e871023acea7389672c4135918f05aa9cbf2f2fa809" dependencies = [ - "block-buffer", + "block-buffer 0.9.0", "digest 0.9.0", "keccak", "opaque-debug", ] [[package]] -name = "signature" -version = "1.2.2" +name = "sha3" +version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29f060a7d147e33490ec10da418795238fd7545bba241504d6b31a409f2e6210" +checksum = "bdf0c33fae925bdc080598b84bc15c55e7b9a4a43b3c704da051f977469691c9" +dependencies = [ + "digest 0.10.6", + "keccak", +] [[package]] -name = "slab" -version = "0.4.2" +name = "signature" +version = "1.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8" +checksum = "74233d3b3b2f6d4b006dc19dee745e73e2a6bfb6f93607cd3b02bd5b00797d7c" [[package]] -name = "smallvec" -version = "0.6.13" +name = "sized-chunks" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7b0758c52e15a8b5e3691eae6cc559f08eee9406e548a4477ba4e67770a82b6" +checksum = "16d69225bde7a69b235da73377861095455d298f2b970996eec25ddbb42b3d1e" dependencies = [ - "maybe-uninit", + "bitmaps", + "typenum", ] [[package]] -name = "smallvec" -version = "1.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe0f37c9e8f3c5a4a66ad655a93c74daac4ad00c441533bf5c6e7990bb42604e" - -[[package]] -name = "socket2" -version = "0.3.19" +name = "slab" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "122e570113d28d773067fab24266b66753f6ea915758651696b6e35e49f88d6e" +checksum = "4614a76b2a8be0058caa9dbbaf66d988527d86d003c11a94fbd335d7661edcef" dependencies = [ - "cfg-if 1.0.0", - "libc", - "winapi 0.3.8", + "autocfg", ] [[package]] -name = "solana-config-program" -version = "1.7.6" +name = "smallvec" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d2245383e19e40a01451563cab7a27215293492371f1730c4a0e83403dac101" -dependencies = [ - "bincode", - "chrono", - "log", - "rand_core 0.6.2", - "serde", - "serde_derive", - "solana-sdk", -] +checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" [[package]] -name = "solana-crate-features" -version = "1.7.6" +name = "socket2" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ff6b42fb8897e49b55abaf7d1ce0c3d5f2b5d03aa55c9b22dfb1b586a6813b9" +checksum = "02e2d2db9033d13a1567121ddd7a095ee144db4e1ca1b1bda3419bc0da294ebd" dependencies = [ - "backtrace", - "bytes 0.4.12", - "cc", - "curve25519-dalek 2.1.0", - "ed25519-dalek", - "either", - "lazy_static", "libc", - "rand_chacha", - "regex-syntax", - "reqwest", - "ring", - "serde", - "syn 0.15.44", - "syn 1.0.62", - "tokio 0.1.22", - "winapi 0.3.8", + "winapi", ] [[package]] name = "solana-frozen-abi" -version = "1.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0b98d31e0662fedf3a1ee30919c655713874d578e19e65affe46109b1b927f9" +version = "1.15.0" dependencies = [ + "ahash", + "blake3", + "block-buffer 0.9.0", "bs58", "bv", - "generic-array 0.14.4", + "byteorder", + "cc", + "either", + "generic-array", + "getrandom 0.1.16", + "hashbrown 0.12.3", + "im", + "lazy_static", "log", "memmap2", - "rustc_version", + "once_cell", + "rand_core 0.6.4", + "rustc_version 0.4.0", "serde", + "serde_bytes", "serde_derive", - "sha2", + "serde_json", + "sha2 0.10.6", "solana-frozen-abi-macro", - "solana-logger", + "subtle", "thiserror", ] [[package]] name = "solana-frozen-abi-macro" -version = "1.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ceac6e8ad1a784c92ff5f3d6ad68a8d664d389b08055b674c38b2b9abb69e6d4" +version = "1.15.0" dependencies = [ - "proc-macro2 1.0.24", - "quote 1.0.7", - "rustc_version", - "syn 1.0.62", + "proc-macro2", + "quote", + "rustc_version 0.4.0", + "syn", ] [[package]] name = "solana-logger" -version = "1.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec7c514fe57f8c5042fa88c19f5711c67f264db723d9d79379fcb78dd1f09bbf" +version = "1.15.0" dependencies = [ "env_logger", "lazy_static", "log", ] +[[package]] +name = "solana-measure" +version = "1.15.0" +dependencies = [ + "log", + "solana-sdk", +] + [[package]] name = "solana-metrics" -version = "1.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31a2edbe81e02bc04ad7476e053be0d6632883ee2ca4178b7b1e27fb5112f535" +version = "1.15.0" dependencies = [ - "env_logger", + "crossbeam-channel", "gethostname", "lazy_static", "log", @@ -1869,55 +2145,94 @@ dependencies = [ [[package]] name = "solana-program" -version = "1.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3bfe6a5dfc5372c0a946018ecdd8115e38af78cea8275bac48cf3d105c6b1fb3" +version = "1.15.0" dependencies = [ + "ark-bn254", + "ark-ec", + "ark-ff", + "array-bytes", + "base64 0.13.1", "bincode", + "bitflags", "blake3", "borsh", "borsh-derive", "bs58", "bv", - "curve25519-dalek 2.1.0", - "hex", + "bytemuck", + "cc", + "console_error_panic_hook", + "console_log", + "curve25519-dalek", + "getrandom 0.2.8", "itertools", + "js-sys", "lazy_static", + "libc", "libsecp256k1", "log", + "memoffset 0.6.5", "num-derive", "num-traits", - "rand", - "rustc_version", + "parking_lot", + "rand 0.7.3", + "rand_chacha 0.2.2", + "rustc_version 0.4.0", "rustversion", "serde", "serde_bytes", "serde_derive", - "sha2", - "sha3", + "serde_json", + "sha2 0.10.6", + "sha3 0.10.6", "solana-frozen-abi", "solana-frozen-abi-macro", - "solana-logger", "solana-sdk-macro", "thiserror", + "tiny-bip39", + "wasm-bindgen", + "zeroize", +] + +[[package]] +name = "solana-program-runtime" +version = "1.15.0" +dependencies = [ + "base64 0.13.1", + "bincode", + "eager", + "enum-iterator", + "itertools", + "libc", + "libloading", + "log", + "num-derive", + "num-traits", + "rand 0.7.3", + "rustc_version 0.4.0", + "serde", + "solana-frozen-abi", + "solana-frozen-abi-macro", + "solana-measure", + "solana-metrics", + "solana-sdk", + "solana_rbpf", + "thiserror", ] [[package]] name = "solana-remote-wallet" -version = "1.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d306e9aacee606f21ec1a019b75507700da4fa2a21ac7d2fe2933c4c7a33f69f" +version = "1.15.0" dependencies = [ - "base32", - "console 0.14.1", + "console", "dialoguer", "hidapi", "log", "num-derive", "num-traits", - "parking_lot 0.10.0", + "parking_lot", "qstring", - "semver", + "semver 1.0.14", "solana-sdk", "thiserror", "uriparse", @@ -1925,44 +2240,44 @@ dependencies = [ [[package]] name = "solana-sdk" -version = "1.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1337d6ffccb86c325289ce2dc763990423713e004d9829227eeb1bb9d097415" +version = "1.15.0" dependencies = [ "assert_matches", + "base64 0.13.1", "bincode", + "bitflags", + "borsh", "bs58", - "bv", + "bytemuck", "byteorder", "chrono", "derivation-path", - "digest 0.9.0", + "digest 0.10.6", "ed25519-dalek", "ed25519-dalek-bip32", - "generic-array 0.14.4", - "hex", - "hmac 0.10.1", + "generic-array", + "hmac 0.12.1", "itertools", + "js-sys", "lazy_static", "libsecp256k1", "log", "memmap2", "num-derive", "num-traits", - "pbkdf2", + "num_enum", + "pbkdf2 0.11.0", "qstring", - "rand", - "rand_chacha", - "rand_core 0.6.2", - "rustc_version", + "rand 0.7.3", + "rand_chacha 0.2.2", + "rustc_version 0.4.0", "rustversion", "serde", "serde_bytes", "serde_derive", "serde_json", - "sha2", - "sha3", - "solana-crate-features", + "sha2 0.10.6", + "sha3 0.10.6", "solana-frozen-abi", "solana-frozen-abi-macro", "solana-logger", @@ -1970,61 +2285,84 @@ dependencies = [ "solana-sdk-macro", "thiserror", "uriparse", + "wasm-bindgen", ] [[package]] name = "solana-sdk-macro" -version = "1.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84710ce45a21cccd9f2b09d8e9aad529080bb2540f27b1253874b6e732b465b9" +version = "1.15.0" dependencies = [ "bs58", - "proc-macro2 1.0.24", - "quote 1.0.7", + "proc-macro2", + "quote", "rustversion", - "syn 1.0.62", + "syn", ] [[package]] -name = "solana-stake-program" -version = "1.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76995cab8160e4dceed310f25ea47e4db6e136604b58aeb0d3dc5c5cf4734700" +name = "solana-vote-program" +version = "1.15.0" dependencies = [ "bincode", "log", "num-derive", "num-traits", - "rustc_version", + "rustc_version 0.4.0", "serde", "serde_derive", - "solana-config-program", "solana-frozen-abi", "solana-frozen-abi-macro", "solana-metrics", + "solana-program", + "solana-program-runtime", + "solana-sdk", + "thiserror", +] + +[[package]] +name = "solana-zk-token-sdk" +version = "1.15.0" +dependencies = [ + "aes-gcm-siv", + "arrayref", + "base64 0.13.1", + "bincode", + "bytemuck", + "byteorder", + "cipher 0.4.3", + "curve25519-dalek", + "getrandom 0.1.16", + "itertools", + "lazy_static", + "merlin", + "num-derive", + "num-traits", + "rand 0.7.3", + "serde", + "serde_json", + "sha3 0.9.1", + "solana-program", "solana-sdk", - "solana-vote-program", + "subtle", "thiserror", + "zeroize", ] [[package]] -name = "solana-vote-program" -version = "1.7.6" +name = "solana_rbpf" +version = "0.2.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e32818e9d7b76500c30a9ac7451052d4e529a8f59f2e4c31b611bc543e7a368b" +checksum = "0669f9f5c355899600732451c65cc717d0ef0c53717749f03520337c824fd8a1" dependencies = [ - "bincode", + "byteorder", + "combine", + "goblin", + "hash32", + "libc", "log", - "num-derive", - "num-traits", - "rustc_version", - "serde", - "serde_derive", - "solana-frozen-abi", - "solana-frozen-abi-macro", - "solana-logger", - "solana-metrics", - "solana-sdk", + "rand 0.8.5", + "rustc-demangle", + "scroll", "thiserror", ] @@ -2036,30 +2374,31 @@ checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" [[package]] name = "spl-associated-token-account" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4adc47eebe5d2b662cbaaba1843719c28a67e5ec5d0460bc3ca60900a51f74e2" +version = "1.1.1" dependencies = [ + "assert_matches", + "borsh", + "num-derive", + "num-traits", "solana-program", "spl-token", + "spl-token-2022", + "thiserror", ] [[package]] name = "spl-memo" version = "3.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd0dc6f70db6bacea7ff25870b016a65ba1d1b6013536f08e4fd79a8f9005325" dependencies = [ "solana-program", ] [[package]] name = "spl-token" -version = "3.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93bfdd5bd7c869cb565c7d7635c4fafe189b988a0bdef81063cd9585c6b8dc01" +version = "3.5.0" dependencies = [ "arrayref", + "bytemuck", "num-derive", "num-traits", "num_enum", @@ -2068,64 +2407,69 @@ dependencies = [ ] [[package]] -name = "subtle" -version = "2.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c65d530b10ccaeac294f349038a597e435b18fb456aadd0840a623f83b9e941" +name = "spl-token-2022" +version = "0.4.3" +dependencies = [ + "arrayref", + "bytemuck", + "num-derive", + "num-traits", + "num_enum", + "solana-program", + "solana-zk-token-sdk", + "spl-memo", + "spl-token", + "thiserror", +] [[package]] -name = "syn" -version = "0.15.44" +name = "subtle" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ca4b3b69a77cbe1ffc9e198781b7acb0c7365a883670e8f1c1bc66fba79a5c5" -dependencies = [ - "proc-macro2 0.4.30", - "quote 0.6.13", - "unicode-xid 0.1.0", -] +checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" [[package]] name = "syn" -version = "1.0.62" +version = "1.0.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "123a78a3596b24fee53a6464ce52d8ecbf62241e6294c7e7fe12086cd161f512" +checksum = "a864042229133ada95abf3b54fdc62ef5ccabe9515b64717bcb9a1919e59445d" dependencies = [ - "proc-macro2 1.0.24", - "quote 1.0.7", - "unicode-xid 0.2.0", + "proc-macro2", + "quote", + "unicode-ident", ] [[package]] name = "synstructure" -version = "0.12.3" +version = "0.12.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67656ea1dc1b41b1451851562ea232ec2e5a80242139f7e679ceccfb5d61f545" +checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f" dependencies = [ - "proc-macro2 1.0.24", - "quote 1.0.7", - "syn 1.0.62", - "unicode-xid 0.2.0", + "proc-macro2", + "quote", + "syn", + "unicode-xid", ] [[package]] name = "tempfile" -version = "3.1.0" +version = "3.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a6e24d9338a0a5be79593e2fa15a648add6138caa803e2d5bc782c371732ca9" +checksum = "5cdb1ef4eaeeaddc8fbd371e5017057064af0911902ef36b39801f67cc6d79e4" dependencies = [ - "cfg-if 0.1.10", + "cfg-if", + "fastrand", "libc", - "rand", "redox_syscall", "remove_dir_all", - "winapi 0.3.8", + "winapi", ] [[package]] name = "termcolor" -version = "1.1.0" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb6bfa289a4d7c5766392812c0a1f4c1ba45afa1ad47803c11e1f407d846d75f" +checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755" dependencies = [ "winapi-util", ] @@ -2137,54 +2481,53 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "633c1a546cee861a1a6d0dc69ebeca693bf4296661ba7852b9d21d159e0506df" dependencies = [ "libc", - "winapi 0.3.8", -] - -[[package]] -name = "termios" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b620c5ea021d75a735c943269bb07d30c9b77d6ac6b236bc8b5c496ef05625" -dependencies = [ - "libc", + "winapi", ] [[package]] name = "thiserror" -version = "1.0.24" +version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0f4a65597094d4483ddaed134f409b2cb7c1beccf25201a9f73c719254fa98e" +checksum = "10deb33631e3c9018b9baf9dcbbc4f737320d2b576bac10f6aefa048fa407e3e" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.24" +version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7765189610d8241a44529806d6fd1f2e0a08734313a35d5b3a556f92b381f3c0" +checksum = "982d17546b47146b28f7c22e3d08465f6b8903d0ea13c1660d9d84a6e7adcdbb" dependencies = [ - "proc-macro2 1.0.24", - "quote 1.0.7", - "syn 1.0.62", + "proc-macro2", + "quote", + "syn", ] [[package]] -name = "time" -version = "0.1.42" +name = "tiny-bip39" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f" +checksum = "ffc59cb9dfc85bb312c3a78fd6aa8a8582e310b0fa885d5bb877f6dcc601839d" dependencies = [ - "libc", - "redox_syscall", - "winapi 0.3.8", + "anyhow", + "hmac 0.8.1", + "once_cell", + "pbkdf2 0.4.0", + "rand 0.7.3", + "rustc-hash", + "sha2 0.9.9", + "thiserror", + "unicode-normalization", + "wasm-bindgen", + "zeroize", ] [[package]] name = "tinyvec" -version = "1.1.1" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "317cca572a0e89c3ce0ca1f1bdc9369547fe318a683418e42ac8f59d14701023" +checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" dependencies = [ "tinyvec_macros", ] @@ -2197,308 +2540,150 @@ checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" [[package]] name = "tokio" -version = "0.1.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a09c0b5bb588872ab2f09afa13ee6e9dac11e10a0ec9e8e3ba39a5a5d530af6" -dependencies = [ - "bytes 0.4.12", - "futures", - "mio 0.6.21", - "num_cpus", - "tokio-codec", - "tokio-current-thread", - "tokio-executor", - "tokio-fs", - "tokio-io", - "tokio-reactor", - "tokio-sync", - "tokio-tcp", - "tokio-threadpool", - "tokio-timer", - "tokio-udp", - "tokio-uds", -] - -[[package]] -name = "tokio" -version = "1.4.0" +version = "1.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "134af885d758d645f0f0505c9a8b3f9bf8a348fd822e112ab5248138348f1722" +checksum = "d76ce4a75fb488c605c54bf610f221cea8b0dafb53333c1a67e8ee199dcd2ae3" dependencies = [ "autocfg", - "bytes 1.0.1", + "bytes", "libc", "memchr", - "mio 0.7.9", + "mio", "num_cpus", "pin-project-lite", -] - -[[package]] -name = "tokio-codec" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25b2998660ba0e70d18684de5d06b70b70a3a747469af9dea7618cc59e75976b" -dependencies = [ - "bytes 0.4.12", - "futures", - "tokio-io", -] - -[[package]] -name = "tokio-current-thread" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1de0e32a83f131e002238d7ccde18211c0a5397f60cbfffcb112868c2e0e20e" -dependencies = [ - "futures", - "tokio-executor", -] - -[[package]] -name = "tokio-executor" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb2d1b8f4548dbf5e1f7818512e9c406860678f29c300cdf0ebac72d1a3a1671" -dependencies = [ - "crossbeam-utils", - "futures", -] - -[[package]] -name = "tokio-fs" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "297a1206e0ca6302a0eed35b700d292b275256f596e2f3fea7729d5e629b6ff4" -dependencies = [ - "futures", - "tokio-io", - "tokio-threadpool", -] - -[[package]] -name = "tokio-io" -version = "0.1.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57fc868aae093479e3131e3d165c93b1c7474109d13c90ec0dda2a1bbfff0674" -dependencies = [ - "bytes 0.4.12", - "futures", - "log", -] - -[[package]] -name = "tokio-reactor" -version = "0.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09bc590ec4ba8ba87652da2068d150dcada2cfa2e07faae270a5e0409aa51351" -dependencies = [ - "crossbeam-utils", - "futures", - "lazy_static", - "log", - "mio 0.6.21", - "num_cpus", - "parking_lot 0.9.0", - "slab", - "tokio-executor", - "tokio-io", - "tokio-sync", + "socket2", + "winapi", ] [[package]] name = "tokio-rustls" -version = "0.22.0" +version = "0.23.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc6844de72e57df1980054b38be3a9f4702aba4858be64dd700181a8a6d0e1b6" +checksum = "c43ee83903113e03984cb9e5cebe6c04a5116269e900e3ddba8f068a62adda59" dependencies = [ "rustls", - "tokio 1.4.0", + "tokio", "webpki", ] -[[package]] -name = "tokio-sync" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edfe50152bc8164fcc456dab7891fa9bf8beaf01c5ee7e1dd43a397c3cf87dee" -dependencies = [ - "fnv", - "futures", -] - -[[package]] -name = "tokio-tcp" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "98df18ed66e3b72e742f185882a9e201892407957e45fbff8da17ae7a7c51f72" -dependencies = [ - "bytes 0.4.12", - "futures", - "iovec", - "mio 0.6.21", - "tokio-io", - "tokio-reactor", -] - -[[package]] -name = "tokio-threadpool" -version = "0.1.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df720b6581784c118f0eb4310796b12b1d242a7eb95f716a8367855325c25f89" -dependencies = [ - "crossbeam-deque", - "crossbeam-queue", - "crossbeam-utils", - "futures", - "lazy_static", - "log", - "num_cpus", - "slab", - "tokio-executor", -] - -[[package]] -name = "tokio-timer" -version = "0.2.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93044f2d313c95ff1cb7809ce9a7a05735b012288a888b62d4434fd58c94f296" -dependencies = [ - "crossbeam-utils", - "futures", - "slab", - "tokio-executor", -] - -[[package]] -name = "tokio-udp" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2a0b10e610b39c38b031a2fcab08e4b82f16ece36504988dcbd81dbba650d82" -dependencies = [ - "bytes 0.4.12", - "futures", - "log", - "mio 0.6.21", - "tokio-codec", - "tokio-io", - "tokio-reactor", -] - -[[package]] -name = "tokio-uds" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5076db410d6fdc6523df7595447629099a1fdc47b3d9f896220780fa48faf798" -dependencies = [ - "bytes 0.4.12", - "futures", - "iovec", - "libc", - "log", - "mio 0.6.21", - "mio-uds", - "tokio-codec", - "tokio-io", - "tokio-reactor", -] - [[package]] name = "tokio-util" -version = "0.6.5" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5143d049e85af7fbc36f5454d990e62c2df705b3589f123b71f441b6b59f443f" +checksum = "0bb2e075f03b3d66d8d8785356224ba688d2906a371015e225beeb65ca92c740" dependencies = [ - "bytes 1.0.1", + "bytes", "futures-core", "futures-sink", - "log", "pin-project-lite", - "tokio 1.4.0", + "tokio", + "tracing", ] [[package]] name = "toml" -version = "0.5.6" +version = "0.5.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffc92d160b1eef40665be3a05630d003936a3bc7da7421277846c2613e92c71a" +checksum = "8d82e1a7758622a465f8cee077614c73484dac5b836c02ff6a40d5d1010324d7" dependencies = [ "serde", ] [[package]] name = "tower-service" -version = "0.3.0" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e987b6bf443f4b5b3b6f38704195592cca41c5bb7aedd3c3693c7081f8289860" +checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" [[package]] name = "tracing" -version = "0.1.25" +version = "0.1.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01ebdc2bb4498ab1ab5f5b73c5803825e60199229ccba0698170e3be0e7f959f" +checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "pin-project-lite", "tracing-core", ] [[package]] name = "tracing-core" -version = "0.1.17" +version = "0.1.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f50de3927f93d202783f4513cda820ab47ef17f624b03c096e86ef00c67e6b5f" +checksum = "24eb03ba0eab1fd845050058ce5e616558e8f8d8fca633e6b163fe25c797213a" dependencies = [ - "lazy_static", + "once_cell", ] [[package]] name = "try-lock" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e604eb7b43c06650e854be16a2a03155743d3752dd1c943f6829e26b7a36e382" +checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642" [[package]] name = "typenum" -version = "1.12.0" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987" + +[[package]] +name = "ucd-trie" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "373c8a200f9e67a0c95e62a4f52fbf80c23b4381c05a17845531982fa99e6b33" +checksum = "9e79c4d996edb816c91e4308506774452e55e95c3c9de07b6729e17e15a5ef81" [[package]] name = "unicode-bidi" -version = "0.3.4" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5" -dependencies = [ - "matches", -] +checksum = "099b7128301d285f79ddd55b9a83d5e6b9e97c92e0ea0daebee7263e932de992" + +[[package]] +name = "unicode-ident" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ceab39d59e4c9499d4e5a8ee0e2735b891bb7308ac83dfb4e80cad195c9f6f3" [[package]] name = "unicode-normalization" -version = "0.1.17" +version = "0.1.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07fbfce1c8a97d547e8b5334978438d9d6ec8c20e38f56d4a4374d181493eaef" +checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" dependencies = [ "tinyvec", ] [[package]] name = "unicode-width" -version = "0.1.7" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "caaa9d531767d1ff2150b9332433f32a24622147e5ebb1f26409d5da67afd479" +checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" [[package]] name = "unicode-xid" -version = "0.1.0" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" +checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" [[package]] -name = "unicode-xid" -version = "0.2.0" +name = "universal-hash" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c" +checksum = "9f214e8f697e925001e66ec2c6e37a4ef93f0f78c2eed7814394e10c62025b05" +dependencies = [ + "generic-array", + "subtle", +] + +[[package]] +name = "unreachable" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56" +dependencies = [ + "void", +] [[package]] name = "untrusted" @@ -2508,9 +2693,9 @@ checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" [[package]] name = "uriparse" -version = "0.6.3" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e515b1ada404168e145ac55afba3c42f04cf972201a8552d42e2abb17c1b7221" +checksum = "0200d0fc04d809396c2ad43f3c95da3582a2556eba8d453c1087f4120ee352ff" dependencies = [ "fnv", "lazy_static", @@ -2518,21 +2703,26 @@ dependencies = [ [[package]] name = "url" -version = "2.2.1" +version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ccd964113622c8e9322cfac19eb1004a07e636c545f325da085d5cdde6f1f8b" +checksum = "0d68c799ae75762b8c3fe375feb6600ef5602c883c5d21eb51c09f22b83c4643" dependencies = [ "form_urlencoded", "idna", - "matches", "percent-encoding", ] [[package]] name = "version_check" -version = "0.9.1" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + +[[package]] +name = "void" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "078775d0255232fb988e6fccf26ddc9d1ac274299aaedcedce21c6f72cc533ce" +checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" [[package]] name = "want" @@ -2550,40 +2740,44 @@ version = "0.9.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + [[package]] name = "wasm-bindgen" -version = "0.2.71" +version = "0.2.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ee1280240b7c461d6a0071313e08f34a60b0365f14260362e5a2b17d1d31aa7" +checksum = "eaf9f5aceeec8be17c128b2e93e031fb8a4d469bb9c4ae2d7dc1888b26887268" dependencies = [ - "cfg-if 1.0.0", - "serde", - "serde_json", + "cfg-if", "wasm-bindgen-macro", ] [[package]] name = "wasm-bindgen-backend" -version = "0.2.71" +version = "0.2.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b7d8b6942b8bb3a9b0e73fc79b98095a27de6fa247615e59d096754a3bc2aa8" +checksum = "4c8ffb332579b0557b52d268b91feab8df3615f265d5270fec2a8c95b17c1142" dependencies = [ "bumpalo", - "lazy_static", "log", - "proc-macro2 1.0.24", - "quote 1.0.7", - "syn 1.0.62", + "once_cell", + "proc-macro2", + "quote", + "syn", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.21" +version = "0.4.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e67a5806118af01f0d9045915676b22aaebecf4178ae7021bc171dab0b897ab" +checksum = "23639446165ca5a5de86ae1d8896b737ae80319560fbaa4c2887b7da6e7ebd7d" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "js-sys", "wasm-bindgen", "web-sys", @@ -2591,38 +2785,38 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.71" +version = "0.2.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5ac38da8ef716661f0f36c0d8320b89028efe10c7c0afde65baffb496ce0d3b" +checksum = "052be0f94026e6cbc75cdefc9bae13fd6052cdcaf532fa6c45e7ae33a1e6c810" dependencies = [ - "quote 1.0.7", + "quote", "wasm-bindgen-macro-support", ] [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.71" +version = "0.2.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc053ec74d454df287b9374ee8abb36ffd5acb95ba87da3ba5b7d3fe20eb401e" +checksum = "07bc0c051dc5f23e307b13285f9d75df86bfdf816c5721e573dec1f9b8aa193c" dependencies = [ - "proc-macro2 1.0.24", - "quote 1.0.7", - "syn 1.0.62", + "proc-macro2", + "quote", + "syn", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.71" +version = "0.2.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d6f8ec44822dd71f5f221a5847fb34acd9060535c1211b70a05844c0f6383b1" +checksum = "1c38c045535d93ec4f0b4defec448e4291638ee608530863b1e2ba115d4fff7f" [[package]] name = "web-sys" -version = "0.3.48" +version = "0.3.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec600b26223b2948cedfde2a0aa6756dcf1fef616f43d7b3097aaf53a6c4d92b" +checksum = "bcda906d8be16e728fd5adc5b729afad4e444e106ab28cd1c7256e54fa61510f" dependencies = [ "js-sys", "wasm-bindgen", @@ -2630,9 +2824,9 @@ dependencies = [ [[package]] name = "webpki" -version = "0.21.2" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1f50e1972865d6b1adb54167d1c8ed48606004c2c9d0ea5f1eeb34d95e863ef" +checksum = "f095d78192e208183081cc07bc5515ef55216397af48b873e5edcd72637fa1bd" dependencies = [ "ring", "untrusted", @@ -2640,35 +2834,23 @@ dependencies = [ [[package]] name = "webpki-roots" -version = "0.21.0" +version = "0.22.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82015b7e0b8bad8185994674a13a93306bea76cf5a16c5a181382fd3a5ec2376" +checksum = "368bfe657969fb01238bb756d351dcade285e0f6fcbd36dcb23359a5169975be" dependencies = [ "webpki", ] [[package]] name = "winapi" -version = "0.2.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" - -[[package]] -name = "winapi" -version = "0.3.8" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" dependencies = [ "winapi-i686-pc-windows-gnu", "winapi-x86_64-pc-windows-gnu", ] -[[package]] -name = "winapi-build" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" - [[package]] name = "winapi-i686-pc-windows-gnu" version = "0.4.0" @@ -2677,11 +2859,11 @@ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] name = "winapi-util" -version = "0.1.3" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ccfbf554c6ad11084fb7517daca16cfdcaccbdadba4fc336f032a8b12c2ad80" +checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" dependencies = [ - "winapi 0.3.8", + "winapi", ] [[package]] @@ -2691,41 +2873,88 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] -name = "winreg" -version = "0.7.0" +name = "windows-sys" +version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0120db82e8a1e0b9fb3345a539c478767c0048d842860994d96113d5b667bd69" +checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" dependencies = [ - "winapi 0.3.8", + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", ] [[package]] -name = "ws2_32-sys" -version = "0.2.1" +name = "windows_aarch64_gnullvm" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d2aa71f6f0cbe00ae5167d90ef3cfe66527d6f613ca78ac8024c3ccab9a19e" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd0f252f5a35cac83d6311b2e795981f5ee6e67eb1f9a7f64eb4500fbc4dcdb4" + +[[package]] +name = "windows_i686_gnu" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fbeae19f6716841636c28d695375df17562ca208b2b7d0dc47635a50ae6c5de7" + +[[package]] +name = "windows_i686_msvc" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84c12f65daa39dd2babe6e442988fc329d6243fdce47d7d2d155b8d874862246" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf7b1b21b5362cbc318f686150e5bcea75ecedc74dd157d874d754a2ca44b0ed" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09d525d2ba30eeb3297665bd434a54297e4170c7f1a44cad4ef58095b4cd2028" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e" +checksum = "f40009d85759725a34da6d89a94e63d7bdc50a862acf0dbc7c8e488f1edcb6f5" + +[[package]] +name = "winreg" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80d0f4e272c85def139476380b12f9ac60926689dd2e01d4923222f40580869d" dependencies = [ - "winapi 0.2.8", - "winapi-build", + "winapi", ] [[package]] name = "zeroize" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81a974bcdd357f0dca4d41677db03436324d45a4c9ed2d0b873a5a360ce41c36" +checksum = "4756f7db3f7b5574938c3eb1c117038b8e07f95ee6718c0efad4ac21508f1efd" dependencies = [ "zeroize_derive", ] [[package]] name = "zeroize_derive" -version = "1.0.0" +version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de251eec69fc7c1bc3923403d18ececb929380e016afe103da75f396704f8ca2" +checksum = "3f8f187641dad4f680d25c4bfc4225b418165984179f26ca76ec4fb6441d3a17" dependencies = [ - "proc-macro2 1.0.24", - "quote 1.0.7", - "syn 1.0.62", + "proc-macro2", + "quote", + "syn", "synstructure", ] diff --git a/tests/Cargo.toml b/tests/Cargo.toml index 6b1b57b4..20f27490 100644 --- a/tests/Cargo.toml +++ b/tests/Cargo.toml @@ -1,21 +1,20 @@ [package] name = "ledger-app-solana-tests" -version = "0.1.0" +version = "0.2.0" description = "Ledger-app integration tests using Solana tools" authors = ["Solana Maintainers "] repository = "https://github.com/solana-labs/solana" license = "Apache-2.0" homepage = "https://solana.com/" -edition = "2018" +edition = "2021" [dependencies] hex = "0.4.1" rand = "0.7.3" -solana-logger = "1.7.6" -solana-remote-wallet = "1.7.6" -solana-sdk = "1.7.6" -solana-stake-program = "1.7.6" -solana-vote-program = "1.7.6" -spl-associated-token-account = "1.0.2" +solana-logger = "1.11.6" +solana-remote-wallet = "1.11.6" +solana-sdk = "1.11.6" +solana-vote-program = "1.11.6" +spl-associated-token-account = "1.1.1" spl-memo = "3.0.1" -spl-token = "3.2.0" +spl-token = "3.5.0" diff --git a/tests/python/__init__.py b/tests/python/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/tests/python/apps/__init__.py b/tests/python/apps/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/tests/python/apps/solana.py b/tests/python/apps/solana.py new file mode 100644 index 00000000..ca06561f --- /dev/null +++ b/tests/python/apps/solana.py @@ -0,0 +1,146 @@ +from typing import List, Generator +from enum import IntEnum +from contextlib import contextmanager + +from ragger.backend import BackendInterface +from ragger.utils import RAPDU + + +class INS(IntEnum): + # DEPRECATED - Use non "16" suffixed variants below + INS_GET_APP_CONFIGURATION16 = 0x01 + INS_GET_PUBKEY16 = 0x02 + INS_SIGN_MESSAGE16 = 0x03 + # END DEPRECATED + INS_GET_APP_CONFIGURATION = 0x04 + INS_GET_PUBKEY = 0x05 + INS_SIGN_MESSAGE = 0x06 + INS_SIGN_OFFCHAIN_MESSAGE = 0x07 + + +CLA = 0xE0 + +P1_NON_CONFIRM = 0x00 +P1_CONFIRM = 0x01 + +P2_NONE = 0x00 +P2_EXTEND = 0x01 +P2_MORE = 0x02 + +PUBLIC_KEY_LENGTH = 32 + +MAX_CHUNK_SIZE = 255 + +STATUS_OK = 0x9000 + + +class ErrorType: + NO_APP_RESPONSE = 0x6700 + SDK_EXCEPTION = 0x6801 + SDK_INVALID_PARAMETER = 0x6802 + SDK_EXCEPTION_OVERFLOW = 0x6803 + SDK_EXCEPTION_SECURITY = 0x6804 + SDK_INVALID_CRC = 0x6805 + SDK_INVALID_CHECKSUM = 0x6806 + SDK_INVALID_COUNTER = 0x6807 + SDK_NOT_SUPPORTED = 0x6808 + SDK_INVALID_STATE = 0x6809 + SDK_TIMEOUT = 0x6810 + SDK_EXCEPTION_PIC = 0x6811 + SDK_EXCEPTION_APP_EXIT = 0x6812 + SDK_EXCEPTION_IO_OVERFLOW = 0x6813 + SDK_EXCEPTION_IO_HEADER = 0x6814 + SDK_EXCEPTION_IO_STATE = 0x6815 + SDK_EXCEPTION_IO_RESET = 0x6816 + SDK_EXCEPTION_CX_PORT = 0x6817 + SDK_EXCEPTION_SYSTEM = 0x6818 + SDK_NOT_ENOUGH_SPACE = 0x6819 + NO_APDU_RECEIVED = 0x6982 + USER_CANCEL = 0x6985 + SOLANA_INVALID_MESSAGE = 0x6a80 + SOLANA_SUMMARY_FINALIZE_FAILED = 0x6f00 + SOLANA_SUMMARY_UPDATE_FAILED = 0x6f01 + UNIMPLEMENTED_INSTRUCTION = 0x6d00 + INVALID_CLA = 0x6e00 + + +def _extend_and_serialize_multiple_derivations_paths(derivations_paths: List[bytes]): + serialized: bytes = len(derivations_paths).to_bytes(1, byteorder='little') + for derivations_path in derivations_paths: + serialized += derivations_path + return serialized + + +class SolanaClient: + client: BackendInterface + + def __init__(self, client): + self._client = client + + + def get_public_key(self, derivation_path: bytes) -> bytes: + public_key: RAPDU = self._client.exchange(CLA, INS.INS_GET_PUBKEY, + P1_NON_CONFIRM, P2_NONE, + derivation_path) + assert len(public_key.data) == PUBLIC_KEY_LENGTH, "'from' public key size incorrect" + return public_key.data + + + def split_and_prefix_message(self, derivation_path : bytes, message: bytes) -> List[bytes]: + assert len(message) <= 65535, "Message to send is too long" + header: bytes = _extend_and_serialize_multiple_derivations_paths([derivation_path]) + # Check to see if this data needs to be split up and sent in chunks. + max_size = MAX_CHUNK_SIZE - len(header) + message_splited = [message[x:x + max_size] for x in range(0, len(message), max_size)] + # Add the header to every chunk + return [header + s for s in message_splited] + + + def send_first_message_batch(self, messages: List[bytes], p1: int) -> RAPDU: + self._client.exchange(CLA, INS.INS_SIGN_MESSAGE, p1, P2_MORE, messages[0]) + for m in messages[1:]: + self._client.exchange(CLA, INS.INS_SIGN_MESSAGE, p1, P2_MORE | P2_EXTEND, m) + + + @contextmanager + def send_async_sign_message(self, + derivation_path : bytes, + message: bytes) -> Generator[None, None, None]: + message_splited_prefixed = self.split_and_prefix_message(derivation_path, message) + + # Send all chunks with P2_MORE except for the last chunk + # Send all chunks with P2_EXTEND except for the first chunk + if len(message_splited_prefixed) > 1: + final_p2 = P2_EXTEND + self.send_first_message_batch(message_splited_prefixed[:-1], P1_CONFIRM) + else: + final_p2 = 0 + + with self._client.exchange_async(CLA, + INS.INS_SIGN_MESSAGE, + P1_CONFIRM, + final_p2, + message_splited_prefixed[-1]): + yield + + + def get_async_response(self) -> RAPDU: + return self._client.last_async_response + + + def send_blind_sign_message(self, derivation_path : bytes, message: bytes) -> RAPDU: + message_splited_prefixed = self.split_and_prefix_message(derivation_path, message) + + # Send all chunks with P2_MORE except for the last chunk + # Send all chunks with P2_EXTEND except for the first chunk + if len(message_splited_prefixed) > 1: + final_p2 |= P2_EXTEND + self.send_first_message_batch(message_splited_prefixed[:-1], P1_NON_CONFIRM) + else: + final_p2 = 0 + + return self._client.exchange(CLA, + INS.INS_SIGN_MESSAGE, + P1_NON_CONFIRM, + final_p2, + message_splited_prefixed[-1]) diff --git a/tests/python/apps/solana_cmd_builder.py b/tests/python/apps/solana_cmd_builder.py new file mode 100644 index 00000000..3051b7fb --- /dev/null +++ b/tests/python/apps/solana_cmd_builder.py @@ -0,0 +1,117 @@ +from typing import List +from enum import IntEnum +import base58 +from nacl.signing import VerifyKey + + +PROGRAM_ID_SYSTEM = "11111111111111111111111111111111" + +# Fake blockhash so this example doesn't need a network connection. It should be queried from the cluster in normal use. +FAKE_RECENT_BLOCKHASH = "11111111111111111111111111111111" + + +def verify_signature(from_public_key: bytes, message: bytes, signature: bytes): + assert len(signature) == 64, "signature size incorrect" + verify_key = VerifyKey(from_public_key) + verify_key.verify(message, signature) + + +class SystemInstruction(IntEnum): + CreateAccount = 0x00 + Assign = 0x01 + Transfer = 0x02 + CreateAccountWithSeed = 0x03 + AdvanceNonceAccount = 0x04 + WithdrawNonceAccount = 0x05 + InitializeNonceAccount = 0x06 + AuthorizeNonceAccount = 0x07 + Allocate = 0x08 + AllocateWithSeed = 0x09 + AssignWithSeed = 0x10 + TransferWithSeed = 0x11 + UpgradeNonceAccount = 0x12 + + +class MessageHeader: + def __init__(self, num_required_signatures: int, num_readonly_signed_accounts: int, num_readonly_unsigned_accounts: int): + self.num_required_signatures = num_required_signatures + self.num_readonly_signed_accounts = num_readonly_signed_accounts + self.num_readonly_unsigned_accounts = num_readonly_unsigned_accounts + + def serialize(self) -> bytes: + return self.num_required_signatures.to_bytes(1, byteorder='little') + \ + self.num_readonly_signed_accounts.to_bytes(1, byteorder='little') + \ + self.num_readonly_unsigned_accounts.to_bytes(1, byteorder='little') + +class AccountMeta: + pubkey: bytes + is_signer: bool + is_writable: bool + def __init__(self, pubkey: bytes, is_signer: bool, is_writable: bool): + self.pubkey = pubkey + self.is_signer = is_signer + self.is_writable = is_writable + +# Only support Transfer instruction for now +# TODO add other instructions if the need arises +class Instruction: + program_id: bytes + accounts: List[AccountMeta] + data: bytes + from_pubkey: bytes + to_pubkey: bytes + +class SystemInstructionTransfer(Instruction): + def __init__(self, from_pubkey: bytes, to_pubkey: bytes, amount: int): + self.from_pubkey = from_pubkey + self.to_pubkey = to_pubkey + self.program_id = base58.b58decode(PROGRAM_ID_SYSTEM) + self.accounts = [AccountMeta(from_pubkey, True, True), AccountMeta(to_pubkey, False, True)] + self.data = (SystemInstruction.Transfer).to_bytes(4, byteorder='little') + (amount).to_bytes(8, byteorder='little') + +# Cheat as we only support 1 SystemInstructionTransfer currently +# TODO add support for multiple transfers and other instructions if the needs arises +class CompiledInstruction: + program_id_index: int + accounts: List[int] + data: bytes + + def __init__(self, program_id_index: int, accounts: List[int], data: bytes): + self.program_id_index = program_id_index + self.accounts = accounts + self.data = data + + def serialize(self) -> bytes: + serialized: bytes = self.program_id_index.to_bytes(1, byteorder='little') + serialized += len(self.accounts).to_bytes(1, byteorder='little') + for account in self.accounts: + serialized += (account).to_bytes(1, byteorder='little') + serialized += len(self.data).to_bytes(1, byteorder='little') + serialized += self.data + return serialized + +# Solana communication message, header + list of public keys used by the instructions + instructions +# with references to the keys array +class Message: + header: MessageHeader + account_keys: List[AccountMeta] + recent_blockhash: bytes + compiled_instructions: List[CompiledInstruction] + + def __init__(self, instructions: List[Instruction]): + # Cheat as we only support 1 SystemInstructionTransfer currently + # TODO add support for multiple transfers and other instructions if the needs arises + self.header = MessageHeader(2, 0, 1) + self.account_keys = [instructions[0].from_pubkey, instructions[0].to_pubkey, instructions[0].program_id] + self.recent_blockhash = base58.b58decode(FAKE_RECENT_BLOCKHASH) + self.compiled_instructions = [CompiledInstruction(2, [0, 1], instructions[0].data)] + + def serialize(self) -> bytes: + serialized: bytes = self.header.serialize() + serialized += len(self.account_keys).to_bytes(1, byteorder='little') + for account_key in self.account_keys: + serialized += account_key + serialized += self.recent_blockhash + serialized += len(self.compiled_instructions).to_bytes(1, byteorder='little') + serialized += self.compiled_instructions[0].serialize() + return serialized diff --git a/tests/python/apps/solana_utils.py b/tests/python/apps/solana_utils.py new file mode 100644 index 00000000..f18e624e --- /dev/null +++ b/tests/python/apps/solana_utils.py @@ -0,0 +1,54 @@ +import base58 + +from ragger.bip import pack_derivation_path +from ragger.utils import create_currency_config + +### Some utilities functions for amounts conversions ### + +def sol_to_lamports(sol_amount: int) -> int: + return round(sol_amount * 10**9) + + +def lamports_to_bytes(lamports: int) -> str: + hex:str = '{:x}'.format(lamports) + if (len(hex) % 2 != 0): + hex = "0" + hex + return bytes.fromhex(hex) + + +### Proposed values for fees and amounts ### + +AMOUNT = sol_to_lamports(2.078) +AMOUNT_BYTES = lamports_to_bytes(AMOUNT) + +AMOUNT_2 = sol_to_lamports(101.000001234) +AMOUNT_2_BYTES = lamports_to_bytes(AMOUNT_2) + +FEES = sol_to_lamports(0.00000564) +FEES_BYTES = lamports_to_bytes(FEES) + + +### Proposed foreign and owned addresses ### + +# "Foreign" Solana public key (actually the device public key derived on m/44'/501'/11111') +FOREIGN_ADDRESS = b"AxmUF3qkdz1zs151Q5WttVMkFpFGQPwghZs4d1mwY55d" +FOREIGN_PUBLIC_KEY = base58.b58decode(FOREIGN_ADDRESS) + +# "Foreign" Solana public key (actually the device public key derived on m/44'/501'/11112') +FOREIGN_ADDRESS_2 = b"8bjDMujLMttbmkTtoFgfw2sPYchSzzcTCEPGYDaNs3nj" +FOREIGN_PUBLIC_KEY_2 = base58.b58decode(FOREIGN_ADDRESS_2) + +# Device Solana public key (derived on m/44'/501'/12345') +OWNED_ADDRESS = b"3GJzvStsiYZonWE7WTsmt1BpWXkfcgWMGinaDwNs9HBc" +OWNED_PUBLIC_KEY = base58.b58decode(OWNED_ADDRESS) + + +### Proposed Solana derivation paths for tests ### + +SOL_PACKED_DERIVATION_PATH = pack_derivation_path("m/44'/501'/12345'") +SOL_PACKED_DERIVATION_PATH_2 = pack_derivation_path("m/44'/501'/0'/0'") + + +### Package this currency configuration in exchange format ### + +SOL_CONF = create_currency_config("SOL", "Solana") diff --git a/tests/python/conftest.py b/tests/python/conftest.py new file mode 100644 index 00000000..fe82c482 --- /dev/null +++ b/tests/python/conftest.py @@ -0,0 +1,151 @@ +import pytest +from typing import Optional +from pathlib import Path +from ragger.firmware import Firmware +from ragger.backend import SpeculosBackend, LedgerCommBackend, LedgerWalletBackend +from ragger.navigator import NanoNavigator +from ragger.utils import app_path_from_app_name + + +# This variable is needed for Speculos only (physical tests need the application to be already installed) +# Adapt this path to your 'tests/elfs' directory +APPS_DIRECTORY = (Path(__file__).parent.parent / "elfs").resolve() + +# Adapt this name part of the compiled app _.elf in the APPS_DIRECTORY +APP_NAME = "solana" + +BACKENDS = ["speculos", "ledgercomm", "ledgerwallet"] + +DEVICES = ["nanos", "nanox", "nanosp", "all"] + +FIRMWARES = [Firmware('nanos', '2.1'), + Firmware('nanox', '2.0.2'), + Firmware('nanosp', '1.0.3')] + + +def pytest_addoption(parser): + parser.addoption("--device", choices=DEVICES, required=True) + parser.addoption("--backend", choices=BACKENDS, default="speculos") + parser.addoption("--display", action="store_true", default=False) + parser.addoption("--golden_run", action="store_true", default=False) + parser.addoption("--log_apdu_file", action="store", default=None) + + +@pytest.fixture(scope="session") +def backend_name(pytestconfig): + return pytestconfig.getoption("backend") + + +@pytest.fixture(scope="session") +def display(pytestconfig): + return pytestconfig.getoption("display") + + +@pytest.fixture(scope="session") +def golden_run(pytestconfig): + return pytestconfig.getoption("golden_run") + + +@pytest.fixture(scope="session") +def log_apdu_file(pytestconfig): + filename = pytestconfig.getoption("log_apdu_file") + return Path(filename).resolve() if filename is not None else None + + +@pytest.fixture +def test_name(request): + # Get the name of current pytest test + test_name = request.node.name + + # Remove firmware suffix: + # - test_xxx_transaction_ok[nanox 2.0.2] + # => test_xxx_transaction_ok + return test_name.split("[")[0] + + +# Glue to call every test that depends on the firmware once for each required firmware +def pytest_generate_tests(metafunc): + if "firmware" in metafunc.fixturenames: + fw_list = [] + ids = [] + + device = metafunc.config.getoption("device") + backend_name = metafunc.config.getoption("backend") + + if device == "all": + if backend_name != "speculos": + raise ValueError("Invalid device parameter on this backend") + + # Add all supported firmwares + for fw in FIRMWARES: + fw_list.append(fw) + ids.append(fw.device + " " + fw.version) + + else: + # Enable firmware for demanded device + for fw in FIRMWARES: + if device == fw.device: + fw_list.append(fw) + ids.append(fw.device + " " + fw.version) + + metafunc.parametrize("firmware", fw_list, ids=ids, scope="session") + + +def prepare_speculos_args(firmware: Firmware, display: bool): + speculos_args = [] + + if display: + speculos_args += ["--display", "qt"] + + app_path = app_path_from_app_name(APPS_DIRECTORY, APP_NAME, firmware.device) + + return ([app_path], {"args": speculos_args}) + + +# Depending on the "--backend" option value, a different backend is +# instantiated, and the tests will either run on Speculos or on a physical +# device depending on the backend +def create_backend(backend_name: str, firmware: Firmware, display: bool, log_apdu_file: Optional[Path]): + if backend_name.lower() == "ledgercomm": + return LedgerCommBackend(firmware=firmware, interface="hid", log_apdu_file=log_apdu_file) + elif backend_name.lower() == "ledgerwallet": + return LedgerWalletBackend(firmware=firmware, log_apdu_file=log_apdu_file) + elif backend_name.lower() == "speculos": + args, kwargs = prepare_speculos_args(firmware, display) + return SpeculosBackend(*args, firmware=firmware, log_apdu_file=log_apdu_file, **kwargs) + else: + raise ValueError(f"Backend '{backend_name}' is unknown. Valid backends are: {BACKENDS}") + + +# This fixture will return the properly configured backend, to be used in tests. +# As Speculos instantiation takes some time, this fixture scope is by default "session". +# If your tests needs to be run on independent Speculos instances (in case they affect +# settings for example), then you should change this fixture scope and choose between +# function, class, module or session. +# @pytest.fixture(scope="session") +@pytest.fixture(scope="function") +def backend(backend_name, firmware, display, log_apdu_file): + with create_backend(backend_name, firmware, display, log_apdu_file) as b: + yield b + + +@pytest.fixture +def navigator(backend, firmware, golden_run): + if firmware.device.startswith("nano"): + return NanoNavigator(backend, firmware, golden_run) + else: + raise ValueError(f"Device '{firmware.device}' is unsupported.") + + +@pytest.fixture(autouse=True) +def use_only_on_backend(request, backend): + if request.node.get_closest_marker('use_on_backend'): + current_backend = request.node.get_closest_marker('use_on_backend').args[0] + if current_backend != backend: + pytest.skip(f'skipped on this backend: "{current_backend}"') + + +def pytest_configure(config): + config.addinivalue_line( + "markers", "use_only_on_backend(backend): skip test if not on the specified backend", + ) diff --git a/tests/python/requirements.txt b/tests/python/requirements.txt new file mode 100644 index 00000000..391b52bb --- /dev/null +++ b/tests/python/requirements.txt @@ -0,0 +1,2 @@ +base58 +ragger[tests,speculos] diff --git a/tests/python/snapshots/nanos/test_solana_simple_transfer_ok_1/00000.png b/tests/python/snapshots/nanos/test_solana_simple_transfer_ok_1/00000.png new file mode 100644 index 00000000..a202578d Binary files /dev/null and b/tests/python/snapshots/nanos/test_solana_simple_transfer_ok_1/00000.png differ diff --git a/tests/python/snapshots/nanos/test_solana_simple_transfer_ok_1/00001.png b/tests/python/snapshots/nanos/test_solana_simple_transfer_ok_1/00001.png new file mode 100644 index 00000000..28b24e77 Binary files /dev/null and b/tests/python/snapshots/nanos/test_solana_simple_transfer_ok_1/00001.png differ diff --git a/tests/python/snapshots/nanos/test_solana_simple_transfer_ok_1/00002.png b/tests/python/snapshots/nanos/test_solana_simple_transfer_ok_1/00002.png new file mode 100644 index 00000000..66c411c2 Binary files /dev/null and b/tests/python/snapshots/nanos/test_solana_simple_transfer_ok_1/00002.png differ diff --git a/tests/python/snapshots/nanos/test_solana_simple_transfer_ok_1/00003.png b/tests/python/snapshots/nanos/test_solana_simple_transfer_ok_1/00003.png new file mode 100644 index 00000000..2b60c836 Binary files /dev/null and b/tests/python/snapshots/nanos/test_solana_simple_transfer_ok_1/00003.png differ diff --git a/tests/python/snapshots/nanos/test_solana_simple_transfer_ok_2/00000.png b/tests/python/snapshots/nanos/test_solana_simple_transfer_ok_2/00000.png new file mode 100644 index 00000000..caf2175f Binary files /dev/null and b/tests/python/snapshots/nanos/test_solana_simple_transfer_ok_2/00000.png differ diff --git a/tests/python/snapshots/nanos/test_solana_simple_transfer_ok_2/00001.png b/tests/python/snapshots/nanos/test_solana_simple_transfer_ok_2/00001.png new file mode 100644 index 00000000..026dfb18 Binary files /dev/null and b/tests/python/snapshots/nanos/test_solana_simple_transfer_ok_2/00001.png differ diff --git a/tests/python/snapshots/nanos/test_solana_simple_transfer_ok_2/00002.png b/tests/python/snapshots/nanos/test_solana_simple_transfer_ok_2/00002.png new file mode 100644 index 00000000..66c411c2 Binary files /dev/null and b/tests/python/snapshots/nanos/test_solana_simple_transfer_ok_2/00002.png differ diff --git a/tests/python/snapshots/nanos/test_solana_simple_transfer_ok_2/00003.png b/tests/python/snapshots/nanos/test_solana_simple_transfer_ok_2/00003.png new file mode 100644 index 00000000..2b60c836 Binary files /dev/null and b/tests/python/snapshots/nanos/test_solana_simple_transfer_ok_2/00003.png differ diff --git a/tests/python/snapshots/nanos/test_solana_simple_transfer_refused/00000.png b/tests/python/snapshots/nanos/test_solana_simple_transfer_refused/00000.png new file mode 100644 index 00000000..a202578d Binary files /dev/null and b/tests/python/snapshots/nanos/test_solana_simple_transfer_refused/00000.png differ diff --git a/tests/python/snapshots/nanos/test_solana_simple_transfer_refused/00001.png b/tests/python/snapshots/nanos/test_solana_simple_transfer_refused/00001.png new file mode 100644 index 00000000..28b24e77 Binary files /dev/null and b/tests/python/snapshots/nanos/test_solana_simple_transfer_refused/00001.png differ diff --git a/tests/python/snapshots/nanos/test_solana_simple_transfer_refused/00002.png b/tests/python/snapshots/nanos/test_solana_simple_transfer_refused/00002.png new file mode 100644 index 00000000..66c411c2 Binary files /dev/null and b/tests/python/snapshots/nanos/test_solana_simple_transfer_refused/00002.png differ diff --git a/tests/python/snapshots/nanos/test_solana_simple_transfer_refused/00003.png b/tests/python/snapshots/nanos/test_solana_simple_transfer_refused/00003.png new file mode 100644 index 00000000..9c7e7049 Binary files /dev/null and b/tests/python/snapshots/nanos/test_solana_simple_transfer_refused/00003.png differ diff --git a/tests/python/snapshots/nanos/test_solana_simple_transfer_refused/00004.png b/tests/python/snapshots/nanos/test_solana_simple_transfer_refused/00004.png new file mode 100644 index 00000000..2b60c836 Binary files /dev/null and b/tests/python/snapshots/nanos/test_solana_simple_transfer_refused/00004.png differ diff --git a/tests/python/snapshots/nanosp/test_solana_simple_transfer_ok_1/00000.png b/tests/python/snapshots/nanosp/test_solana_simple_transfer_ok_1/00000.png new file mode 100644 index 00000000..c6623a6a Binary files /dev/null and b/tests/python/snapshots/nanosp/test_solana_simple_transfer_ok_1/00000.png differ diff --git a/tests/python/snapshots/nanosp/test_solana_simple_transfer_ok_1/00001.png b/tests/python/snapshots/nanosp/test_solana_simple_transfer_ok_1/00001.png new file mode 100644 index 00000000..8123c910 Binary files /dev/null and b/tests/python/snapshots/nanosp/test_solana_simple_transfer_ok_1/00001.png differ diff --git a/tests/python/snapshots/nanosp/test_solana_simple_transfer_ok_1/00002.png b/tests/python/snapshots/nanosp/test_solana_simple_transfer_ok_1/00002.png new file mode 100644 index 00000000..53ae6519 Binary files /dev/null and b/tests/python/snapshots/nanosp/test_solana_simple_transfer_ok_1/00002.png differ diff --git a/tests/python/snapshots/nanosp/test_solana_simple_transfer_ok_1/00003.png b/tests/python/snapshots/nanosp/test_solana_simple_transfer_ok_1/00003.png new file mode 100644 index 00000000..890ae49f Binary files /dev/null and b/tests/python/snapshots/nanosp/test_solana_simple_transfer_ok_1/00003.png differ diff --git a/tests/python/snapshots/nanosp/test_solana_simple_transfer_ok_2/00000.png b/tests/python/snapshots/nanosp/test_solana_simple_transfer_ok_2/00000.png new file mode 100644 index 00000000..98b576a0 Binary files /dev/null and b/tests/python/snapshots/nanosp/test_solana_simple_transfer_ok_2/00000.png differ diff --git a/tests/python/snapshots/nanosp/test_solana_simple_transfer_ok_2/00001.png b/tests/python/snapshots/nanosp/test_solana_simple_transfer_ok_2/00001.png new file mode 100644 index 00000000..0a1457d9 Binary files /dev/null and b/tests/python/snapshots/nanosp/test_solana_simple_transfer_ok_2/00001.png differ diff --git a/tests/python/snapshots/nanosp/test_solana_simple_transfer_ok_2/00002.png b/tests/python/snapshots/nanosp/test_solana_simple_transfer_ok_2/00002.png new file mode 100644 index 00000000..53ae6519 Binary files /dev/null and b/tests/python/snapshots/nanosp/test_solana_simple_transfer_ok_2/00002.png differ diff --git a/tests/python/snapshots/nanosp/test_solana_simple_transfer_ok_2/00003.png b/tests/python/snapshots/nanosp/test_solana_simple_transfer_ok_2/00003.png new file mode 100644 index 00000000..890ae49f Binary files /dev/null and b/tests/python/snapshots/nanosp/test_solana_simple_transfer_ok_2/00003.png differ diff --git a/tests/python/snapshots/nanosp/test_solana_simple_transfer_refused/00000.png b/tests/python/snapshots/nanosp/test_solana_simple_transfer_refused/00000.png new file mode 100644 index 00000000..c6623a6a Binary files /dev/null and b/tests/python/snapshots/nanosp/test_solana_simple_transfer_refused/00000.png differ diff --git a/tests/python/snapshots/nanosp/test_solana_simple_transfer_refused/00001.png b/tests/python/snapshots/nanosp/test_solana_simple_transfer_refused/00001.png new file mode 100644 index 00000000..8123c910 Binary files /dev/null and b/tests/python/snapshots/nanosp/test_solana_simple_transfer_refused/00001.png differ diff --git a/tests/python/snapshots/nanosp/test_solana_simple_transfer_refused/00002.png b/tests/python/snapshots/nanosp/test_solana_simple_transfer_refused/00002.png new file mode 100644 index 00000000..53ae6519 Binary files /dev/null and b/tests/python/snapshots/nanosp/test_solana_simple_transfer_refused/00002.png differ diff --git a/tests/python/snapshots/nanosp/test_solana_simple_transfer_refused/00003.png b/tests/python/snapshots/nanosp/test_solana_simple_transfer_refused/00003.png new file mode 100644 index 00000000..c9222461 Binary files /dev/null and b/tests/python/snapshots/nanosp/test_solana_simple_transfer_refused/00003.png differ diff --git a/tests/python/snapshots/nanosp/test_solana_simple_transfer_refused/00004.png b/tests/python/snapshots/nanosp/test_solana_simple_transfer_refused/00004.png new file mode 100644 index 00000000..890ae49f Binary files /dev/null and b/tests/python/snapshots/nanosp/test_solana_simple_transfer_refused/00004.png differ diff --git a/tests/python/snapshots/nanox/test_solana_simple_transfer_ok_1/00000.png b/tests/python/snapshots/nanox/test_solana_simple_transfer_ok_1/00000.png new file mode 100644 index 00000000..c6623a6a Binary files /dev/null and b/tests/python/snapshots/nanox/test_solana_simple_transfer_ok_1/00000.png differ diff --git a/tests/python/snapshots/nanox/test_solana_simple_transfer_ok_1/00001.png b/tests/python/snapshots/nanox/test_solana_simple_transfer_ok_1/00001.png new file mode 100644 index 00000000..8123c910 Binary files /dev/null and b/tests/python/snapshots/nanox/test_solana_simple_transfer_ok_1/00001.png differ diff --git a/tests/python/snapshots/nanox/test_solana_simple_transfer_ok_1/00002.png b/tests/python/snapshots/nanox/test_solana_simple_transfer_ok_1/00002.png new file mode 100644 index 00000000..53ae6519 Binary files /dev/null and b/tests/python/snapshots/nanox/test_solana_simple_transfer_ok_1/00002.png differ diff --git a/tests/python/snapshots/nanox/test_solana_simple_transfer_ok_1/00003.png b/tests/python/snapshots/nanox/test_solana_simple_transfer_ok_1/00003.png new file mode 100644 index 00000000..890ae49f Binary files /dev/null and b/tests/python/snapshots/nanox/test_solana_simple_transfer_ok_1/00003.png differ diff --git a/tests/python/snapshots/nanox/test_solana_simple_transfer_ok_2/00000.png b/tests/python/snapshots/nanox/test_solana_simple_transfer_ok_2/00000.png new file mode 100644 index 00000000..98b576a0 Binary files /dev/null and b/tests/python/snapshots/nanox/test_solana_simple_transfer_ok_2/00000.png differ diff --git a/tests/python/snapshots/nanox/test_solana_simple_transfer_ok_2/00001.png b/tests/python/snapshots/nanox/test_solana_simple_transfer_ok_2/00001.png new file mode 100644 index 00000000..0a1457d9 Binary files /dev/null and b/tests/python/snapshots/nanox/test_solana_simple_transfer_ok_2/00001.png differ diff --git a/tests/python/snapshots/nanox/test_solana_simple_transfer_ok_2/00002.png b/tests/python/snapshots/nanox/test_solana_simple_transfer_ok_2/00002.png new file mode 100644 index 00000000..53ae6519 Binary files /dev/null and b/tests/python/snapshots/nanox/test_solana_simple_transfer_ok_2/00002.png differ diff --git a/tests/python/snapshots/nanox/test_solana_simple_transfer_ok_2/00003.png b/tests/python/snapshots/nanox/test_solana_simple_transfer_ok_2/00003.png new file mode 100644 index 00000000..890ae49f Binary files /dev/null and b/tests/python/snapshots/nanox/test_solana_simple_transfer_ok_2/00003.png differ diff --git a/tests/python/snapshots/nanox/test_solana_simple_transfer_refused/00000.png b/tests/python/snapshots/nanox/test_solana_simple_transfer_refused/00000.png new file mode 100644 index 00000000..c6623a6a Binary files /dev/null and b/tests/python/snapshots/nanox/test_solana_simple_transfer_refused/00000.png differ diff --git a/tests/python/snapshots/nanox/test_solana_simple_transfer_refused/00001.png b/tests/python/snapshots/nanox/test_solana_simple_transfer_refused/00001.png new file mode 100644 index 00000000..8123c910 Binary files /dev/null and b/tests/python/snapshots/nanox/test_solana_simple_transfer_refused/00001.png differ diff --git a/tests/python/snapshots/nanox/test_solana_simple_transfer_refused/00002.png b/tests/python/snapshots/nanox/test_solana_simple_transfer_refused/00002.png new file mode 100644 index 00000000..53ae6519 Binary files /dev/null and b/tests/python/snapshots/nanox/test_solana_simple_transfer_refused/00002.png differ diff --git a/tests/python/snapshots/nanox/test_solana_simple_transfer_refused/00003.png b/tests/python/snapshots/nanox/test_solana_simple_transfer_refused/00003.png new file mode 100644 index 00000000..c9222461 Binary files /dev/null and b/tests/python/snapshots/nanox/test_solana_simple_transfer_refused/00003.png differ diff --git a/tests/python/snapshots/nanox/test_solana_simple_transfer_refused/00004.png b/tests/python/snapshots/nanox/test_solana_simple_transfer_refused/00004.png new file mode 100644 index 00000000..890ae49f Binary files /dev/null and b/tests/python/snapshots/nanox/test_solana_simple_transfer_refused/00004.png differ diff --git a/tests/python/test_solana.py b/tests/python/test_solana.py new file mode 100644 index 00000000..e647e8eb --- /dev/null +++ b/tests/python/test_solana.py @@ -0,0 +1,80 @@ +from ragger.backend import RaisePolicy +from ragger.navigator import NavInsID +from ragger.utils import RAPDU + +from .apps.solana import SolanaClient, ErrorType +from .apps.solana_cmd_builder import SystemInstructionTransfer, Message, verify_signature +from .apps.solana_utils import FOREIGN_PUBLIC_KEY, FOREIGN_PUBLIC_KEY_2, AMOUNT, AMOUNT_2, SOL_PACKED_DERIVATION_PATH, SOL_PACKED_DERIVATION_PATH_2 + +from .utils import ROOT_SCREENSHOT_PATH + +def test_solana_simple_transfer_ok_1(backend, navigator, test_name): + sol = SolanaClient(backend) + from_public_key = sol.get_public_key(SOL_PACKED_DERIVATION_PATH) + + # Create instruction + instruction: SystemInstructionTransfer = SystemInstructionTransfer(from_public_key, FOREIGN_PUBLIC_KEY, AMOUNT) + message: bytes = Message([instruction]).serialize() + + with sol.send_async_sign_message(SOL_PACKED_DERIVATION_PATH, message): + navigator.navigate_until_text_and_compare(NavInsID.RIGHT_CLICK, + [NavInsID.BOTH_CLICK], + "Approve", + ROOT_SCREENSHOT_PATH, + test_name) + + signature: bytes = sol.get_async_response().data + + verify_signature(from_public_key, message, signature) + + +def test_solana_simple_transfer_ok_2(backend, navigator, test_name): + sol = SolanaClient(backend) + from_public_key = sol.get_public_key(SOL_PACKED_DERIVATION_PATH_2) + + # Create instruction + instruction: SystemInstructionTransfer = SystemInstructionTransfer(from_public_key, FOREIGN_PUBLIC_KEY_2, AMOUNT_2) + message: bytes = Message([instruction]).serialize() + + with sol.send_async_sign_message(SOL_PACKED_DERIVATION_PATH_2, message): + navigator.navigate_until_text_and_compare(NavInsID.RIGHT_CLICK, + [NavInsID.BOTH_CLICK], + "Approve", + ROOT_SCREENSHOT_PATH, + test_name) + + signature: bytes = sol.get_async_response().data + + verify_signature(from_public_key, message, signature) + + +def test_solana_simple_transfer_refused(backend, navigator, test_name): + sol = SolanaClient(backend) + from_public_key = sol.get_public_key(SOL_PACKED_DERIVATION_PATH) + + instruction: SystemInstructionTransfer = SystemInstructionTransfer(from_public_key, FOREIGN_PUBLIC_KEY, AMOUNT) + message: bytes = Message([instruction]).serialize() + + backend.raise_policy = RaisePolicy.RAISE_NOTHING + with sol.send_async_sign_message(SOL_PACKED_DERIVATION_PATH, message): + navigator.navigate_until_text_and_compare(NavInsID.RIGHT_CLICK, + [NavInsID.BOTH_CLICK], + "Reject", + ROOT_SCREENSHOT_PATH, + test_name) + + rapdu: RAPDU = sol.get_async_response() + assert rapdu.status == ErrorType.USER_CANCEL + + +def test_solana_blind_sign_refused(backend): + sol = SolanaClient(backend) + from_public_key = sol.get_public_key(SOL_PACKED_DERIVATION_PATH) + + instruction: SystemInstructionTransfer = SystemInstructionTransfer(from_public_key, FOREIGN_PUBLIC_KEY, AMOUNT) + message: bytes = Message([instruction]).serialize() + + backend.raise_policy = RaisePolicy.RAISE_NOTHING + rapdu: RAPDU = sol.send_blind_sign_message(SOL_PACKED_DERIVATION_PATH, message) + assert rapdu.status == ErrorType.SDK_NOT_SUPPORTED + diff --git a/tests/python/utils.py b/tests/python/utils.py new file mode 100644 index 00000000..1d79e50f --- /dev/null +++ b/tests/python/utils.py @@ -0,0 +1,3 @@ +from pathlib import Path + +ROOT_SCREENSHOT_PATH = Path(__file__).parent.resolve() diff --git a/tests/src/main.rs b/tests/src/main.rs index 7cf2ed47..46c4c636 100644 --- a/tests/src/main.rs +++ b/tests/src/main.rs @@ -6,15 +6,21 @@ use solana_remote_wallet::{ remote_wallet::{initialize_wallet_manager, RemoteWallet, RemoteWalletError}, }; use solana_sdk::{ + address_lookup_table_account::AddressLookupTableAccount, derivation_path::DerivationPath, + hash::Hash, instruction::{AccountMeta, Instruction}, - message::Message, + message::{v0::Message as MessageV0, Message}, pubkey::Pubkey, + stake::{ + instruction as stake_instruction, program as solana_stake_program, state as stake_state, + }, system_instruction, system_program, }; -use solana_stake_program::{stake_instruction, stake_state}; use solana_vote_program::{vote_instruction, vote_state}; -use spl_associated_token_account::*; +use spl_associated_token_account::{ + get_associated_token_address, instruction::create_associated_token_account, +}; use std::{collections::HashSet, sync::Arc}; fn get_ledger() -> (Arc, Pubkey) { @@ -85,6 +91,69 @@ fn test_ledger_sign_transaction() -> Result<(), RemoteWalletError> { Ok(()) } +// This test requires interactive approval of message signing on the ledger. +fn test_ledger_sign_versioned_transaction() -> Result<(), RemoteWalletError> { + let (ledger, ledger_base_pubkey) = get_ledger(); + + let derivation_path = DerivationPath::new_bip44(Some(12345), None); + + let from = ledger.get_pubkey(&derivation_path, false)?; + let instruction = system_instruction::transfer(&from, &ledger_base_pubkey, 42); + let message = MessageV0::try_compile(&ledger_base_pubkey, &[instruction], &[], Hash::default()) + .unwrap() + .serialize(); + let signature = ledger.sign_message(&derivation_path, &message)?; + assert!(signature.verify(from.as_ref(), &message)); + + // Test large transaction + let recipients: Vec<(Pubkey, u64)> = (0..10).map(|_| (Pubkey::new_unique(), 42)).collect(); + let instructions = system_instruction::transfer_many(&from, &recipients); + let message = MessageV0::try_compile(&ledger_base_pubkey, &instructions, &[], Hash::default()) + .unwrap() + .serialize(); + let hash = solana_sdk::hash::hash(&message); + println!("Expected hash: {}", hash); + let signature = ledger.sign_message(&derivation_path, &message)?; + assert!(signature.verify(from.as_ref(), &message)); + Ok(()) +} + +// This test requires interactive approval of message signing on the ledger. +fn test_ledger_sign_versioned_transaction_with_table() -> Result<(), RemoteWalletError> { + let (ledger, ledger_base_pubkey) = get_ledger(); + + let derivation_path = DerivationPath::new_bip44(Some(12345), None); + + let from = ledger.get_pubkey(&derivation_path, false)?; + let instruction = system_instruction::transfer(&from, &ledger_base_pubkey, 42); + let lookup_table = AddressLookupTableAccount { + key: solana_sdk::pubkey::Pubkey::new_unique(), + addresses: vec![from, ledger_base_pubkey], + }; + let message = MessageV0::try_compile( + &from, + &[instruction], + &[lookup_table.clone()], + Hash::default(), + ) + .unwrap() + .serialize(); + let signature = ledger.sign_message(&derivation_path, &message)?; + assert!(signature.verify(from.as_ref(), &message)); + + // Test large transaction + let recipients: Vec<(Pubkey, u64)> = (0..10).map(|_| (Pubkey::new_unique(), 42)).collect(); + let instructions = system_instruction::transfer_many(&from, &recipients); + let message = MessageV0::try_compile(&from, &instructions, &[lookup_table], Hash::default()) + .unwrap() + .serialize(); + let hash = solana_sdk::hash::hash(&message); + println!("Expected hash: {}", hash); + let signature = ledger.sign_message(&derivation_path, &message)?; + assert!(signature.verify(from.as_ref(), &message)); + Ok(()) +} + fn test_ledger_sign_transaction_too_big() -> Result<(), RemoteWalletError> { // Test too big of a transaction let (ledger, ledger_base_pubkey) = get_ledger(); @@ -99,6 +168,47 @@ fn test_ledger_sign_transaction_too_big() -> Result<(), RemoteWalletError> { Ok(()) } +// This test requires interactive approval of message signing on the ledger. +fn test_ledger_sign_offchain_message_ascii() -> Result<(), RemoteWalletError> { + let (ledger, _ledger_base_pubkey) = get_ledger(); + + let derivation_path = DerivationPath::new_bip44(Some(12345), None); + + let from = ledger.get_pubkey(&derivation_path, false)?; + + let message = solana_sdk::offchain_message::OffchainMessage::new(0, b"Test message") + .map_err(|_| RemoteWalletError::InvalidInput("Bad message".to_string()))? + .serialize() + .map_err(|_| RemoteWalletError::InvalidInput("Failed to serialize message".to_string()))?; + let signature = ledger.sign_message(&derivation_path, &message)?; + assert!(signature.verify(from.as_ref(), &message)); + + Ok(()) +} + +// This test requires interactive approval of message signing on the ledger. +fn test_ledger_sign_offchain_message_utf8() -> Result<(), RemoteWalletError> { + let (ledger, _ledger_base_pubkey) = get_ledger(); + + let derivation_path = DerivationPath::new_bip44(Some(12345), None); + + let from = ledger.get_pubkey(&derivation_path, false)?; + + let message = + solana_sdk::offchain_message::OffchainMessage::new(0, "Тестовое сообщение".as_bytes()) + .map_err(|_| RemoteWalletError::InvalidInput("Bad message".to_string()))? + .serialize() + .map_err(|_| { + RemoteWalletError::InvalidInput("Failed to serialize message".to_string()) + })?; + let hash = solana_sdk::hash::hash(&message); + println!("Expected hash: {}", hash); + let signature = ledger.sign_message(&derivation_path, &message)?; + assert!(signature.verify(from.as_ref(), &message)); + + Ok(()) +} + /// This test requires interactive approval of message signing on the ledger. fn test_ledger_delegate_stake() -> Result<(), RemoteWalletError> { let (ledger, ledger_base_pubkey) = get_ledger(); @@ -1483,7 +1593,8 @@ fn test_spl_associated_token_account_create() -> Result<(), RemoteWalletError> { let derivation_path = DerivationPath::new_bip44(Some(12345), None); let owner = ledger.get_pubkey(&derivation_path, false)?; let mint = Pubkey::new_unique(); - let instruction = create_associated_token_account(&owner, &owner, &mint); + let instruction = + create_associated_token_account(&owner, &owner, &mint, &spl_associated_token_account::id()); let message = Message::new(&[instruction], Some(&owner)).serialize(); let signature = ledger.sign_message(&derivation_path, &message)?; assert!(signature.verify(owner.as_ref(), &message)); @@ -1501,7 +1612,12 @@ fn test_spl_associated_token_account_create_with_transfer_checked() -> Result<() let recipient = Pubkey::new_unique(); let recipient_holder = get_associated_token_address(&recipient, &mint); let instructions = vec![ - create_associated_token_account(&sender, &recipient, &mint), + create_associated_token_account( + &sender, + &recipient, + &mint, + &spl_associated_token_account::id(), + ), spl_token::instruction::transfer_checked( &spl_token::id(), &sender_holder, @@ -1550,7 +1666,12 @@ fn test_spl_associated_token_account_create_with_transfer_checked_and_serum_asse let recipient_holder = get_associated_token_address(&recipient, &mint); let instructions = vec![ serum_assert_owner_program::instruction::check(&recipient, &system_program::id()), - create_associated_token_account(&sender, &recipient, &mint), + create_associated_token_account( + &sender, + &recipient, + &mint, + &spl_associated_token_account::id(), + ), spl_token::instruction::transfer_checked( &spl_token::id(), &sender_holder, @@ -1601,6 +1722,7 @@ fn ensure_blind_signing() -> Result<(), RemoteWalletError> { } Ok(()) } + fn main() { solana_logger::setup(); match do_run_tests() { @@ -1621,6 +1743,10 @@ macro_rules! run { fn do_run_tests() -> Result<(), RemoteWalletError> { ensure_blind_signing()?; + run!(test_ledger_sign_versioned_transaction); + run!(test_ledger_sign_versioned_transaction_with_table); + run!(test_ledger_sign_offchain_message_ascii); + run!(test_ledger_sign_offchain_message_utf8); run!(test_ledger_transfer_with_memos); run!(test_spl_associated_token_account_create_with_transfer_checked_and_serum_assert_owner); run!(test_spl_associated_token_account_create_with_transfer_checked); @@ -1686,5 +1812,6 @@ fn do_run_tests() -> Result<(), RemoteWalletError> { run!(test_create_stake_account_with_seed_and_nonce); run!(test_create_stake_account_checked_with_seed_and_nonce); run!(test_sign_full_shred_of_garbage_tx); + Ok(()) } diff --git a/util/active-target.sh b/util/active-target.sh new file mode 100644 index 00000000..3e95b566 --- /dev/null +++ b/util/active-target.sh @@ -0,0 +1,77 @@ +#!/usr/bin/env bash + +declare -r nanos_sdk=NANOS_SDK +declare -r nanox_sdk=NANOX_SDK +declare -r nanosp_sdk=NANOSP_SDK + +sdk_mnemonic_to_bolos_variable() { + local -r sdk_mnemonic="${1:?}" + local bolos_sdk_var= + case "$sdk_mnemonic" in + s) + bolos_sdk_var="$nanos_sdk" + ;; + x) + bolos_sdk_var="$nanox_sdk" + ;; + sp) + bolos_sdk_var="$nanosp_sdk" + ;; + *) + echo "unimplemented sdk mnemonic: \`$sdk\`" 1>&2 + exit 1 + ;; + esac + echo "$bolos_sdk_var" +} + +get_last_target_sdk_stamp_filepath() { + local -r app_root="${1:?'missing required arg 1: `app_root`'}" + local -r stamp_dir="${app_root}"/obj + local -r last_target_sdk_stamp_filepath="${stamp_dir}"/.target_sdk.stamp + mkdir -p "${stamp_dir}" + echo "${last_target_sdk_stamp_filepath}" +} + +normalize_mnemonic() { + local -r target_sdk_mnemonic="${1:?'missing required arg 1: `target_sdk_mnemonic`'}" + local -r fail_unimplemented="${2:?'missing required arg 2: `fail_unimplemented`'}" + local -r l_target_sdk_mnemonic="$(tr '[:upper:]' '[:lower:]' <<<"$target_sdk_mnemonic")" + local normalized_target_sdk_mnemonic= + case "$l_target_sdk_mnemonic" in + s|x|sp) + normalized_target_sdk_mnemonic="$l_target_sdk_mnemonic" + ;; + "") + ;; + *) + if $fail_unimplemented; then + echo "unimplemented sdk mnemonic: \`$l_target_sdk_mnemonic\`" 1>&2 + exit 1 + fi + ;; + esac + echo "$normalized_target_sdk_mnemonic" +} + +read_last_target_sdk_mnemonic() { + local -r app_root="${1:?'missing required arg 1: `app_root`'}" + local -r target_sdk_stamp_filepath="$(get_last_target_sdk_stamp_filepath "$app_root")" + local last_target_sdk_mnemonic= + if [[ -r "$target_sdk_stamp_filepath" ]]; then + last_target_sdk_mnemonic="$(normalize_mnemonic "$(<"$target_sdk_stamp_filepath")" true)" + fi + echo "$last_target_sdk_mnemonic" +} + +write_last_target_sdk_mnemonic() { + local -r app_root="${1:?'missing required arg 1: `app_root`'}" + local -r last_target_sdk_mnemonic="${2:?'missing required arg 2: `last_target_sdk_mnemonic`'}" + local -r target_sdk_stamp_filepath="$(get_last_target_sdk_stamp_filepath "$app_root")" + if [[ ! -e "$target_sdk_stamp_filepath" ]]; then + echo "$last_target_sdk_mnemonic" > "$target_sdk_stamp_filepath" + else + echo "failed to write target sdk mnemonic. stamp file already exists: \`$target_sdk_stamp_filepath\`" 1>&2 + exit 1 + fi +} diff --git a/util/read-last-sdk b/util/read-last-sdk new file mode 100755 index 00000000..97f4e549 --- /dev/null +++ b/util/read-last-sdk @@ -0,0 +1,14 @@ +#!/usr/bin/env bash +here="$(realpath "$(dirname "$0")")" + +source "${here}"/active-target.sh + +app_root="$(realpath "$here"/..)" +last_target_sdk="$(read_last_target_sdk_mnemonic "$app_root")" + +if [[ -z "$last_target_sdk" ]]; then + echo 'cannot resolve target sdk. please run `docker-make ` first' >&2 + exit 1 +fi + +sdk_mnemonic_to_bolos_variable "$last_target_sdk"