1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2024-11-22 07:28:10 +00:00

Merge remote-tracking branch 'origin/master' into andrewkozlik/slip0039

This commit is contained in:
Andrew Kozlik 2019-04-29 11:29:54 +02:00
commit e631983d6d
200 changed files with 6760 additions and 4171 deletions

1
.gitignore vendored
View File

@ -6,3 +6,4 @@
.vscode/
__pycache__/
*.pyc
/build

30
.gitlab-ci.yml Normal file
View File

@ -0,0 +1,30 @@
variables:
# Init submodules.
# See https://docs.gitlab.com/ee/ci/yaml/#git-submodule-strategy
GIT_SUBMODULE_STRATEGY: "recursive"
# Use shallow cloning to speed up git clone. This can fail, if retrying an older build on CI
# and the old commit is not in the shallow history any more.
# See https://docs.gitlab.com/ee/ci/yaml/#shallow-cloning
GIT_DEPTH: "50"
# run make paralel
MAKEFLAGS: "-j10"
stages:
- environment
- prebuild
- build
- test
before_script:
- pipenv install
include:
- ci/environment.yml
- ci/prebuild.yml # common, style
- ci/core.yml
- ci/legacy.yml
# - ci/python.yml TODO
- ci/crypto.yml
- ci/storage.yml

1
.gitmodules vendored
View File

@ -23,6 +23,7 @@
[submodule "legacy/vendor/nanopb"]
path = legacy/vendor/nanopb
url = https://github.com/nanopb/nanopb.git
ignore = untracked
[submodule "legacy/vendor/QR-Code-generator"]
path = legacy/vendor/QR-Code-generator
url = https://github.com/nayuki/QR-Code-generator.git

24
Makefile Normal file
View File

@ -0,0 +1,24 @@
## help commands:
help: ## show this help
@awk -f ./tools/help.awk $(MAKEFILE_LIST)
## style commands:
style_check: ## run code style check on application sources and tests
flake8 --version
isort --version | awk '/VERSION/{print $$2}'
black --version
flake8 $(shell find -type f -name '*.py' | grep -f ./tools/style.py.include | grep -v -f ./tools/style.py.exclude )
isort --check-only $(shell find -type f -name '*.py' | grep -f ./tools/style.py.include | grep -v -f ./tools/style.py.exclude )
black --check $(shell find -type f -name '*.py' | grep -f ./tools/style.py.include | grep -v -f ./tools/style.py.exclude )
style: ## apply code style on application sources and tests
isort $(shell find -type f -name '*.py' | grep -f ./tools/style.py.include | grep -v -f ./tools/style.py.exclude )
black $(shell find -type f -name '*.py' | grep -f ./tools/style.py.include | grep -v -f ./tools/style.py.exclude )
cstyle_check: ## run code style check on low-level C code
./tools/clang-format-check $(shell find -type f -name '*.c' -o -name '*.h' | grep -f ./tools/style.c.include | grep -v -f ./tools/style.c.exclude )
cstyle: ## apply code style on low-level C code
clang-format -i $(shell find -type f -name '*.c' -o -name '*.h' | grep -f ./tools/style.c.include | grep -v -f ./tools/style.c.exclude )

View File

@ -4,31 +4,49 @@ name = "pypi"
verify_ssl = true
[packages]
trezor = {git = "https://github.com/trezor/python-trezor", editable = true, ref = "master"}
# all
trezor = {editable = true, path = "./python"}
scons = "*"
protobuf = "==3.4.0"
# python-trezor tests
pyblake2 = "*"
## tests
pytest = "*"
mock = "*"
# make style
## style
isort = "*"
flake8 = "*"
black = "*"
mako = ">=1.0.7"
munch = ">=2.3.2"
# trezor-common cointool
# common
demjson = "*"
graphviz = "*" # TODO this was '8' do we need that?
## cointool
click = ">=6"
"ed25519" = ">=1.4"
requests = ">=2.19"
munch = ">=2.3.2"
termcolor = ">=0.1.2"
Pillow = ">=5.2.0"
Mako = ">=1.0.7"
# monero
# crypto
ecdsa = "*"
curve25519-donna = "*"
pyasn1 = "*"
# core
## monero
monero_agent = {version = ">=2.0.1", extras = ["tcry", "dev"]}
py_trezor_crypto_ph4 = {version = ">=0.1.1"}
# legacy
setuptools = ">=24.2.0"
typing = "*"
# storage
cryptography = "*"
hypothesis = "*"
[dev-packages]
scan-build = "*"

View File

@ -1,7 +1,7 @@
{
"_meta": {
"hash": {
"sha256": "f038c016ebf0f0551ad1a2d066dd5861661925767b56bcf3c82b6764156b3b60"
"sha256": "4c4b090a727ea8f5db592444bf5930bb9ec06898d5b58d7c4eba4fd9a1317ebb"
},
"pipfile-spec": 6,
"requires": {},
@ -79,36 +79,36 @@
},
"cffi": {
"hashes": [
"sha256:00b97afa72c233495560a0793cdc86c2571721b4271c0667addc83c417f3d90f",
"sha256:0ba1b0c90f2124459f6966a10c03794082a2f3985cd699d7d63c4a8dae113e11",
"sha256:0bffb69da295a4fc3349f2ec7cbe16b8ba057b0a593a92cbe8396e535244ee9d",
"sha256:21469a2b1082088d11ccd79dd84157ba42d940064abbfa59cf5f024c19cf4891",
"sha256:2e4812f7fa984bf1ab253a40f1f4391b604f7fc424a3e21f7de542a7f8f7aedf",
"sha256:2eac2cdd07b9049dd4e68449b90d3ef1adc7c759463af5beb53a84f1db62e36c",
"sha256:2f9089979d7456c74d21303c7851f158833d48fb265876923edcb2d0194104ed",
"sha256:3dd13feff00bddb0bd2d650cdb7338f815c1789a91a6f68fdc00e5c5ed40329b",
"sha256:4065c32b52f4b142f417af6f33a5024edc1336aa845b9d5a8d86071f6fcaac5a",
"sha256:51a4ba1256e9003a3acf508e3b4f4661bebd015b8180cc31849da222426ef585",
"sha256:59888faac06403767c0cf8cfb3f4a777b2939b1fbd9f729299b5384f097f05ea",
"sha256:59c87886640574d8b14910840327f5cd15954e26ed0bbd4e7cef95fa5aef218f",
"sha256:610fc7d6db6c56a244c2701575f6851461753c60f73f2de89c79bbf1cc807f33",
"sha256:70aeadeecb281ea901bf4230c6222af0248c41044d6f57401a614ea59d96d145",
"sha256:71e1296d5e66c59cd2c0f2d72dc476d42afe02aeddc833d8e05630a0551dad7a",
"sha256:8fc7a49b440ea752cfdf1d51a586fd08d395ff7a5d555dc69e84b1939f7ddee3",
"sha256:9b5c2afd2d6e3771d516045a6cfa11a8da9a60e3d128746a7fe9ab36dfe7221f",
"sha256:9c759051ebcb244d9d55ee791259ddd158188d15adee3c152502d3b69005e6bd",
"sha256:b4d1011fec5ec12aa7cc10c05a2f2f12dfa0adfe958e56ae38dc140614035804",
"sha256:b4f1d6332339ecc61275bebd1f7b674098a66fea11a00c84d1c58851e618dc0d",
"sha256:c030cda3dc8e62b814831faa4eb93dd9a46498af8cd1d5c178c2de856972fd92",
"sha256:c2e1f2012e56d61390c0e668c20c4fb0ae667c44d6f6a2eeea5d7148dcd3df9f",
"sha256:c37c77d6562074452120fc6c02ad86ec928f5710fbc435a181d69334b4de1d84",
"sha256:c8149780c60f8fd02752d0429246088c6c04e234b895c4a42e1ea9b4de8d27fb",
"sha256:cbeeef1dc3c4299bd746b774f019de9e4672f7cc666c777cd5b409f0b746dac7",
"sha256:e113878a446c6228669144ae8a56e268c91b7f1fafae927adc4879d9849e0ea7",
"sha256:e21162bf941b85c0cda08224dade5def9360f53b09f9f259adb85fc7dd0e7b35",
"sha256:fb6934ef4744becbda3143d30c6604718871495a5e36c408431bf33d9c146889"
"sha256:041c81822e9f84b1d9c401182e174996f0bae9991f33725d059b771744290774",
"sha256:046ef9a22f5d3eed06334d01b1e836977eeef500d9b78e9ef693f9380ad0b83d",
"sha256:066bc4c7895c91812eff46f4b1c285220947d4aa46fa0a2651ff85f2afae9c90",
"sha256:066c7ff148ae33040c01058662d6752fd73fbc8e64787229ea8498c7d7f4041b",
"sha256:2444d0c61f03dcd26dbf7600cf64354376ee579acad77aef459e34efcb438c63",
"sha256:300832850b8f7967e278870c5d51e3819b9aad8f0a2c8dbe39ab11f119237f45",
"sha256:34c77afe85b6b9e967bd8154e3855e847b70ca42043db6ad17f26899a3df1b25",
"sha256:46de5fa00f7ac09f020729148ff632819649b3e05a007d286242c4882f7b1dc3",
"sha256:4aa8ee7ba27c472d429b980c51e714a24f47ca296d53f4d7868075b175866f4b",
"sha256:4d0004eb4351e35ed950c14c11e734182591465a33e960a4ab5e8d4f04d72647",
"sha256:4e3d3f31a1e202b0f5a35ba3bc4eb41e2fc2b11c1eff38b362de710bcffb5016",
"sha256:50bec6d35e6b1aaeb17f7c4e2b9374ebf95a8975d57863546fa83e8d31bdb8c4",
"sha256:55cad9a6df1e2a1d62063f79d0881a414a906a6962bc160ac968cc03ed3efcfb",
"sha256:5662ad4e4e84f1eaa8efce5da695c5d2e229c563f9d5ce5b0113f71321bcf753",
"sha256:59b4dc008f98fc6ee2bb4fd7fc786a8d70000d058c2bbe2698275bc53a8d3fa7",
"sha256:73e1ffefe05e4ccd7bcea61af76f36077b914f92b76f95ccf00b0c1b9186f3f9",
"sha256:a1f0fd46eba2d71ce1589f7e50a9e2ffaeb739fb2c11e8192aa2b45d5f6cc41f",
"sha256:a2e85dc204556657661051ff4bab75a84e968669765c8a2cd425918699c3d0e8",
"sha256:a5457d47dfff24882a21492e5815f891c0ca35fefae8aa742c6c263dac16ef1f",
"sha256:a8dccd61d52a8dae4a825cdbb7735da530179fea472903eb871a5513b5abbfdc",
"sha256:ae61af521ed676cf16ae94f30fe202781a38d7178b6b4ab622e4eec8cefaff42",
"sha256:b012a5edb48288f77a63dba0840c92d0504aa215612da4541b7b42d849bc83a3",
"sha256:d2c5cfa536227f57f97c92ac30c8109688ace8fa4ac086d19d0af47d134e2909",
"sha256:d42b5796e20aacc9d15e66befb7a345454eef794fdb0737d1af593447c6c8f45",
"sha256:dee54f5d30d775f525894d67b1495625dd9322945e7fee00731952e0368ff42d",
"sha256:e070535507bd6aa07124258171be2ee8dfc19119c28ca94c9dfb7efd23564512",
"sha256:e1ff2748c84d97b065cc95429814cdba39bcbd77c9c85c89344b317dc0d9cbff",
"sha256:ed851c75d1e0e043cbf5ca9a8e1b13c4c90f3fbd863dacb01c0808e2b5204201"
],
"version": "==1.12.2"
"version": "==1.12.3"
},
"chacha20poly1305": {
"hashes": [
@ -160,6 +160,7 @@
"sha256:d9ed28030797c00f4bc43c86bf819266c76a5ea61d006cd4078a93ebf7da6bfd",
"sha256:e603aa7bb52e4e8ed4119a58a03b60323918467ef209e6ff9db3ac382e5cf2c6"
],
"index": "pypi",
"version": "==2.6.1"
},
"ctypeslib2": {
@ -169,11 +170,26 @@
],
"version": "==2.2.2"
},
"curve25519-donna": {
"hashes": [
"sha256:1818a9d5356a05c022cd504f44fe1d2f641a5c020f8a4c51b2294e02bd9c1bf0"
],
"index": "pypi",
"version": "==1.3"
},
"demjson": {
"hashes": [
"sha256:31de2038a0fdd9c4c11f8bf3b13fe77bc2a128307f965c8d5fb4dc6d6f6beb79"
],
"index": "pypi",
"version": "==2.2.4"
},
"ecdsa": {
"hashes": [
"sha256:20c17e527e75acad8f402290e158a6ac178b91b881f941fc6ea305bfdfb9657c",
"sha256:5c034ffa23413ac923541ceb3ac14ec15a0d2530690413bff58c12b80e56d884"
],
"index": "pypi",
"version": "==0.13.2"
},
"ed25519": {
@ -205,6 +221,23 @@
"index": "pypi",
"version": "==3.7.7"
},
"graphviz": {
"hashes": [
"sha256:0e1744a45b0d707bc44f99c7b8e5f25dc22cf96b6aaf2432ac308ed9822a9cb6",
"sha256:d311be4fddfe832a56986ac5e1d6e8715d7fcb0208560da79d1bb0f72abef41f"
],
"index": "pypi",
"version": "==0.10.1"
},
"hypothesis": {
"hashes": [
"sha256:4e1378aec40b109f2212f8416a0ef27635b40fdc22a7a8116cd5527776ce1f9e",
"sha256:63d33b2394410ab09a05a19354d826e2aa7814288b0800eb5e89857181def40a",
"sha256:905395b9da7fe04e5ce32b41eace83b613586a104db4b4b0a2552db980a40dd2"
],
"index": "pypi",
"version": "==4.18.0"
},
"idna": {
"hashes": [
"sha256:c357b3f628cf53ae2c4c05627ecc484553142ca23264e593d327bcde5e9c3407",
@ -441,6 +474,14 @@
"index": "pypi",
"version": "==0.1.1"
},
"pyasn1": {
"hashes": [
"sha256:da2420fe13a9452d8ae97a0e478adde1dee153b11ba832a95b223a2ba01c10f7",
"sha256:da6b43a8c9ae93bc80e2739efb38cc776ba74a886e3e9318d65fe81a8b8a2c6e"
],
"index": "pypi",
"version": "==0.4.5"
},
"pyblake2": {
"hashes": [
"sha256:3757f7ad709b0e1b2a6b3919fa79fe3261f166fc375cd521f2be480f8319dde9",
@ -453,6 +494,7 @@
"sha256:c53417ee0bbe77db852d5fd1036749f03696ebc2265de359fe17418d800196c4",
"sha256:fbc9fcde75713930bc2a91b149e97be2401f7c9c56d735b46a109210f58d7358"
],
"index": "pypi",
"version": "==1.1.2"
},
"pycodestyle": {
@ -543,6 +585,14 @@
"index": "pypi",
"version": "==2.21.0"
},
"scons": {
"hashes": [
"sha256:8c2353ae3ce559e9361baa254c0c85d3eb099d5f96e44b5bc586801b7c756a06",
"sha256:e95eaae17d9e490cf12cd37f091a6cbee8a628b5c8dbd3cab1f348f602f46462"
],
"index": "pypi",
"version": "==3.0.5"
},
"shlib": {
"hashes": [
"sha256:f9798b0a3e37407171f06efca7c213269f034eee2c94dd9933a819730a6d528b"
@ -579,8 +629,16 @@
},
"trezor": {
"editable": true,
"git": "https://github.com/trezor/python-trezor",
"ref": "2813522b05cef4e0e545a101f8b3559a3183b45b"
"path": "./python"
},
"typing": {
"hashes": [
"sha256:4027c5f6127a6267a435201981ba156de91ad0d1d98e9ddc2aa173453453492d",
"sha256:57dcf675a99b74d64dacf6fba08fb17cf7e3d5fdff53d4a30ea2a5e7e52543d4",
"sha256:a4c8473ce11a65999c8f59cb093e70686b6c84c98df58c1dae9b3b196089858a"
],
"index": "pypi",
"version": "==3.6.6"
},
"typing-extensions": {
"hashes": [
@ -599,10 +657,10 @@
},
"virtualenv": {
"hashes": [
"sha256:6aebaf4dd2568a0094225ebbca987859e369e3e5c22dc7d52e5406d504890417",
"sha256:984d7e607b0a5d1329425dd8845bd971b957424b5ba664729fab51ab8c11bc39"
"sha256:15ee248d13e4001a691d9583948ad3947bcb8a289775102e4c4aa98a8b7a6d73",
"sha256:bfc98bb9b42a3029ee41b96dc00a34c2f254cbf7716bec824477b2c82741a5c4"
],
"version": "==16.4.3"
"version": "==16.5.0"
},
"wheel": {
"hashes": [
@ -626,6 +684,7 @@
"sha256:57dcf675a99b74d64dacf6fba08fb17cf7e3d5fdff53d4a30ea2a5e7e52543d4",
"sha256:a4c8473ce11a65999c8f59cb093e70686b6c84c98df58c1dae9b3b196089858a"
],
"index": "pypi",
"version": "==3.6.6"
}
}

View File

@ -1,17 +1,17 @@
# initialize from the image
FROM debian:9
FROM python
ARG TOOLCHAIN_FLAVOR=linux
ENV TOOLCHAIN_FLAVOR=$TOOLCHAIN_FLAVOR
# install build tools and dependencies
ARG EMULATOR=0
ENV EMULATOR=$EMULATOR
RUN apt-get update && apt-get install -y \
build-essential wget git python3-pip
build-essential wget git libsodium-dev graphviz \
valgrind check libssl-dev libusb-1.0-0-dev libudev-dev
# TODO are all apt packages actually needed?
# install dependencies from toolchain source build
@ -31,10 +31,6 @@ ENV TOOLCHAIN_URL=https://developer.arm.com/-/media/Files/downloads/gnu-rm/$TOOL
ENV TOOLCHAIN_HASH_linux=fb31fbdfe08406ece43eef5df623c0b2deb8b53e405e2c878300f7a1f303ee52
ENV TOOLCHAIN_HASH_src=bc228325dbbfaf643f2ee5d19e01d8b1873fcb9c31781b5e1355d40a68704ce7
RUN if [ "$EMULATOR" = 1 ]; then \
apt-get install -y libsdl2-dev libsdl2-image-dev; \
fi
# extract toolchain
RUN cd /opt && wget $TOOLCHAIN_URL
@ -64,14 +60,19 @@ RUN echo "${PROTOBUF_HASH} protoc-${PROTOBUF_VERSION}-linux-x86_64.zip" | sha256
ENV PATH=/opt/$TOOLCHAIN_LONGVER/bin:$PATH
ENV PYTHON=python3
ENV LC_ALL=C.UTF-8 LANG=C.UTF-8
# use zipfile module to extract files world-readable
ENV PYTHON=python
RUN $PYTHON -m zipfile -e "protoc-${PROTOBUF_VERSION}-linux-x86_64.zip" /usr/local && chmod 755 /usr/local/bin/protoc
ENV WORKON_HOME=/tmp/.venvs
# install python dependencies
RUN $PYTHON -m pip install pipenv
RUN pip install pipenv
RUN $PYTHON --version
RUN pip --version
RUN pipenv --version

58
ci/core.yml Normal file
View File

@ -0,0 +1,58 @@
image: registry.corp.sldev.cz/trezor/trezor-firmware/environment
build core firmware:
stage: build
script:
- cd core
- pipenv run make build_cross
- pipenv run make build_boardloader
- pipenv run make build_bootloader
- pipenv run make build_prodtest
- pipenv run make build_firmware
# - test "$TREZOR_MODEL" = "1" || pipenv run make sizecheck
artifacts:
name: "$CI_JOB_NAME-$CI_COMMIT_SHORT_SHA"
paths:
- core/build/firmware/firmware.bin
- core/build/bootloader/bootloader.bin
expire_in: 1 week
build core unix:
stage: build
script:
- cd core
- pipenv run make build_unix_noui
artifacts:
name: "$CI_JOB_NAME-$CI_COMMIT_SHORT_SHA"
untracked: true
expire_in: 1 day
test core unix unit:
stage: test
variables:
GIT_SUBMODULE_STRATEGY: none # no need to fetch submodules
dependencies:
- build core unix
script:
- cd core
- pipenv run make test
test core unix device:
stage: test
variables:
GIT_SUBMODULE_STRATEGY: none # no need to fetch submodules
dependencies:
- build core unix
script:
- cd core
- pipenv run make test_emu
test core unix monero:
stage: test
variables:
GIT_SUBMODULE_STRATEGY: none # no need to fetch submodules
dependencies:
- build core unix
script:
- cd core
- pipenv run make test_emu_monero

23
ci/crypto.yml Normal file
View File

@ -0,0 +1,23 @@
image: registry.corp.sldev.cz/trezor/trezor-firmware/environment
build crypto:
stage: build
script:
- cd crypto
- pipenv run make
artifacts:
name: "$CI_JOB_NAME-$CI_COMMIT_SHORT_SHA"
untracked: true
expire_in: 1 day
test crypto:
stage: test
dependencies:
- build crypto
script:
- cd crypto
- ./tests/aestst
- ./tests/test_check
- CK_TIMEOUT_MULTIPLIER=20 valgrind -q --error-exitcode=1 ./tests/test_check
- ./tests/test_openssl 1000
- ITERS=10 pipenv run pytest tests/ # TODO are ITERS=10 propagated?

16
ci/environment.yml Normal file
View File

@ -0,0 +1,16 @@
environment:
stage: environment
image: docker:latest
variables:
GIT_SUBMODULE_STRATEGY: none # no need to fetch submodules
CONTAINER_NAME: "$CI_REGISTRY/trezor/trezor-firmware/environment"
services:
- docker:dind
before_script:
- docker login $CI_REGISTRY -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD
when: manual
script:
- docker pull $CONTAINER_NAME:latest || true
- docker build --cache-from $CONTAINER_NAME:latest --tag $CONTAINER_NAME:$CI_COMMIT_SHA --tag $CONTAINER_NAME:latest ci/
- docker push $CONTAINER_NAME:$CI_COMMIT_SHA
- docker push $CONTAINER_NAME:latest

56
ci/legacy.yml Normal file
View File

@ -0,0 +1,56 @@
image: registry.corp.sldev.cz/trezor/trezor-firmware/environment
build legacy firmware:
stage: build
script:
- cd legacy
- pipenv run script/cibuild
- pipenv run make -C bootloader
- pipenv run make -C demo
build legacy firmware debug:
stage: build
variables:
DEBUG_LINK: "1"
script:
- cd legacy
- pipenv run script/cibuild
- pipenv run make -C bootloader
- pipenv run make -C demo
build legacy firmware bitcoinonly:
stage: build
variables:
BITCOIN_ONLY: "1"
script:
- cd legacy
- pipenv run script/cibuild
- pipenv run make -C bootloader
- pipenv run make -C demo
build legacy emu:
stage: build
variables:
HEADLESS: "1"
EMULATOR: "1"
DEBUG_LINK: "1"
script:
- cd legacy
- pipenv run script/cibuild
artifacts:
name: "$CI_JOB_NAME-$CI_COMMIT_SHORT_SHA"
untracked: true
expire_in: 1 day
# TODO: aren't some tests from .travis.yml missing?
test legacy emu:
variables:
GIT_SUBMODULE_STRATEGY: none # no need to fetch submodules
stage: test
dependencies:
- build legacy emu
variables:
EMULATOR: "1"
script:
- cd legacy
- pipenv run script/test

18
ci/prebuild.yml Normal file
View File

@ -0,0 +1,18 @@
image: registry.corp.sldev.cz/trezor/trezor-firmware/environment
prebuild style:
stage: prebuild
script:
- pipenv run make style_check
- cd core && pipenv run make templates_check # TODO
prebuild common:
stage: prebuild
script:
- cd common
- pipenv run jsonlint defs/*.json
- pipenv run jsonlint defs/*/*.json
- pipenv run python tools/cointool.py check
- pipenv run python tools/support.py check --ignore-missing
- pipenv run python protob/check.py
- pipenv run python protob/graph.py protob/*.proto # TODO: artifacts?

11
ci/storage.yml Normal file
View File

@ -0,0 +1,11 @@
image: registry.corp.sldev.cz/trezor/trezor-firmware/environment
test storage:
variables:
GIT_SUBMODULE_STRATEGY: none # no need to fetch submodules
stage: test
dependencies: []
script:
- cd storage/tests
- pipenv run make build
- pipenv run make tests_all

View File

@ -1,37 +0,0 @@
language: python
# Runs jobs on container based infrastructure
sudo: false
# Saves pip downloads/wheels between builds
cache:
directories:
- $HOME/.cache/pip
addons:
apt:
packages:
- graphviz
python:
- "3.6"
install:
- pip install demjson graphviz
- pip install -r tools/requirements.txt
script:
- jsonlint defs/*.json
- jsonlint defs/*/*.json
- python tools/cointool.py check
- python tools/support.py check --ignore-missing
- python protob/check.py
- python protob/graph.py protob/*.proto
notifications:
webhooks:
urls:
- http://ci-bot.satoshilabs.com:5000/travis
on_success: always
on_failure: always
on_start: always

View File

@ -0,0 +1,42 @@
{
"coin_name": "BlockStamp",
"coin_shortcut": "BST",
"coin_label": "BlockStamp",
"website": "https://blockstamp.info",
"github": "https://github.com/BlockStamp/bst",
"maintainer": "Krzysztof Kuchta <k.kuchta@blockstamp.info>",
"curve_name": "secp256k1",
"address_type": 26,
"address_type_p2sh": 5,
"maxfee_kb": 2000000,
"minfee_kb": 1000,
"signed_message_header": "BST Signed Message:\n",
"hash_genesis_block": "8000000049a2e26b0185be50b4b8ed58b707c8893762959f0b1673641cae1828",
"xprv_magic": 76066276,
"xpub_magic": 76067358,
"xpub_magic_segwit_p2sh": 77429938,
"xpub_magic_segwit_native": 78792518,
"bech32_prefix": "bst",
"cashaddr_prefix": null,
"slip44": 254,
"segwit": true,
"decred": false,
"fork_id": null,
"force_bip143": false,
"bip115": false,
"default_fee_b": {
"Low": 10,
"Economy": 70,
"Normal": 140,
"High": 200
},
"dust_limit": 546,
"blocktime_seconds": 60,
"uri_prefix": "blockstamp",
"min_address_length": 27,
"max_address_length": 34,
"bitcore": [],
"blockbook": [],
"cooldown": 1000,
"consensus_branch_id": null
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.9 KiB

After

Width:  |  Height:  |  Size: 11 KiB

View File

@ -8,8 +8,8 @@
"curve_name": "secp256k1",
"address_type": 36,
"address_type_p2sh": 16,
"maxfee_kb": 10000000,
"minfee_kb": 100000,
"maxfee_kb": 1000000000,
"minfee_kb": 10000000,
"signed_message_header": "FujiCoin Signed Message:\n",
"hash_genesis_block": "adb6d9cfd74075e7f91608add4bd2a2ea636f70856183086842667a1597714a0",
"xpub_magic": 76067358,
@ -25,10 +25,10 @@
"force_bip143": false,
"bip115": false,
"default_fee_b": {
"Low": 100,
"Economy": 200,
"Normal": 500,
"High": 1000
"Low": 10000,
"Economy": 20000,
"Normal": 50000,
"High": 100000
},
"dust_limit": 546,
"blocktime_seconds": 60,

View File

@ -96,6 +96,7 @@
"bitcoin:BCH": "1.6.2",
"bitcoin:BITC": "1.7.2",
"bitcoin:BSD": "1.7.2",
"bitcoin:BST": "soon",
"bitcoin:BTC": "1.5.2",
"bitcoin:BTCP": "1.6.2",
"bitcoin:BTDX": "1.7.2",
@ -106,6 +107,7 @@
"bitcoin:DGB": "1.6.3",
"bitcoin:DNR": "1.7.1",
"bitcoin:DOGE": "1.5.2",
"bitcoin:FAIR": "soon",
"bitcoin:FJC": "1.6.1",
"bitcoin:FLASH": "1.7.1",
"bitcoin:FLO": "1.7.2",
@ -122,8 +124,10 @@
"bitcoin:NIX": "1.7.2",
"bitcoin:NMC": "1.5.2",
"bitcoin:PIVX": "1.8.0",
"bitcoin:POLIS": "soon",
"bitcoin:PTC": "1.7.1",
"bitcoin:QTUM": "1.8.1",
"bitcoin:REGTEST": "1.8.2",
"bitcoin:RVN": "1.7.2",
"bitcoin:SMART": "1.7.1",
"bitcoin:TAZ": "1.6.2",
@ -135,6 +139,7 @@
"bitcoin:VTC": "1.6.1",
"bitcoin:XMY": "1.7.1",
"bitcoin:XPM": "1.8.0",
"bitcoin:XRC": "soon",
"bitcoin:XSN": "1.8.0",
"bitcoin:XZC": "1.6.2",
"bitcoin:ZCL": "1.8.0",
@ -284,7 +289,6 @@
"erc20:eth:BRD": "1.6.2",
"erc20:eth:BRLN": "1.8.0",
"erc20:eth:BSDC": "1.6.2",
"erc20:eth:BST": "1.6.2",
"erc20:eth:BTCA": "1.8.0",
"erc20:eth:BTCE": "1.6.2",
"erc20:eth:BTCL": "1.6.2",
@ -1232,9 +1236,11 @@
"eth:ETC": "1.6.2",
"eth:ETH": "1.6.2",
"eth:ETHO": "1.6.3",
"eth:ETI": "soon",
"eth:ETSC": "1.6.2",
"eth:EXP": "1.6.2",
"eth:GO": "1.6.2",
"eth:META": "soon",
"eth:MIX": "1.7.2",
"eth:MUSIC": "1.6.3",
"eth:PIRL": "1.6.3",
@ -1261,6 +1267,7 @@
"nem:XEM": "1.6.2"
},
"unsupported": {
"bitcoin:CPC": "not implemented",
"bitcoin:CRW": "address_type collides with Bitcoin",
"bitcoin:TRC": "address_type collides with Bitcoin",
"bitcoin:ZEN": "not implemented",
@ -1278,6 +1285,7 @@
"erc20:eth:BNC:ef51": "(AUTO) duplicate key",
"erc20:eth:BOX:63f5": "(AUTO) duplicate key",
"erc20:eth:BOX:e1a1": "(AUTO) duplicate key",
"erc20:eth:BST": "(AUTO) duplicate key",
"erc20:eth:BTL (Battle)": "(AUTO) duplicate key",
"erc20:eth:BTL (Bitlle)": "(AUTO) duplicate key",
"erc20:eth:BTR:499a": "(AUTO) duplicate key",
@ -1417,12 +1425,14 @@
"erc20:eth:YEED:6f7a": "(AUTO) duplicate key",
"erc20:eth:YEED:ca27": "(AUTO) duplicate key",
"misc:ADA": "not implemented",
"misc:BNB": "not implemented",
"misc:EOS": "not implemented",
"misc:ONT": "not implemented",
"misc:TRX": "not implemented",
"misc:XMR": "not implemented",
"misc:XRP": "not implemented",
"misc:XTZ": "not implemented"
"misc:XTZ": "not implemented",
"misc:tXRP": "not implemented"
}
},
"trezor2": {
@ -1432,6 +1442,7 @@
"bitcoin:BCH": "2.0.7",
"bitcoin:BITC": "2.0.10",
"bitcoin:BSD": "2.0.10",
"bitcoin:BST": "soon",
"bitcoin:BTC": "2.0.5",
"bitcoin:BTCP": "2.0.7",
"bitcoin:BTDX": "2.0.10",
@ -1443,6 +1454,7 @@
"bitcoin:DGB": "2.0.7",
"bitcoin:DNR": "2.0.8",
"bitcoin:DOGE": "2.0.5",
"bitcoin:FAIR": "soon",
"bitcoin:FJC": "2.0.5",
"bitcoin:FLASH": "2.0.8",
"bitcoin:FLO": "2.0.11",
@ -1459,8 +1471,10 @@
"bitcoin:NIX": "2.0.11",
"bitcoin:NMC": "2.0.5",
"bitcoin:PIVX": "2.0.11",
"bitcoin:POLIS": "soon",
"bitcoin:PTC": "2.0.8",
"bitcoin:QTUM": "2.1.1",
"bitcoin:REGTEST": "2.1.2",
"bitcoin:RVN": "2.0.10",
"bitcoin:SMART": "2.0.8",
"bitcoin:TAZ": "2.0.7",
@ -1472,6 +1486,7 @@
"bitcoin:VTC": "2.0.5",
"bitcoin:XMY": "2.0.8",
"bitcoin:XPM": "2.0.11",
"bitcoin:XRC": "soon",
"bitcoin:XSN": "2.0.11",
"bitcoin:XZC": "2.0.7",
"bitcoin:ZCL": "2.0.11",
@ -1622,7 +1637,6 @@
"erc20:eth:BRD": "2.0.7",
"erc20:eth:BRLN": "2.0.10",
"erc20:eth:BSDC": "2.0.7",
"erc20:eth:BST": "2.0.7",
"erc20:eth:BTCA": "2.0.10",
"erc20:eth:BTCE": "2.0.7",
"erc20:eth:BTCL": "2.0.7",
@ -2570,9 +2584,11 @@
"eth:ETC": "2.0.7",
"eth:ETH": "2.0.7",
"eth:ETHO": "2.0.8",
"eth:ETI": "soon",
"eth:ETSC": "2.0.7",
"eth:EXP": "2.0.7",
"eth:GO": "2.0.7",
"eth:META": "soon",
"eth:MIX": "2.0.10",
"eth:MUSIC": "2.0.8",
"eth:PIRL": "2.0.8",
@ -2620,6 +2636,7 @@
"erc20:eth:BNC:ef51": "(AUTO) duplicate key",
"erc20:eth:BOX:63f5": "(AUTO) duplicate key",
"erc20:eth:BOX:e1a1": "(AUTO) duplicate key",
"erc20:eth:BST": "(AUTO) duplicate key",
"erc20:eth:BTL (Battle)": "(AUTO) duplicate key",
"erc20:eth:BTL (Bitlle)": "(AUTO) duplicate key",
"erc20:eth:BTR:499a": "(AUTO) duplicate key",

View File

@ -1,13 +1,12 @@
#!/usr/bin/env python3
import json
import sys
from glob import glob
import json
from hashlib import sha256
try:
opt = sys.argv[1]
except:
except IndexError:
print("Usage: gen.py [core|mcu|check])")
sys.exit(1)
@ -22,12 +21,12 @@ def gen_core(data):
for d in data:
if "u2f" in d:
url, label = d["u2f"], d["label"]
print(" \"%s\": \"%s\"," % (url, label))
print(' "%s": "%s",' % (url, label))
print(" # WebAuthn")
for d in data:
if "webauthn" in d:
origin, label = d["webauthn"], d["label"]
print(" \"%s\": \"%s\"," % (origin, label))
print(' "%s": "%s",' % (origin, label))
print("}")
@ -36,12 +35,17 @@ def gen_mcu(data):
if "u2f" in d:
url, label = d["u2f"], d["label"]
h = sha256(url.encode()).digest()
print("\t{\n\t\t// U2F: %s\n\t\t%s,\n\t\t\"%s\"\n\t}," % (url, c_bytes(h), label))
print(
'\t{\n\t\t// U2F: %s\n\t\t%s,\n\t\t"%s"\n\t},'
% (url, c_bytes(h), label)
)
if "webauthn" in d:
origin, label = d["webauthn"], d["label"]
h = sha256(origin.encode()).digest()
print("\t{\n\t\t// WebAuthn: %s\n\t\t%s,\n\t\t\"%s\"\n\t}," % (origin, c_bytes(h), label))
print(
'\t{\n\t\t// WebAuthn: %s\n\t\t%s,\n\t\t"%s"\n\t},'
% (origin, c_bytes(h), label)
)
data = []

View File

@ -1,3 +1,4 @@
// clang-format off
// TREZORv1 production public keys
"\x04\xd5\x71\xb7\xf1\x48\xc5\xe4\x23\x2c\x38\x14\xf7\x77\xd8\xfa\xea\xf1\xa8\x42\x16\xc7\x8d\x56\x9b\x71\x04\x1f\xfc\x76\x8a\x5b\x2d\x81\x0f\xc3\xbb\x13\x4d\xd0\x26\xb5\x7e\x65\x00\x52\x75\xae\xde\xf4\x3e\x15\x5f\x48\xfc\x11\xa3\x2e\xc7\x90\xa9\x33\x12\xbd\x58",
"\x04\x63\x27\x9c\x0c\x08\x66\xe5\x0c\x05\xc7\x99\xd3\x2b\xd6\xba\xb0\x18\x8b\x6d\xe0\x65\x36\xd1\x10\x9d\x2e\xd9\xce\x76\xcb\x33\x5c\x49\x0e\x55\xae\xe1\x0c\xc9\x01\x21\x51\x32\xe8\x53\x09\x7d\x54\x32\xed\xa0\x6b\x79\x20\x73\xbd\x77\x40\xc9\x4c\xe4\x51\x6c\xb1",

View File

@ -1,2 +1,3 @@
// clang-format off
// sample public key "correct horse battery staple"
"\x04\x78\xd4\x30\x27\x4f\x8c\x5e\xc1\x32\x13\x38\x15\x1e\x9f\x27\xf4\xc6\x76\xa0\x08\xbd\xf8\x63\x8d\x07\xc0\xb6\xbe\x9a\xb3\x5c\x71\xa1\x51\x80\x63\x24\x3a\xcd\x4d\xfe\x96\xb6\x6e\x3f\x2e\xc8\x01\x3c\x8e\x07\x2c\xd0\x9b\x38\x34\xa1\x9f\x81\xf6\x59\xcc\x34\x55"

View File

@ -1,8 +1,8 @@
#!/usr/bin/env python3
from glob import glob
import os
import re
import sys
from glob import glob
error = False
@ -21,7 +21,9 @@ for fn in sorted(glob(os.path.join(MYDIR, "messages-*.proto"))):
line = line.strip().split(" ")
if line[0] not in ["enum", "message"]:
continue
if not line[1].startswith(prefix) and not line[1].startswith("Debug" + prefix):
if not line[1].startswith(prefix) and not line[1].startswith(
"Debug" + prefix
):
print("ERROR:", fn, line[1])
error = True

View File

@ -55,6 +55,8 @@ message TezosSignTx {
optional TezosTransactionOp transaction = 4; // Tezos transaction operation
optional TezosOriginationOp origination = 5; // Tezos origination operation
optional TezosDelegationOp delegation = 6; // Tezos delegation operation
optional TezosProposalOp proposal = 7; // Tezos proposal operation
optional TezosBallotOp ballot = 8; // Tezos ballot operation
/*
* Tezos contract ID
*/
@ -120,6 +122,29 @@ message TezosSignTx {
optional uint64 storage_limit = 5;
optional bytes delegate = 6;
}
/**
* Structure representing information for proposal
*/
message TezosProposalOp {
optional bytes source = 1; //Contains only public_key_hash, not to be confused with TezosContractID
optional uint64 period = 2;
repeated bytes proposals = 4;
}
/**
* Structure representing information for ballot
*/
message TezosBallotOp {
optional bytes source = 1; //Contains only public_key_hash, not to be confused with TezosContractID
optional uint64 period = 2;
optional bytes proposal = 3;
optional TezosBallotType ballot = 4;
enum TezosBallotType {
Yay = 0;
Nay = 1;
Pass = 2;
}
}
}
/**

View File

@ -1,10 +1,10 @@
#!/usr/bin/env python3
from collections import defaultdict, OrderedDict
import re
import os
import json
import glob
import json
import logging
import os
import re
from collections import OrderedDict, defaultdict
try:
import requests

View File

@ -3,38 +3,38 @@ from trezorlib import protobuf as p
class CoinDef(p.MessageType):
FIELDS = {
1: ('coin_name', p.UnicodeType, 0),
2: ('coin_shortcut', p.UnicodeType, 0),
3: ('coin_label', p.UnicodeType, 0),
4: ('curve_name', p.UnicodeType, 0),
5: ('address_type', p.UVarintType, 0),
6: ('address_type_p2sh', p.UVarintType, 0),
7: ('maxfee_kb', p.UVarintType, 0),
8: ('minfee_kb', p.UVarintType, 0),
9: ('signed_message_header', p.BytesType, 0),
10: ('hash_genesis_block', p.BytesType, 0),
11: ('xprv_magic', p.UVarintType, 0),
12: ('xpub_magic', p.UVarintType, 0),
13: ('xpub_magic_segwit_p2sh', p.UVarintType, 0),
14: ('xpub_magic_segwit_native', p.UVarintType, 0),
15: ('bech32_prefix', p.UnicodeType, 0),
16: ('cashaddr_prefix', p.UnicodeType, 0),
17: ('slip44', p.UVarintType, 0),
18: ('segwit', p.BoolType, 0),
19: ('decred', p.BoolType, 0),
20: ('fork_id', p.UVarintType, 0),
21: ('force_bip143', p.BoolType, 0),
22: ('dust_limit', p.UVarintType, 0),
23: ('uri_prefix', p.UnicodeType, 0),
24: ('min_address_length', p.UVarintType, 0),
25: ('max_address_length', p.UVarintType, 0),
26: ('icon', p.BytesType, 0),
28: ('website', p.UnicodeType, 0),
29: ('github', p.UnicodeType, 0),
30: ('maintainer', p.UnicodeType, 0),
31: ('blocktime_seconds', p.UVarintType, 0),
32: ('bip115', p.BoolType, 0),
33: ('cooldown', p.UVarintType, 0),
1: ("coin_name", p.UnicodeType, 0),
2: ("coin_shortcut", p.UnicodeType, 0),
3: ("coin_label", p.UnicodeType, 0),
4: ("curve_name", p.UnicodeType, 0),
5: ("address_type", p.UVarintType, 0),
6: ("address_type_p2sh", p.UVarintType, 0),
7: ("maxfee_kb", p.UVarintType, 0),
8: ("minfee_kb", p.UVarintType, 0),
9: ("signed_message_header", p.BytesType, 0),
10: ("hash_genesis_block", p.BytesType, 0),
11: ("xprv_magic", p.UVarintType, 0),
12: ("xpub_magic", p.UVarintType, 0),
13: ("xpub_magic_segwit_p2sh", p.UVarintType, 0),
14: ("xpub_magic_segwit_native", p.UVarintType, 0),
15: ("bech32_prefix", p.UnicodeType, 0),
16: ("cashaddr_prefix", p.UnicodeType, 0),
17: ("slip44", p.UVarintType, 0),
18: ("segwit", p.BoolType, 0),
19: ("decred", p.BoolType, 0),
20: ("fork_id", p.UVarintType, 0),
21: ("force_bip143", p.BoolType, 0),
22: ("dust_limit", p.UVarintType, 0),
23: ("uri_prefix", p.UnicodeType, 0),
24: ("min_address_length", p.UVarintType, 0),
25: ("max_address_length", p.UVarintType, 0),
26: ("icon", p.BytesType, 0),
28: ("website", p.UnicodeType, 0),
29: ("github", p.UnicodeType, 0),
30: ("maintainer", p.UnicodeType, 0),
31: ("blocktime_seconds", p.UVarintType, 0),
32: ("bip115", p.BoolType, 0),
33: ("cooldown", p.UVarintType, 0),
}
def __init__(
@ -73,7 +73,7 @@ class CoinDef(p.MessageType):
default_fee_b: dict = None,
bitcore: dict = None,
blockbook: dict = None,
cooldown: int = None
cooldown: int = None,
):
self.coin_name = coin_name
self.coin_shortcut = coin_shortcut

View File

@ -1,14 +1,15 @@
#!/usr/bin/env python3
"""Fetch information about coins and tokens supported by Trezor and update it in coins_details.json."""
import os
import time
import json
import logging
import requests
import os
import sys
import coin_info
import time
import click
import requests
import coin_info
LOG = logging.getLogger(__name__)
@ -149,7 +150,7 @@ def summary(coins, api_key):
try:
ret = coinmarketcap_call("global-metrics/quotes/latest", api_key)
total_marketcap = int(ret["data"]["quote"]["USD"]["total_market_cap"])
except:
except Exception:
pass
return dict(

View File

@ -1,13 +1,13 @@
#!/usr/bin/env python3
import fnmatch
import glob
import io
import json
import logging
import re
import sys
import os
import glob
import re
import struct
import sys
import zlib
from collections import defaultdict
from hashlib import sha256
@ -209,7 +209,7 @@ def check_btc(coins):
for coin in bucket:
name = coin["name"]
prefix = ""
if name.endswith("Testnet"):
if name.endswith("Testnet") or name.endswith("Regtest"):
color = "green"
elif name == "Bitcoin":
color = "red"
@ -232,7 +232,12 @@ def check_btc(coins):
"""
failed = False
for key, bucket in buckets.items():
mainnets = [c for c in bucket if not c["name"].endswith("Testnet")]
mainnets = [
c
for c in bucket
if not c["name"].endswith("Testnet")
and not c["name"].endswith("Regtest")
]
have_bitcoin = False
for coin in mainnets:
@ -524,8 +529,7 @@ def cli(colors):
# fmt: off
@click.option("--backend/--no-backend", "-b", default=False, help="Check blockbook/bitcore responses")
@click.option("--icons/--no-icons", default=True, help="Check icon files")
@click.option("-d", "--show-duplicates", type=click.Choice(("all", "nontoken", "errors")),
default="errors", help="How much information about duplicate shortcuts should be shown.")
@click.option("-d", "--show-duplicates", type=click.Choice(("all", "nontoken", "errors")), default="errors", help="How much information about duplicate shortcuts should be shown.")
# fmt: on
def check(backend, icons, show_duplicates):
"""Validate coin definitions.
@ -779,8 +783,9 @@ def coindefs(outfile):
@click.argument("paths", metavar="[path]...", nargs=-1)
@click.option("-o", "--outfile", type=click.File("w"), help="Alternate output file")
@click.option("-v", "--verbose", is_flag=True, help="Print rendered file names")
@click.option("-b", "--bitcoin-only", is_flag=True, help="Accept only Bitcoin coins")
# fmt: on
def render(paths, outfile, verbose):
def render(paths, outfile, verbose, bitcoin_only):
"""Generate source code from Mako templates.
For every "foo.bar.mako" filename passed, runs the template and
@ -801,6 +806,13 @@ def render(paths, outfile, verbose):
defs = coin_info.coin_info()
support_info = coin_info.support_info(defs)
if bitcoin_only:
defs["bitcoin"] = [
x
for x in defs["bitcoin"]
if x["coin_name"] in ("Bitcoin", "Testnet", "Regtest")
]
# munch dicts - make them attribute-accessible
for key, value in defs.items():
defs[key] = [Munch(coin) for coin in value]

View File

@ -1,13 +1,12 @@
#!/usr/bin/env python3
import click
import json
import os
import requests
import tempfile
import subprocess
import sys
import tempfile
import click
import requests
LIVE_URL = "https://trezor.io/static/json/coins_details.json"
COINS_DETAILS = os.path.join(

View File

@ -1,16 +0,0 @@
click>=6
# for `coin_gen coindefs` and checking icons:
ed25519>=1.4
Pillow>=5.2.0
trezor>=0.10
# for checking backends, generating coins_details.json
requests>=2.19
# for rendering templates:
Mako>=1.0.7
munch>=2.3.2
# for pretty colors in checks
termcolor >= 0.1.2

View File

@ -1,11 +1,13 @@
#!/usr/bin/env python3
import re
import json
import os
import re
import subprocess
import sys
import click
import coin_info
import json
SUPPORT_INFO = coin_info.get_support_data()

View File

@ -1,78 +0,0 @@
sudo: false
dist: trusty
language: c
addons:
apt:
sources:
- deadsnakes
packages:
- build-essential
- python3.6
- python3.6-dev
- python3.6-venv
- libusb-1.0-0-dev
- libudev-dev
env:
global:
- MAKEFLAGS=-j2
- PYTHON=python3.6
- PROTOBUF_VERSION=3.4.0
- TOOLCHAIN_SHORTVER=8-2018q4
- TOOLCHAIN_LONGVER=gcc-arm-none-eabi-8-2018-q4-major
matrix:
- GOAL=stm32
- GOAL=unix
- GOAL=src
matrix:
include:
- compiler: clang
env: GOAL=unix
cache:
directories:
- $HOME/libsodium
before_install:
- $PYTHON -m ensurepip --user
- $PYTHON -m pip install --user pipenv
install:
- ./travis-install-libsodium.sh
- export PKG_CONFIG_PATH=$HOME/libsodium/lib/pkgconfig:$PKG_CONFIG_PATH
- export LD_LIBRARY_PATH=$HOME/libsodium/lib:$LD_LIBRARY_PATH
- wget "https://github.com/google/protobuf/releases/download/v${PROTOBUF_VERSION}/protoc-${PROTOBUF_VERSION}-linux-x86_64.zip"
- unzip "protoc-${PROTOBUF_VERSION}-linux-x86_64.zip" -d protoc
- export PATH="$(pwd)/protoc/bin:$PATH"
- pipenv install
before_script:
- test "$GOAL" != "stm32" || wget https://developer.arm.com/-/media/Files/downloads/gnu-rm/$TOOLCHAIN_SHORTVER/$TOOLCHAIN_LONGVER-linux.tar.bz2
- test "$GOAL" != "stm32" || tar xfj $TOOLCHAIN_LONGVER-linux.tar.bz2
- test "$GOAL" != "stm32" || export PATH=$PWD/$TOOLCHAIN_LONGVER/bin:$PATH
script:
- test "$GOAL" != "src" || pipenv run make style_check
- test "$GOAL" != "src" || pipenv run make templates_check
- test "$GOAL" != "stm32" || pipenv run make build_cross
- test "$GOAL" != "stm32" || pipenv run make build_boardloader
- test "$GOAL" != "stm32" || pipenv run make build_bootloader
- test "$GOAL" != "stm32" || pipenv run make build_prodtest
- test "$GOAL" != "stm32" || pipenv run make build_firmware
- test "$GOAL" != "stm32" || test "$TREZOR_MODEL" = "1" || pipenv run make sizecheck
- test "$GOAL" != "unix" || pipenv run make build_unix_noui
- test "$GOAL" != "unix" || pipenv run make test
- test "$GOAL" != "unix" || test "$TREZOR_MODEL" = "1" || pipenv run make test_emu
- test "$GOAL" != "unix" || test "$TREZOR_MODEL" = "1" || pipenv run make test_emu_monero
notifications:
webhooks:
urls:
- http://ci-bot.satoshilabs.com:5000/travis
on_success: always
on_failure: always
on_start: always

View File

@ -1,5 +1,11 @@
Version 2.1.0
* stable release, optional update
Version 2.1.1 [unreleased]
* More strict path validations
* Display non-zero locktime values
* Don't rotate the screen via swipe gesture
* Set screen rotation via user setting
* Monero UI fixes
Version 2.1.0 [Mar 2019]
* Security improvements
* Upgraded to new storage format
* Ripple, Stellar, Cardano and NEM fixes
@ -7,20 +13,17 @@ Version 2.1.0
PIVX, REOSC, XPM, XSN, ZCL
* New ETH tokens
Version 2.0.10
* stable release, optional update
Version 2.0.10 [Dec 2018]
* Fix Monero payment ID computation
* Fix issue with touch screen and flickering
* Add support for OMNI layer: OMNI/MAID/USDT
* Add support for new coins: BTX, CPC, GAME, RVN
* Add support for new Ethereum tokens
Version 2.0.9
* stable release, optional update
Version 2.0.9 [Nov 2018]
* Small Monero and Segwit bugfixes
Version 2.0.8
* stable release, optional update
Version 2.0.8 [Oct 2018]
* Monero support
* Cardano support
* Stellar support
@ -32,25 +35,22 @@ Version 2.0.8
* Zcash sapling hardfork support
* Implemented seedless setup
Version 2.0.7
* stable release, optional update
Version 2.0.7 [Jun 2018]
* Bitcoin Cash cashaddr support
* Zcash Overwinter hardfork support
* NEM support
* Lisk support
* Show warning on home screen if PIN is not set
* Support for new coins:
- Bitcoin Private, Fujicoin, Vertcoin, Viacoin, Zcoin
Bitcoin Private, Fujicoin, Vertcoin, Viacoin, Zcoin
* Support for new Ethereum networks:
- EOS Classic, Ethereum Social, Ellaism, Callisto, EtherGem, Wanchain
EOS Classic, Ethereum Social, Ellaism, Callisto, EtherGem, Wanchain
* Support for 500+ new Ethereum tokens
Version 2.0.6
* stable release, optional update
Version 2.0.6 [Mar 2018]
* fix layout for Ethereum transactions
* fix public key generation for SSH and GPG
* add special characters to passphrase keyboard
Version 2.0.5
* stable release, required update
Version 2.0.5 [Mar 2018]
* first public release

View File

@ -1,69 +0,0 @@
# initialize from the image
FROM debian:9
ARG TOOLCHAIN_FLAVOR=linux
ENV TOOLCHAIN_FLAVOR=$TOOLCHAIN_FLAVOR
# install build tools and dependencies
RUN apt-get update && apt-get install -y \
build-essential wget git python3-pip
# install dependencies from toolchain source build
RUN if [ "$TOOLCHAIN_FLAVOR" = "src" ]; then \
apt-get install -y autoconf autogen bison dejagnu \
flex flip gawk git gperf gzip nsis \
openssh-client p7zip-full perl python-dev \
libisl-dev tcl tofrodos zip \
texinfo texlive texlive-extra-utils; \
fi
# download toolchain
ENV TOOLCHAIN_SHORTVER=8-2018q4
ENV TOOLCHAIN_LONGVER=gcc-arm-none-eabi-8-2018-q4-major
ENV TOOLCHAIN_URL=https://developer.arm.com/-/media/Files/downloads/gnu-rm/$TOOLCHAIN_SHORTVER/$TOOLCHAIN_LONGVER-$TOOLCHAIN_FLAVOR.tar.bz2
ENV TOOLCHAIN_HASH_linux=fb31fbdfe08406ece43eef5df623c0b2deb8b53e405e2c878300f7a1f303ee52
ENV TOOLCHAIN_HASH_src=bc228325dbbfaf643f2ee5d19e01d8b1873fcb9c31781b5e1355d40a68704ce7
# extract toolchain
RUN cd /opt && wget $TOOLCHAIN_URL
RUN cd /opt && echo "$TOOLCHAIN_HASH_linux $TOOLCHAIN_LONGVER-linux.tar.bz2\n$TOOLCHAIN_HASH_src $TOOLCHAIN_LONGVER-src.tar.bz2" | sha256sum -c --ignore-missing
RUN cd /opt && tar xfj $TOOLCHAIN_LONGVER-$TOOLCHAIN_FLAVOR.tar.bz2
# build toolchain (if required)
RUN if [ "$TOOLCHAIN_FLAVOR" = "src" ]; then \
pushd /opt/$TOOLCHAIN_LONGVER ; \
./install-sources.sh --skip_steps=mingw32 ; \
./build-prerequisites.sh --skip_steps=mingw32 ; \
./build-toolchain.sh --skip_steps=mingw32,manual ; \
popd ; \
fi
# download protobuf
ENV PROTOBUF_VERSION=3.4.0
ENV PROTOBUF_HASH=e4b51de1b75813e62d6ecdde582efa798586e09b5beaebfb866ae7c9eaadace4
RUN wget "https://github.com/google/protobuf/releases/download/v${PROTOBUF_VERSION}/protoc-${PROTOBUF_VERSION}-linux-x86_64.zip"
RUN echo "${PROTOBUF_HASH} protoc-${PROTOBUF_VERSION}-linux-x86_64.zip" | sha256sum -c
# setup toolchain
ENV PATH=/opt/$TOOLCHAIN_LONGVER/bin:$PATH
ENV PYTHON=python3
ENV LC_ALL=C.UTF-8 LANG=C.UTF-8
RUN ln -s /usr/bin/python3 /usr/bin/python
# use zipfile module to extract files world-readable
RUN $PYTHON -m zipfile -e "protoc-${PROTOBUF_VERSION}-linux-x86_64.zip" /usr/local && chmod 755 /usr/local/bin/protoc
# install python dependencies
RUN $PYTHON -m pip install scons trezor

View File

@ -39,7 +39,7 @@ CFLAGS += -DGITREV=$(GITREV)
## help commands:
help: ## show this help
@awk -f help.awk $(MAKEFILE_LIST)
@awk -f ../tools/help.awk $(MAKEFILE_LIST)
## dependencies commands:
@ -71,27 +71,6 @@ test_emu_monero: ## run selected monero device tests from monero-agent
pylint: ## run pylint on application sources and tests
pylint -E $(shell find src tests -name *.py)
## style commands:
style_check: ## run code style check on application sources and tests
flake8 --version
isort --version | grep "VERSION"
black --version
flake8 $(shell find src -name *.py)
isort --check-only $(shell find src -name *.py ! -path 'src/trezor/messages/*')
black --check $(shell find src -name *.py ! -path 'src/trezor/messages/*')
style: ## apply code style on application sources and tests
isort $(shell find src -name *.py ! -path 'src/trezor/messages/*')
black $(shell find src -name *.py ! -path 'src/trezor/messages/*')
cstyle_check: ## run code style check on low-level C code
./tools/clang-format-check embed/*/*.{c,h} embed/extmod/modtrezor*/*.{c,h}
cstyle: ## apply code style on low-level C code
clang-format -i embed/*/*.{c,h} embed/extmod/modtrezor*/*.{c,h}
## code generation:
templates: ## render Mako templates (for lists of coins, tokens, etc.)

View File

@ -1,6 +1,8 @@
#!/bin/sh
set -e
cd "$(dirname $0)/.."
if [ "$1" = "--gcc_source" ]; then
TOOLCHAIN_FLAVOR=src
shift
@ -16,16 +18,19 @@ PRODUCTION=${PRODUCTION:-0}
if [ "$REPOSITORY" = "local" ]; then
REPOSITORY=file:///local/
else
REPOSITORY=https://github.com/$REPOSITORY/trezor-core.git
REPOSITORY=https://github.com/$REPOSITORY/trezor-firmware.git
fi
docker build -t $IMAGE --build-arg TOOLCHAIN_FLAVOR=$TOOLCHAIN_FLAVOR .
docker build -t $IMAGE --build-arg TOOLCHAIN_FLAVOR=$TOOLCHAIN_FLAVOR ci/
mkdir -p $(pwd)/build-docker
docker run -t -v $(pwd):/local -v $(pwd)/build-docker:/build:z --user="$(stat -c "%u:%g" .)" $IMAGE /bin/sh -c "\
USER=$(ls -lnd . | awk '{ print $3 }')
GROUP=$(ls -lnd . | awk '{ print $4 }')
mkdir -p $(pwd)/build/core
docker run -t -v $(pwd):/local -v $(pwd)/build/core:/build:z --user="$USER:$GROUP" $IMAGE /bin/sh -c "\
cd /tmp && \
git clone $REPOSITORY trezor-core && \
cd trezor-core && \
git clone $REPOSITORY trezor-firmware && \
cd trezor-firmware/core && \
ln -s /build build &&
git checkout $TAG && \
git submodule update --init --recursive && \

View File

@ -236,7 +236,7 @@ void ui_screen_install_confirm_newvendor(const vendor_header *const vhdr,
void ui_screen_install(void) {
display_bar(0, 0, DISPLAY_RESX, DISPLAY_RESY, COLOR_WHITE);
display_loader(0, -20, COLOR_BL_PROCESS, COLOR_WHITE, toi_icon_install,
display_loader(0, false, -20, COLOR_BL_PROCESS, COLOR_WHITE, toi_icon_install,
sizeof(toi_icon_install), COLOR_BLACK);
display_text_center(DISPLAY_RESX / 2, DISPLAY_RESY - 24,
"Installing firmware", -1, FONT_NORMAL, COLOR_BLACK,
@ -244,13 +244,13 @@ void ui_screen_install(void) {
}
void ui_screen_install_progress_erase(int pos, int len) {
display_loader(250 * pos / len, -20, COLOR_BL_PROCESS, COLOR_WHITE,
display_loader(250 * pos / len, false, -20, COLOR_BL_PROCESS, COLOR_WHITE,
toi_icon_install, sizeof(toi_icon_install), COLOR_BLACK);
}
void ui_screen_install_progress_upload(int pos) {
display_loader(pos, -20, COLOR_BL_PROCESS, COLOR_WHITE, toi_icon_install,
sizeof(toi_icon_install), COLOR_BLACK);
display_loader(pos, false, -20, COLOR_BL_PROCESS, COLOR_WHITE,
toi_icon_install, sizeof(toi_icon_install), COLOR_BLACK);
}
// wipe UI
@ -274,14 +274,14 @@ void ui_screen_wipe_confirm(void) {
void ui_screen_wipe(void) {
display_bar(0, 0, DISPLAY_RESX, DISPLAY_RESY, COLOR_WHITE);
display_loader(0, -20, COLOR_BL_PROCESS, COLOR_WHITE, toi_icon_wipe,
display_loader(0, false, -20, COLOR_BL_PROCESS, COLOR_WHITE, toi_icon_wipe,
sizeof(toi_icon_wipe), COLOR_BLACK);
display_text_center(DISPLAY_RESX / 2, DISPLAY_RESY - 24, "Wiping device", -1,
FONT_NORMAL, COLOR_BLACK, COLOR_WHITE);
}
void ui_screen_wipe_progress(int pos, int len) {
display_loader(1000 * pos / len, -20, COLOR_BL_PROCESS, COLOR_WHITE,
display_loader(1000 * pos / len, false, -20, COLOR_BL_PROCESS, COLOR_WHITE,
toi_icon_wipe, sizeof(toi_icon_wipe), COLOR_BLACK);
}
@ -300,7 +300,7 @@ void ui_screen_done(int restart_seconds, secbool full_redraw) {
if (sectrue == full_redraw) {
display_bar(0, 0, DISPLAY_RESX, DISPLAY_RESY, COLOR_WHITE);
}
display_loader(1000, -20, COLOR_BL_DONE, COLOR_WHITE, toi_icon_done,
display_loader(1000, false, -20, COLOR_BL_DONE, COLOR_WHITE, toi_icon_done,
sizeof(toi_icon_done), COLOR_BLACK);
if (secfalse == full_redraw) {
display_bar(0, DISPLAY_RESY - 24 - 18, 240, 23, COLOR_WHITE);
@ -313,7 +313,7 @@ void ui_screen_done(int restart_seconds, secbool full_redraw) {
void ui_screen_fail(void) {
display_bar(0, 0, DISPLAY_RESX, DISPLAY_RESY, COLOR_WHITE);
display_loader(1000, -20, COLOR_BL_FAIL, COLOR_WHITE, toi_icon_fail,
display_loader(1000, false, -20, COLOR_BL_FAIL, COLOR_WHITE, toi_icon_fail,
sizeof(toi_icon_fail), COLOR_BLACK);
display_text_center(DISPLAY_RESX / 2, DISPLAY_RESY - 24,
"Failed! Please, reconnect.", -1, FONT_NORMAL,

View File

@ -1,6 +1,6 @@
#define VERSION_MAJOR 2
#define VERSION_MINOR 0
#define VERSION_PATCH 3
#define VERSION_PATCH 4
#define VERSION_BUILD 0
#define VERSION_UINT32 \
(VERSION_MAJOR | (VERSION_MINOR << 8) | (VERSION_PATCH << 16) | \

View File

@ -241,6 +241,4 @@ void display_refresh(void) {
HAL_GPIO_WritePin(OLED_DC_PORT, OLED_DC_PIN, GPIO_PIN_RESET); // set to CMD
}
const char *display_save(const char *prefix) {
return NULL;
}
const char *display_save(const char *prefix) { return NULL; }

View File

@ -498,6 +498,4 @@ void display_refresh(void) {
}
}
const char *display_save(const char *prefix) {
return NULL;
}
const char *display_save(const char *prefix) { return NULL; }

View File

@ -316,9 +316,9 @@ static void inflate_callback_loader(uint8_t byte, uint32_t pos,
#endif
void display_loader(uint16_t progress, int yoffset, uint16_t fgcolor,
uint16_t bgcolor, const uint8_t *icon, uint32_t iconlen,
uint16_t iconfgcolor) {
void display_loader(uint16_t progress, bool indeterminate, int yoffset,
uint16_t fgcolor, uint16_t bgcolor, const uint8_t *icon,
uint32_t iconlen, uint16_t iconfgcolor) {
#if TREZOR_MODEL == T
uint16_t colortable[16], iconcolortable[16];
set_color_table(colortable, fgcolor, bgcolor);
@ -362,6 +362,7 @@ void display_loader(uint16_t progress, int yoffset, uint16_t fgcolor,
}
// inside of circle - draw glyph
#define LOADER_ICON_CORNER_CUT 2
#define LOADER_INDETERMINATE_WIDTH 100
if (icon &&
mx + my > (((LOADER_ICON_SIZE / 2) + LOADER_ICON_CORNER_CUT) * 2) &&
mx >= img_loader_size - (LOADER_ICON_SIZE / 2) &&
@ -378,11 +379,22 @@ void display_loader(uint16_t progress, int yoffset, uint16_t fgcolor,
PIXELDATA(iconcolortable[c]);
} else {
uint8_t c;
if (indeterminate) {
uint16_t diff =
(progress > a) ? (progress - a) : (1000 + progress - a);
if (diff < LOADER_INDETERMINATE_WIDTH ||
diff > 1000 - LOADER_INDETERMINATE_WIDTH) {
c = (img_loader[my][mx] & 0x00F0) >> 4;
} else {
c = img_loader[my][mx] & 0x000F;
}
} else {
if (progress > a) {
c = (img_loader[my][mx] & 0x00F0) >> 4;
} else {
c = img_loader[my][mx] & 0x000F;
}
}
PIXELDATA(colortable[c]);
}
}

View File

@ -21,6 +21,7 @@
#define __DISPLAY_H__
#include <stdint.h>
#include <stdbool.h>
#if TREZOR_MODEL == T
@ -82,9 +83,9 @@ void display_avatar(int x, int y, const void *data, int datalen,
uint16_t fgcolor, uint16_t bgcolor);
void display_icon(int x, int y, int w, int h, const void *data, int datalen,
uint16_t fgcolor, uint16_t bgcolor);
void display_loader(uint16_t progress, int yoffset, uint16_t fgcolor,
uint16_t bgcolor, const uint8_t *icon, uint32_t iconlen,
uint16_t iconfgcolor);
void display_loader(uint16_t progress, bool indeterminate, int yoffset,
uint16_t fgcolor, uint16_t bgcolor, const uint8_t *icon,
uint32_t iconlen, uint16_t iconfgcolor);
#ifndef TREZOR_PRINT_DISABLE
void display_print_color(uint16_t fgcolor, uint16_t bgcolor);

View File

@ -197,8 +197,8 @@ STATIC mp_obj_t mod_trezorui_Display_icon(size_t n_args, const mp_obj_t *args) {
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_trezorui_Display_icon_obj, 6, 6,
mod_trezorui_Display_icon);
/// def loader(self, progress: int, yoffset: int, fgcolor: int, bgcolor: int,
/// icon: bytes = None, iconfgcolor: int = None) -> None:
/// def loader(self, progress: int, indeterminate: bool, yoffset: int, fgcolor:
/// int, bgcolor: int, icon: bytes = None, iconfgcolor: int = None) -> None:
/// '''
/// Renders a rotating loader graphic.
/// Progress determines its position (0-1000), fgcolor is used as foreground
@ -210,12 +210,13 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_trezorui_Display_icon_obj, 6, 6,
STATIC mp_obj_t mod_trezorui_Display_loader(size_t n_args,
const mp_obj_t *args) {
mp_int_t progress = mp_obj_get_int(args[1]);
mp_int_t yoffset = mp_obj_get_int(args[2]);
mp_int_t fgcolor = mp_obj_get_int(args[3]);
mp_int_t bgcolor = mp_obj_get_int(args[4]);
if (n_args > 5) { // icon provided
bool indeterminate = args[2] == mp_const_true;
mp_int_t yoffset = mp_obj_get_int(args[3]);
mp_int_t fgcolor = mp_obj_get_int(args[4]);
mp_int_t bgcolor = mp_obj_get_int(args[5]);
if (n_args > 6) { // icon provided
mp_buffer_info_t icon;
mp_get_buffer_raise(args[5], &icon, MP_BUFFER_READ);
mp_get_buffer_raise(args[6], &icon, MP_BUFFER_READ);
const uint8_t *data = icon.buf;
if (icon.len < 8 || memcmp(data, "TOIg", 4) != 0) {
mp_raise_ValueError("Invalid image format");
@ -230,20 +231,21 @@ STATIC mp_obj_t mod_trezorui_Display_loader(size_t n_args,
mp_raise_ValueError("Invalid size of data");
}
uint16_t iconfgcolor;
if (n_args > 6) { // icon color provided
iconfgcolor = mp_obj_get_int(args[6]);
if (n_args > 7) { // icon color provided
iconfgcolor = mp_obj_get_int(args[7]);
} else {
iconfgcolor = ~bgcolor; // invert
}
display_loader(progress, yoffset, fgcolor, bgcolor, icon.buf, icon.len,
iconfgcolor);
display_loader(progress, indeterminate, yoffset, fgcolor, bgcolor, icon.buf,
icon.len, iconfgcolor);
} else {
display_loader(progress, yoffset, fgcolor, bgcolor, NULL, 0, 0);
display_loader(progress, indeterminate, yoffset, fgcolor, bgcolor, NULL, 0,
0);
}
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_trezorui_Display_loader_obj, 5,
7, mod_trezorui_Display_loader);
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_trezorui_Display_loader_obj, 6,
8, mod_trezorui_Display_loader);
/// def print(self, text: str) -> None:
/// '''

View File

@ -1,6 +1,6 @@
#define VERSION_MAJOR 2
#define VERSION_MINOR 1
#define VERSION_PATCH 0
#define VERSION_PATCH 1
#define VERSION_BUILD 0
#define FIX_VERSION_MAJOR 2

View File

@ -1,3 +1,5 @@
// clang-format off
/*
* This file is part of the MicroPython project, http://micropython.org/
*

View File

@ -5,7 +5,6 @@ source emu.config 2>/dev/null
EXE=build/unix/micropython
PYOPT="${PYOPT:-1}"
MAIN="${MAIN:-${PWD}/src/main.py}"
BROWSER="${BROWSER:-chromium}"
HEAPSIZE="${HEAPSIZE:-50M}"
SOURCE_PY_DIR="${SOURCE_PY_DIR:-src}"
@ -33,14 +32,6 @@ case "$1" in
kill $UPY_PID
done
;;
"-p")
shift
../$EXE $ARGS $* $MAIN &
perf record -F 100 -p $! -g -- sleep 600
perf script > perf.trace
../vendor/flamegraph/stackcollapse-perf.pl perf.trace | ../vendor/flamegraph/flamegraph.pl > perf.svg
$BROWSER perf.svg
;;
*)
../$EXE $ARGS $* $MAIN
esac

View File

@ -24,5 +24,5 @@ def report_init(text):
def report():
p = int(1000 * _progress / _steps)
ui.display.loader(p, 18, ui.WHITE, ui.BG)
p = 1000 * _progress // _steps
ui.display.loader(p, False, 18, ui.WHITE, ui.BG)

View File

@ -549,7 +549,7 @@ COINS = [
coin_shortcut="FJC",
address_type=36,
address_type_p2sh=16,
maxfee_kb=10000000,
maxfee_kb=1000000000,
signed_message_header="FujiCoin Signed Message:\n",
xpub_magic=0x0488b21e,
xpub_magic_segwit_p2sh=0x049d7cb2,
@ -984,6 +984,26 @@ COINS = [
decred=False,
curve_name='secp256k1',
),
CoinInfo(
coin_name="Regtest",
coin_shortcut="REGTEST",
address_type=111,
address_type_p2sh=196,
maxfee_kb=10000000,
signed_message_header="Bitcoin Signed Message:\n",
xpub_magic=0x043587cf,
xpub_magic_segwit_p2sh=0x044a5262,
xpub_magic_segwit_native=0x045f1cf6,
bech32_prefix="bcrt",
cashaddr_prefix=None,
slip44=1,
segwit=True,
fork_id=None,
force_bip143=False,
bip115=False,
decred=False,
curve_name='secp256k1',
),
CoinInfo(
coin_name="SmartCash",
coin_shortcut="SMART",

View File

@ -44,6 +44,6 @@ def _start_progress():
def _render_progress(progress: int, total: int):
p = int(1000 * progress / total)
ui.display.loader(p, 18, ui.WHITE, ui.BG)
p = 1000 * progress // total
ui.display.loader(p, False, 18, ui.WHITE, ui.BG)
ui.display.refresh()

View File

@ -24,6 +24,13 @@ def write_uint16_le(w: bytearray, n: int) -> int:
return 2
def write_uint16_be(w: bytearray, n: int):
ensure(0 <= n <= 0xFFFF)
w.append((n >> 8) & 0xFF)
w.append(n & 0xFF)
return 2
def write_uint32_le(w: bytearray, n: int) -> int:
ensure(0 <= n <= 0xFFFFFFFF)
w.append(n & 0xFF)

View File

@ -159,7 +159,6 @@ tokens = [
(1, b"\x80\x04\x63\x05\xaa\xab\x08\xf6\x03\x3b\x56\xa3\x60\xc1\x84\x39\x11\x65\xdc\x2d", "BRLN", 18), # eth / Berlin Coin
(1, b"\xb2\x2c\x27\x86\xa5\x49\xb0\x08\x51\x7b\x67\x62\x5f\x52\x96\xe8\xfa\xf9\x58\x9e", "BRP", 18), # eth / Rental Processor Token
(1, b"\xf2\x6e\xf5\xe0\x54\x53\x84\xb7\xdc\xc0\xf2\x97\xf2\x67\x41\x89\x58\x68\x30\xdf", "BSDC", 18), # eth / BSDC
(1, b"\x50\x9a\x38\xb7\xa1\xcc\x0d\xcd\x83\xaa\x9d\x06\x21\x46\x63\xd9\xec\x7c\x7f\x4a", "BST", 18), # eth / BlocksquareToken
(1, b"\x02\x72\x58\x36\xeb\xf3\xec\xdb\x1c\xdf\x1c\x7b\x02\xfc\xbb\xfa\xa2\x73\x6a\xf8", "BTCA", 8), # eth / BitAir
(1, b"\x08\x86\x94\x9c\x1b\x8c\x41\x28\x60\xc4\x26\x4c\xeb\x80\x83\xd1\x36\x5e\x86\xcf", "BTCE", 8), # eth / EthereumBitcoin
(1, b"\x5a\xcd\x19\xb9\xc9\x1e\x59\x6b\x1f\x06\x2f\x18\xe3\xd0\x2d\xa7\xed\x8d\x1e\x50", "BTCL", 8), # eth / BTC Lite

View File

@ -42,7 +42,7 @@ async def require_confirm_tx_key(ctx, export_key=False):
return await require_confirm(ctx, content, ButtonRequestType.SignTx)
async def require_confirm_transaction(ctx, tsx_data, network_type):
async def require_confirm_transaction(ctx, state, tsx_data, network_type):
"""
Ask for confirmation from user.
"""
@ -70,10 +70,7 @@ async def require_confirm_transaction(ctx, tsx_data, network_type):
await _require_confirm_payment_id(ctx, tsx_data.payment_id)
await _require_confirm_fee(ctx, tsx_data.fee)
text = Text("Signing transaction", ui.ICON_SEND, icon_color=ui.BLUE)
text.normal("Signing...")
text.render()
await transaction_step(state, 0)
async def _require_confirm_output(ctx, dst, network_type, payment_id):
@ -119,46 +116,66 @@ async def _require_confirm_fee(ctx, fee):
await require_hold_to_confirm(ctx, content, ButtonRequestType.ConfirmOutput)
@ui.layout
async def transaction_step(ctx, step, sub_step=None, sub_step_total=None):
@ui.layout_no_slide
async def transaction_step(state, step, sub_step=None):
info = []
if step == 100:
info = ["Processing inputs", "%d/%d" % (sub_step + 1, sub_step_total)]
if step == 0:
info = ["Signing..."]
elif step == 100:
info = ["Processing inputs", "%d/%d" % (sub_step + 1, state.input_count)]
elif step == 200:
info = ["Sorting"]
info = ["Sorting..."]
elif step == 300:
info = [
"Processing inputs",
"phase 2",
"%d/%d" % (sub_step + 1, sub_step_total),
]
info = ["Hashing inputs", "%d/%d" % (sub_step + 1, state.input_count)]
elif step == 350:
info = ["Processing..."]
elif step == 400:
info = ["Processing outputs", "%d/%d" % (sub_step + 1, sub_step_total)]
info = ["Processing outputs", "%d/%d" % (sub_step + 1, state.output_count)]
elif step == 500:
info = ["Postprocessing..."]
elif step == 600:
info = ["Signing inputs", "%d/%d" % (sub_step + 1, sub_step_total)]
info = ["Signing inputs", "%d/%d" % (sub_step + 1, state.input_count)]
else:
info = ["Processing..."]
state.progress_cur += 1
ui.display.clear()
text = Text("Signing transaction", ui.ICON_SEND, icon_color=ui.BLUE)
text.normal(*info)
text.render()
p = 1000 * state.progress_cur // state.progress_total
ui.display.loader(p, False, -4, ui.WHITE, ui.BG)
ui.display.text_center(ui.WIDTH // 2, 210, info[0], ui.NORMAL, ui.FG, ui.BG)
if len(info) > 1:
ui.display.text_center(ui.WIDTH // 2, 235, info[1], ui.NORMAL, ui.FG, ui.BG)
ui.display.refresh()
@ui.layout
@ui.layout_no_slide
async def keyimage_sync_step(ctx, current, total_num):
if current is None:
return
ui.display.clear()
text = Text("Syncing", ui.ICON_SEND, icon_color=ui.BLUE)
text.normal("%d/%d" % (current + 1, total_num))
text.render()
p = (1000 * (current + 1) // total_num) if total_num > 0 else 0
ui.display.loader(p, False, 18, ui.WHITE, ui.BG)
ui.display.refresh()
@ui.layout
@ui.layout_no_slide
async def live_refresh_step(ctx, current):
if current is None:
return
ui.display.clear()
text = Text("Refreshing", ui.ICON_SEND, icon_color=ui.BLUE)
text.normal("%d" % current)
text.render()
step = 8
p = (1000 * current // step) % 1000
ui.display.loader(p, True, 18, ui.WHITE, ui.BG)
ui.display.text_center(ui.WIDTH // 2, 145, "%d" % current, ui.NORMAL, ui.FG, ui.BG)
ui.display.refresh()

View File

@ -37,7 +37,7 @@ async def live_refresh(ctx, msg: MoneroLiveRefreshStartRequest, keychain):
class LiveRefreshState:
def __init__(self):
self.current_output = -1
self.current_output = 0
self.creds = None

View File

@ -68,6 +68,9 @@ class State:
self.input_count = 0
self.output_count = 0
self.progress_total = 0
self.progress_cur = 0
self.output_change = None
self.fee = 0

View File

@ -36,16 +36,19 @@ async def init_transaction(
state.mem_trace(1)
state.input_count = tsx_data.num_inputs
state.output_count = len(tsx_data.outputs)
state.progress_total = 4 + 3 * state.input_count + state.output_count
state.progress_cur = 0
# Ask for confirmation
await confirms.require_confirm_transaction(
state.ctx, tsx_data, state.creds.network_type
state.ctx, state, tsx_data, state.creds.network_type
)
gc.collect()
state.mem_trace(3)
# Basic transaction parameters
state.input_count = tsx_data.num_inputs
state.output_count = len(tsx_data.outputs)
state.output_change = tsx_data.change_dts
state.mixin = tsx_data.mixin
state.fee = tsx_data.fee

View File

@ -32,9 +32,7 @@ async def set_input(state: State, src_entr: MoneroTransactionSourceEntry):
state.current_input_index += 1
await confirms.transaction_step(
state.ctx, state.STEP_INP, state.current_input_index, state.input_count
)
await confirms.transaction_step(state, state.STEP_INP, state.current_input_index)
if state.current_input_index >= state.input_count:
raise ValueError("Too many inputs")

View File

@ -21,7 +21,7 @@ async def tsx_inputs_permutation(state: State, permutation: list):
MoneroTransactionInputsPermutationAck,
)
await transaction_step(state.ctx, state.STEP_PERM)
await transaction_step(state, state.STEP_PERM)
"""
Set permutation on the inputs - sorted by key image on host.

View File

@ -33,7 +33,7 @@ async def input_vini(
)
await confirms.transaction_step(
state.ctx, state.STEP_VINI, state.current_input_index + 1, state.input_count
state, state.STEP_VINI, state.current_input_index + 1
)
if state.current_input_index >= state.input_count:
raise ValueError("Too many inputs")

View File

@ -12,7 +12,7 @@ from apps.monero.xmr import crypto
async def all_inputs_set(state: State):
state.mem_trace(0)
await confirms.transaction_step(state.ctx, state.STEP_ALL_IN)
await confirms.transaction_step(state, state.STEP_ALL_IN)
from trezor.messages.MoneroTransactionAllInputsSetAck import (
MoneroTransactionAllInputsSetAck,

View File

@ -23,10 +23,7 @@ async def set_output(
# Progress update only for master message (skip for offloaded BP msg)
if not is_offloaded_bp:
await confirms.transaction_step(
state.ctx,
state.STEP_OUT,
state.current_output_index + 1,
state.output_count,
state, state.STEP_OUT, state.current_output_index + 1
)
state.mem_trace(1, True)

View File

@ -18,7 +18,7 @@ from apps.monero.xmr import crypto
async def all_outputs_set(state: State):
state.mem_trace(0)
await confirms.transaction_step(state.ctx, state.STEP_ALL_OUT)
await confirms.transaction_step(state, state.STEP_ALL_OUT)
state.mem_trace(1)
_validate(state)

View File

@ -48,7 +48,7 @@ async def sign_input(
:return: Generated signature MGs[i]
"""
await confirms.transaction_step(
state.ctx, state.STEP_SIGN, state.current_input_index + 1, state.input_count
state, state.STEP_SIGN, state.current_input_index + 1
)
state.current_input_index += 1

View File

@ -3,6 +3,7 @@ from micropython import const
from trezor.crypto import base58
from apps.common import HARDENED
from apps.common.writers import write_uint8
TEZOS_AMOUNT_DIVISIBILITY = const(6)
TEZOS_ED25519_ADDRESS_PREFIX = "tz1"
@ -21,6 +22,8 @@ TEZOS_PREFIX_BYTES = {
"edsig": [9, 245, 205, 134, 18],
# operation hash
"o": [5, 116],
# protocol hash
"P": [2, 170],
}
@ -42,13 +45,29 @@ def validate_full_path(path: list) -> bool:
"""
Validates derivation path to equal 44'/1729'/a',
where `a` is an account index from 0 to 1 000 000.
Additional component added to allow ledger migration
44'/1729'/0'/b' where `b` is an account index from 0 to 1 000 000
"""
if len(path) != 3:
length = len(path)
if length < 3 or length > 4:
return False
if path[0] != 44 | HARDENED:
return False
if path[1] != 1729 | HARDENED:
return False
if length == 3:
if path[2] < HARDENED or path[2] > 1000000 | HARDENED:
return False
if length == 4:
if path[2] != 0 | HARDENED:
return False
if path[3] < HARDENED or path[3] > 1000000 | HARDENED:
return False
return True
def write_bool(w: bytearray, boolean: bool):
if boolean:
write_uint8(w, 255)
else:
write_uint8(w, 0)

View File

@ -1,5 +1,10 @@
from trezor import ui
from trezor.messages import ButtonRequestType
from micropython import const
from trezor import ui, wire
from trezor.messages import ButtonRequestType, MessageType
from trezor.messages.ButtonRequest import ButtonRequest
from trezor.ui.confirm import CANCELLED, ConfirmDialog
from trezor.ui.scroll import Scrollpage, animate_swipe, paginate
from trezor.ui.text import Text
from trezor.utils import chunks, format_amount
@ -66,6 +71,45 @@ def split_address(address):
return chunks(address, 18)
def split_proposal(proposal):
return chunks(proposal, 17)
def format_tezos_amount(value):
formatted_value = format_amount(value, TEZOS_AMOUNT_DIVISIBILITY)
return formatted_value + " XTZ"
async def require_confirm_ballot(ctx, proposal, ballot):
text = Text("Submit ballot", ui.ICON_SEND, icon_color=ui.PURPLE)
text.bold("Ballot: {}".format(ballot))
text.bold("Proposal:")
text.mono(*split_proposal(proposal))
await require_confirm(ctx, text, ButtonRequestType.SignTx)
# use, when there are more then one proposals in one operation
async def require_confirm_proposals(ctx, proposals):
await ctx.call(ButtonRequest(code=ButtonRequestType.SignTx), MessageType.ButtonAck)
first_page = const(0)
pages = proposals
title = "Submit proposals" if len(proposals) > 1 else "Submit proposal"
paginator = paginate(show_proposal_page, len(pages), first_page, pages, title)
return await ctx.wait(paginator)
@ui.layout
async def show_proposal_page(page: int, page_count: int, pages: list, title: str):
text = Text(title, ui.ICON_SEND, icon_color=ui.PURPLE)
text.bold("Proposal {}: ".format(page + 1))
text.mono(*split_proposal(pages[page]))
content = Scrollpage(text, page, page_count)
if page + 1 >= page_count:
confirm = await ConfirmDialog(content)
if confirm == CANCELLED:
raise wire.ActionCancelled("Cancelled")
else:
content.render()
await animate_swipe()

View File

@ -1,13 +1,17 @@
from micropython import const
from trezor import wire
from trezor.crypto import hashlib
from trezor.crypto.curve import ed25519
from trezor.messages import TezosContractType
from trezor.messages import TezosBallotType, TezosContractType
from trezor.messages.TezosSignedTx import TezosSignedTx
from apps.common import paths
from apps.common.writers import write_bytes, write_uint8
from apps.common.writers import write_bytes, write_uint8, write_uint32_be
from apps.tezos import CURVE, helpers, layout
PROPOSAL_LENGTH = const(32)
async def sign_tx(ctx, msg, keychain):
await paths.validate_path(
@ -52,6 +56,15 @@ async def sign_tx(ctx, msg, keychain):
ctx, source, msg.delegation.fee
)
elif msg.proposal is not None:
proposed_protocols = [_get_protocol_hash(p) for p in msg.proposal.proposals]
await layout.require_confirm_proposals(ctx, proposed_protocols)
elif msg.ballot is not None:
proposed_protocol = _get_protocol_hash(msg.ballot.proposal)
submitted_ballot = _get_ballot(msg.ballot.ballot)
await layout.require_confirm_ballot(ctx, proposed_protocol, submitted_ballot)
else:
raise wire.DataError("Invalid operation")
@ -101,11 +114,24 @@ def _get_address_from_contract(address):
raise wire.DataError("Invalid contract type")
def _get_protocol_hash(proposal):
return helpers.base58_encode_check(proposal, prefix="P")
def _get_ballot(ballot):
if ballot == TezosBallotType.Yay:
return "yay"
elif ballot == TezosBallotType.Nay:
return "nay"
elif ballot == TezosBallotType.Pass:
return "pass"
def _get_operation_bytes(w: bytearray, msg):
write_bytes(w, msg.branch)
# when the account sends first operation in lifetime,
# we need to reveal its publickey
# we need to reveal its public key
if msg.reveal is not None:
_encode_common(w, msg.reveal, "reveal")
write_bytes(w, msg.reveal.public_key)
@ -121,14 +147,18 @@ def _get_operation_bytes(w: bytearray, msg):
_encode_common(w, msg.origination, "origination")
write_bytes(w, msg.origination.manager_pubkey)
_encode_zarith(w, msg.origination.balance)
_encode_bool(w, msg.origination.spendable)
_encode_bool(w, msg.origination.delegatable)
helpers.write_bool(w, msg.origination.spendable)
helpers.write_bool(w, msg.origination.delegatable)
_encode_data_with_bool_prefix(w, msg.origination.delegate)
_encode_data_with_bool_prefix(w, msg.origination.script)
# delegation operation
elif msg.delegation is not None:
_encode_common(w, msg.delegation, "delegation")
_encode_data_with_bool_prefix(w, msg.delegation.delegate)
elif msg.proposal is not None:
_encode_proposal(w, msg.proposal)
elif msg.ballot is not None:
_encode_ballot(w, msg.ballot)
def _encode_common(w: bytearray, operation, str_operation):
@ -146,19 +176,12 @@ def _encode_contract_id(w: bytearray, contract_id):
write_bytes(w, contract_id.hash)
def _encode_bool(w: bytearray, boolean):
if boolean:
write_uint8(w, 255)
else:
write_uint8(w, 0)
def _encode_data_with_bool_prefix(w: bytearray, data):
if data:
_encode_bool(w, True)
helpers.write_bool(w, True)
write_bytes(w, data)
else:
_encode_bool(w, False)
helpers.write_bool(w, False)
def _encode_zarith(w: bytearray, num):
@ -171,3 +194,24 @@ def _encode_zarith(w: bytearray, num):
break
write_uint8(w, 128 | byte)
def _encode_proposal(w: bytearray, proposal):
proposal_tag = 5
write_uint8(w, proposal_tag)
write_bytes(w, proposal.source)
write_uint32_be(w, proposal.period)
write_uint32_be(w, len(proposal.proposals) * PROPOSAL_LENGTH)
for proposal_hash in proposal.proposals:
write_bytes(w, proposal_hash)
def _encode_ballot(w: bytearray, ballot):
ballot_tag = 6
write_uint8(w, ballot_tag)
write_bytes(w, ballot.source)
write_uint32_be(w, ballot.period)
write_bytes(w, ballot.proposal)
write_uint8(w, ballot.ballot)

View File

@ -204,7 +204,7 @@ def validate_full_path(
See docs/coins for what paths are allowed. Please note that this is not
a comprehensive check, some nuances are omitted for simplification.
"""
if len(path) != 5:
if len(path) not in (4, 5, 6):
return False
if not validate_purpose(path[0], coin):
@ -214,21 +214,29 @@ def validate_full_path(
):
return False
if path[1] != coin.slip44 | HARDENED:
if path[1] > 20 and path[1] != coin.slip44 | HARDENED:
return False
if path[2] < HARDENED or path[2] > 20 | HARDENED:
if (path[2] > 20 and path[2] < HARDENED) or path[2] > 20 | HARDENED:
return False
if path[3] not in [0, 1]:
if path[3] not in (0, 1, 0 | HARDENED, 1 | HARDENED, 2 | HARDENED):
return False
if path[4] > 1000000:
if len(path) > 4 and path[4] > 1000000:
return False
if len(path) > 5 and path[5] > 1000000:
return False
return True
def validate_purpose(purpose: int, coin: CoinInfo) -> bool:
if purpose not in (44 | HARDENED, 48 | HARDENED, 49 | HARDENED, 84 | HARDENED):
if purpose not in (
44 | HARDENED,
45 | HARDENED,
48 | HARDENED,
49 | HARDENED,
84 | HARDENED,
):
return False
if not coin.segwit and purpose not in (44 | HARDENED, 48 | HARDENED):
if not coin.segwit and purpose not in (44 | HARDENED, 45 | HARDENED, 48 | HARDENED):
return False
return True
@ -239,21 +247,23 @@ def validate_purpose_against_script_type(
"""
Validates purpose against provided input's script type:
- 44 for spending address (script_type == SPENDADDRESS)
- 48 for multisig (script_type == SPENDMULTISIG)
- 49 for p2sh-segwit spend (script_type == SPENDP2SHWITNESS)
- 84 for native segwit spend (script_type == SPENDWITNESS)
- 45, 48 for multisig (script_type == SPENDMULTISIG)
- 49 for p2wsh-nested-in-p2sh spend (script_type == SPENDP2SHWITNESS)
- 84 for p2wsh native segwit spend (script_type == SPENDWITNESS)
"""
if purpose == 44 | HARDENED and script_type != InputScriptType.SPENDADDRESS:
return False
if purpose == 48 | HARDENED and script_type != InputScriptType.SPENDMULTISIG:
if purpose == 45 | HARDENED and script_type != InputScriptType.SPENDMULTISIG:
return False
if ( # p2wsh-nested-in-p2sh
purpose == 49 | HARDENED and script_type != InputScriptType.SPENDP2SHWITNESS
if purpose == 48 | HARDENED and script_type not in (
InputScriptType.SPENDMULTISIG,
InputScriptType.SPENDP2SHWITNESS,
InputScriptType.SPENDWITNESS,
):
return False
if ( # p2wsh
purpose == 84 | HARDENED and script_type != InputScriptType.SPENDWITNESS
):
if purpose == 49 | HARDENED and script_type != InputScriptType.SPENDP2SHWITNESS:
return False
if purpose == 84 | HARDENED and script_type != InputScriptType.SPENDWITNESS:
return False
return True

View File

@ -24,5 +24,5 @@ def report_init():
def report():
p = int(1000 * _progress / _steps)
ui.display.loader(p, 18, ui.WHITE, ui.BG)
p = 1000 * _progress // _steps
ui.display.loader(p, False, 18, ui.WHITE, ui.BG)

View File

@ -29,6 +29,8 @@ class MoneroTransactionData(p.MessageType):
rsig_data: MoneroTransactionRsigData = None,
integrated_indices: List[int] = None,
client_version: int = None,
hard_fork: int = None,
monero_version: bytes = None,
) -> None:
self.version = version
self.payment_id = payment_id
@ -43,6 +45,8 @@ class MoneroTransactionData(p.MessageType):
self.rsig_data = rsig_data
self.integrated_indices = integrated_indices if integrated_indices is not None else []
self.client_version = client_version
self.hard_fork = hard_fork
self.monero_version = monero_version
@classmethod
def get_fields(cls):
@ -60,4 +64,6 @@ class MoneroTransactionData(p.MessageType):
11: ('rsig_data', MoneroTransactionRsigData, 0),
12: ('integrated_indices', p.UVarintType, p.FLAG_REPEATED),
13: ('client_version', p.UVarintType, 0),
14: ('hard_fork', p.UVarintType, 0),
15: ('monero_version', p.BytesType, 0),
}

View File

@ -0,0 +1,27 @@
# Automatically generated by pb2py
# fmt: off
import protobuf as p
class TezosBallotOp(p.MessageType):
def __init__(
self,
source: bytes = None,
period: int = None,
proposal: bytes = None,
ballot: int = None,
) -> None:
self.source = source
self.period = period
self.proposal = proposal
self.ballot = ballot
@classmethod
def get_fields(cls):
return {
1: ('source', p.BytesType, 0),
2: ('period', p.UVarintType, 0),
3: ('proposal', p.BytesType, 0),
4: ('ballot', p.UVarintType, 0),
}

View File

@ -0,0 +1,5 @@
# Automatically generated by pb2py
# fmt: off
Yay = 0
Nay = 1
Pass = 2

View File

@ -0,0 +1,30 @@
# Automatically generated by pb2py
# fmt: off
import protobuf as p
if __debug__:
try:
from typing import List
except ImportError:
List = None # type: ignore
class TezosProposalOp(p.MessageType):
def __init__(
self,
source: bytes = None,
period: int = None,
proposals: List[bytes] = None,
) -> None:
self.source = source
self.period = period
self.proposals = proposals if proposals is not None else []
@classmethod
def get_fields(cls):
return {
1: ('source', p.BytesType, 0),
2: ('period', p.UVarintType, 0),
4: ('proposals', p.BytesType, p.FLAG_REPEATED),
}

View File

@ -2,8 +2,10 @@
# fmt: off
import protobuf as p
from .TezosBallotOp import TezosBallotOp
from .TezosDelegationOp import TezosDelegationOp
from .TezosOriginationOp import TezosOriginationOp
from .TezosProposalOp import TezosProposalOp
from .TezosRevealOp import TezosRevealOp
from .TezosTransactionOp import TezosTransactionOp
@ -25,6 +27,8 @@ class TezosSignTx(p.MessageType):
transaction: TezosTransactionOp = None,
origination: TezosOriginationOp = None,
delegation: TezosDelegationOp = None,
proposal: TezosProposalOp = None,
ballot: TezosBallotOp = None,
) -> None:
self.address_n = address_n if address_n is not None else []
self.branch = branch
@ -32,6 +36,8 @@ class TezosSignTx(p.MessageType):
self.transaction = transaction
self.origination = origination
self.delegation = delegation
self.proposal = proposal
self.ballot = ballot
@classmethod
def get_fields(cls):
@ -42,4 +48,6 @@ class TezosSignTx(p.MessageType):
4: ('transaction', TezosTransactionOp, 0),
5: ('origination', TezosOriginationOp, 0),
6: ('delegation', TezosDelegationOp, 0),
7: ('proposal', TezosProposalOp, 0),
8: ('ballot', TezosBallotOp, 0),
}

View File

@ -31,6 +31,6 @@ def get_type(wire_type):
for msg_name in dir(MessageType):
# Modules contain internal variables that may cause exception here.
# No Message begins with underscore so it's safe to skip those.
if (msg_name[0] == '_'):
if msg_name[0] == "_":
continue
type_to_name[getattr(MessageType, msg_name)] = msg_name

View File

@ -18,7 +18,7 @@ def show_pin_timeout(seconds: int, progress: int, message: str) -> bool:
ui.display.text_center(
ui.WIDTH // 2, 37, message, ui.BOLD, ui.FG, ui.BG, ui.WIDTH
)
ui.display.loader(progress, 0, ui.FG, ui.BG)
ui.display.loader(progress, False, 0, ui.FG, ui.BG)
if seconds == 0:
ui.display.text_center(
ui.WIDTH // 2, ui.HEIGHT - 22, "Done", ui.BOLD, ui.FG, ui.BG, ui.WIDTH

View File

@ -47,12 +47,15 @@ class Loader(ui.Widget):
else:
s = self.normal_style
if s["icon"] is None:
ui.display.loader(r, -24, s["fg-color"], s["bg-color"])
ui.display.loader(r, False, -24, s["fg-color"], s["bg-color"])
elif s["icon-fg-color"] is None:
ui.display.loader(r, -24, s["fg-color"], s["bg-color"], res.load(s["icon"]))
ui.display.loader(
r, False, -24, s["fg-color"], s["bg-color"], res.load(s["icon"])
)
else:
ui.display.loader(
r,
False,
-24,
s["fg-color"],
s["bg-color"],

View File

@ -21,9 +21,9 @@ async def change_page(page, page_count):
else:
s = await swipe
if s == SWIPE_UP:
return page + 1 # scroll down
return min(page + 1, page_count - 1) # scroll down
elif s == SWIPE_DOWN:
return page - 1 # scroll up
return max(page - 1, 0) # scroll up
async def paginate(render_page, page_count, page=0, *args):

View File

@ -62,7 +62,6 @@ bus = io.USB(
product="TREZOR",
interface="TREZOR Interface",
serial_number=get_device_id(),
usb21_landing=False,
)
bus.add(iface_wire)
if __debug__:

View File

@ -46,10 +46,11 @@ class TestTezosAddress(unittest.TestCase):
[44 | HARDENED],
[44 | HARDENED, 1729 | HARDENED],
[44 | HARDENED, 1729 | HARDENED, 0],
[44 | HARDENED, 1729 | HARDENED, 0 | HARDENED, 0 | HARDENED],
[44 | HARDENED, 1729 | HARDENED, 0 | HARDENED, 0],
[44 | HARDENED, 1729 | HARDENED, 0 | HARDENED, 0 | HARDENED, 0 | HARDENED],
[44 | HARDENED, 1729 | HARDENED, 0 | HARDENED, 1, 0],
[44 | HARDENED, 1729 | HARDENED, 0 | HARDENED, 0, 0],
[44 | HARDENED, 1729 | HARDENED, 1 | HARDENED, 1 | HARDENED],
[44 | HARDENED, 1729 | HARDENED, 9999000 | HARDENED],
[44 | HARDENED, 60 | HARDENED, 0 | HARDENED, 0, 0],
[1 | HARDENED, 1 | HARDENED, 1 | HARDENED],
@ -58,6 +59,9 @@ class TestTezosAddress(unittest.TestCase):
[44 | HARDENED, 1729 | HARDENED, 0 | HARDENED],
[44 | HARDENED, 1729 | HARDENED, 3 | HARDENED],
[44 | HARDENED, 1729 | HARDENED, 9 | HARDENED],
[44 | HARDENED, 1729 | HARDENED, 0 | HARDENED, 0 | HARDENED],
[44 | HARDENED, 1729 | HARDENED, 0 | HARDENED, 3 | HARDENED],
[44 | HARDENED, 1729 | HARDENED, 0 | HARDENED, 9 | HARDENED],
]
for path in incorrect_paths:

View File

@ -4,9 +4,8 @@ from common import *
from trezor.messages import TezosContractType
from trezor.messages.TezosContractID import TezosContractID
from apps.tezos.helpers import base58_decode_check, base58_encode_check
from apps.tezos.helpers import base58_decode_check, base58_encode_check, write_bool
from apps.tezos.sign_tx import (
_encode_bool,
_encode_contract_id,
_encode_data_with_bool_prefix,
_encode_zarith,
@ -35,11 +34,11 @@ class TestTezosEncoding(unittest.TestCase):
def test_tezos_encode_bool(self):
w = bytearray()
_encode_bool(w, True)
write_bool(w, True)
self.assertEqual(bytes(w), bytes([255]))
w = bytearray()
_encode_bool(w, False)
write_bool(w, False)
self.assertEqual(bytes(w), bytes([0]))
def test_tezos_encode_contract_id(self):

View File

@ -130,7 +130,7 @@ class TestAddress(unittest.TestCase):
([49 | HARDENED], InputScriptType.SPENDP2SHWITNESS), # invalid length
([49 | HARDENED, 0 | HARDENED, 0 | HARDENED, 0 | HARDENED, 0 | HARDENED], InputScriptType.SPENDP2SHWITNESS), # too many HARDENED
([49 | HARDENED, 0 | HARDENED], InputScriptType.SPENDP2SHWITNESS), # invalid length
([49 | HARDENED, 0 | HARDENED, 0 | HARDENED, 0, 0, 0], InputScriptType.SPENDP2SHWITNESS), # invalid length
([49 | HARDENED, 0 | HARDENED, 0 | HARDENED, 0, 0, 0, 0], InputScriptType.SPENDP2SHWITNESS), # invalid length
([49 | HARDENED, 123 | HARDENED, 0 | HARDENED, 0, 0, 0], InputScriptType.SPENDP2SHWITNESS), # invalid slip44
([49 | HARDENED, 0 | HARDENED, 1000 | HARDENED, 0, 0], InputScriptType.SPENDP2SHWITNESS), # account too high
([49 | HARDENED, 0 | HARDENED, 1 | HARDENED, 2, 0], InputScriptType.SPENDP2SHWITNESS), # invalid y
@ -172,7 +172,7 @@ class TestAddress(unittest.TestCase):
([49 | HARDENED, 145 | HARDENED, 0 | HARDENED, 0, 0], InputScriptType.SPENDP2SHWITNESS), # bch is not segwit coin so 49' is not allowed
([84 | HARDENED, 145 | HARDENED, 1 | HARDENED, 0, 1], InputScriptType.SPENDWITNESS), # and neither is 84'
([44 | HARDENED, 145 | HARDENED], InputScriptType.SPENDADDRESS), # invalid length
([44 | HARDENED, 145 | HARDENED, 0 | HARDENED, 0, 0, 0], InputScriptType.SPENDADDRESS), # invalid length
([44 | HARDENED, 145 | HARDENED, 0 | HARDENED, 0, 0, 0, 0], InputScriptType.SPENDADDRESS), # invalid length
([44 | HARDENED, 123 | HARDENED, 0 | HARDENED, 0, 0, 0], InputScriptType.SPENDADDRESS), # invalid slip44
([44 | HARDENED, 145 | HARDENED, 1000 | HARDENED, 0, 0], InputScriptType.SPENDADDRESS), # account too high
([44 | HARDENED, 145 | HARDENED, 1 | HARDENED, 2, 0], InputScriptType.SPENDADDRESS), # invalid y

View File

@ -39,7 +39,7 @@ class TestDisplay(unittest.TestCase):
display.qrcode(0, 0, 'Test', 4)
def test_loader(self):
display.loader(333, 0, 0xFFFF, 0x0000)
display.loader(333, False, 0, 0xFFFF, 0x0000)
def test_orientation(self):
for o in [0, 90, 180, 270]:

View File

@ -1,5 +1,6 @@
#!/bin/bash
set -e
cd $(dirname $0)
rm -f ../src/trezor/messages/[A-Z]*.py
../vendor/trezor-common/protob/pb2py \

View File

@ -1,21 +0,0 @@
#!/bin/sh
# libsodium-dev replacement
#
# The purpose of this file is to install libsodium in
# the Travis CI environment. Outside this environment,
# you would probably not want to install it like this.
set -e
export LIBSODIUM_VER="1.0.16"
# check if libsodium is already installed
if [ ! -d "$HOME/libsodium/lib" ]; then
wget "https://github.com/jedisct1/libsodium/releases/download/${LIBSODIUM_VER}/libsodium-${LIBSODIUM_VER}.tar.gz"
tar xvfz "libsodium-${LIBSODIUM_VER}.tar.gz"
cd "libsodium-${LIBSODIUM_VER}"
./configure --prefix=$HOME/libsodium
make
make install
else
echo 'Using cached directory.'
fi

File diff suppressed because it is too large Load Diff

View File

@ -1,257 +0,0 @@
#!/usr/bin/perl -w
#
# stackcolllapse-perf.pl collapse perf samples into single lines.
#
# Parses a list of multiline stacks generated by "perf script", and
# outputs a semicolon separated stack followed by a space and a count.
# If memory addresses (+0xd) are present, they are stripped, and resulting
# identical stacks are colased with their counts summed.
#
# USAGE: ./stackcollapse-perf.pl [options] infile > outfile
#
# Run "./stackcollapse-perf.pl -h" to list options.
#
# Example input:
#
# swapper 0 [000] 158665.570607: cpu-clock:
# ffffffff8103ce3b native_safe_halt ([kernel.kallsyms])
# ffffffff8101c6a3 default_idle ([kernel.kallsyms])
# ffffffff81013236 cpu_idle ([kernel.kallsyms])
# ffffffff815bf03e rest_init ([kernel.kallsyms])
# ffffffff81aebbfe start_kernel ([kernel.kallsyms].init.text)
# [...]
#
# Example output:
#
# swapper;start_kernel;rest_init;cpu_idle;default_idle;native_safe_halt 1
#
# Input may be created and processed using:
#
# perf record -a -g -F 997 sleep 60
# perf script | ./stackcollapse-perf.pl > out.stacks-folded
#
# The output of "perf script" should include stack traces. If these are missing
# for you, try manually selecting the perf script output; eg:
#
# perf script -f comm,pid,tid,cpu,time,event,ip,sym,dso,trace | ...
#
# This is also required for the --pid or --tid options, so that the output has
# both the PID and TID.
#
# Copyright 2012 Joyent, Inc. All rights reserved.
# Copyright 2012 Brendan Gregg. All rights reserved.
#
# CDDL HEADER START
#
# The contents of this file are subject to the terms of the
# Common Development and Distribution License (the "License").
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at docs/cddl1.txt or
# http://opensource.org/licenses/CDDL-1.0.
# See the License for the specific language governing permissions
# and limitations under the License.
#
# When distributing Covered Code, include this CDDL HEADER in each
# file and include the License file at docs/cddl1.txt.
# If applicable, add the following below this CDDL HEADER, with the
# fields enclosed by brackets "[]" replaced with your own identifying
# information: Portions Copyright [yyyy] [name of copyright owner]
#
# CDDL HEADER END
#
# 02-Mar-2012 Brendan Gregg Created this.
# 02-Jul-2014 " " Added process name to stacks.
use strict;
use Getopt::Long;
my %collapsed;
sub remember_stack {
my ($stack, $count) = @_;
$collapsed{$stack} += $count;
}
my $annotate_kernel = 0; # put an annotation on kernel function
my $include_pname = 1; # include process names in stacks
my $include_pid = 0; # include process ID with process name
my $include_tid = 0; # include process & thread ID with process name
my $tidy_java = 1; # condense Java signatures
my $tidy_generic = 1; # clean up function names a little
my $target_pname; # target process name from perf invocation
my $show_inline = 0;
my $show_context = 0;
GetOptions('inline' => \$show_inline,
'context' => \$show_context,
'pid' => \$include_pid,
'kernel' => \$annotate_kernel,
'tid' => \$include_tid)
or die <<USAGE_END;
USAGE: $0 [options] infile > outfile\n
--pid # include PID with process names [1]
--tid # include TID and PID with process names [1]
--inline # un-inline using addr2line
--kernel # annotate kernel functions with a _[k]
--context # include source context from addr2line\n
[1] perf script must emit both PID and TIDs for these to work; eg:
perf script -f comm,pid,tid,cpu,time,event,ip,sym,dso,trace
USAGE_END
# for the --inline option
sub inline {
my ($pc, $mod) = @_;
# capture addr2line output
my $a2l_output = `addr2line -a $pc -e $mod -i -f -s -C`;
# remove first line
$a2l_output =~ s/^(.*\n){1}//;
my @fullfunc;
my $one_item = "";
for (split /^/, $a2l_output) {
chomp $_;
# remove discriminator info if exists
$_ =~ s/ \(discriminator \S+\)//;
if ($one_item eq "") {
$one_item = $_;
} else {
if ($show_context == 1) {
unshift @fullfunc, $one_item . ":$_";
} else {
unshift @fullfunc, $one_item;
}
$one_item = "";
}
}
return join(";", @fullfunc);
}
my @stack;
my $pname;
#
# Main loop
#
while (defined($_ = <>)) {
# find the name of the process launched by perf, by stepping backwards
# over the args to find the first non-option (no dash):
if (/^# cmdline/) {
my @args = split ' ', $_;
foreach my $arg (reverse @args) {
if ($arg !~ /^-/) {
$target_pname = $arg;
$target_pname =~ s:.*/::; # strip pathname
last;
}
}
}
# skip remaining comments
next if m/^#/;
chomp;
# end of stack. save cached data.
if (m/^$/) {
if ($include_pname) {
if (defined $pname) {
unshift @stack, $pname;
} else {
unshift @stack, "";
}
}
remember_stack(join(";", @stack), 1) if @stack;
undef @stack;
undef $pname;
next;
}
# event record start
if (/^(\S+\s*?\S*?)\s+(\d+)\s/) {
# default "perf script" output has TID but not PID
# eg, "java 25607 4794564.109216: cycles:"
# eg, "java 12688 [002] 6544038.708352: cpu-clock:"
# eg, "V8 WorkerThread 25607 4794564.109216: cycles:"
# other combinations possible
if ($include_tid) {
$pname = "$1-?/$2";
} elsif ($include_pid) {
$pname = "$1-?";
} else {
$pname = $1;
}
$pname =~ tr/ /_/;
} elsif (/^(\S+\s*?\S*?)\s+(\d+)\/(\d+)/) {
# eg, "java 24636/25607 [000] 4794564.109216: cycles:"
# eg, "java 12688/12764 6544038.708352: cpu-clock:"
# eg, "V8 WorkerThread 24636/25607 [000] 94564.109216: cycles:"
# other combinations possible
if ($include_tid) {
$pname = "$1-$2/$3";
} elsif ($include_pid) {
$pname = "$1-$2";
} else {
$pname = $1;
}
$pname =~ tr/ /_/;
# stack line
} elsif (/^\s*(\w+)\s*(.+) \((\S*)\)/) {
my ($pc, $rawfunc, $mod) = ($1, $2, $3);
$rawfunc.="_[k]" if ($annotate_kernel == 1 && $mod =~ m/kernel\./);
if ($show_inline == 1 && $mod !~ m/(perf-\d+.map|kernel\.|\[[^\]]+\])/) {
unshift @stack, inline($pc, $mod);
next;
}
next if $rawfunc =~ /^\(/; # skip process names
my @inline;
for (split /\->/, $rawfunc) {
my $func = $_;
if ($tidy_generic) {
$func =~ s/;/:/g;
$func =~ tr/<>//d;
if ($func !~ m/\.\(.*\)\./) {
# This doesn't look like a Go method name (such as
# "net/http.(*Client).Do"), so everything after the first open
# paren is just noise.
$func =~ s/\(.*//;
}
# now tidy this horrible thing:
# 13a80b608e0a RegExp:[&<>\"\'] (/tmp/perf-7539.map)
$func =~ tr/"\'//d;
# fall through to $tidy_java
}
if ($tidy_java and $pname eq "java") {
# along with $tidy_generic, converts the following:
# Lorg/mozilla/javascript/ContextFactory;.call(Lorg/mozilla/javascript/ContextAction;)Ljava/lang/Object;
# Lorg/mozilla/javascript/ContextFactory;.call(Lorg/mozilla/javascript/C
# Lorg/mozilla/javascript/MemberBox;.<init>(Ljava/lang/reflect/Method;)V
# into:
# org/mozilla/javascript/ContextFactory:.call
# org/mozilla/javascript/ContextFactory:.call
# org/mozilla/javascript/MemberBox:.init
$func =~ s/^L// if $func =~ m:/:;
}
$func .= "_[i]" if scalar(@inline) > 0; #inlined
push @inline, $func;
}
unshift @stack, @inline;
} else {
warn "Unrecognized line: $_";
}
}
foreach my $k (sort { $a cmp $b } keys %collapsed) {
print "$k $collapsed{$k}\n";
}

View File

@ -1,2 +0,0 @@
---
BasedOnStyle: Google

View File

@ -1,38 +0,0 @@
sudo: false
dist: trusty
language: c
compiler:
- clang
- gcc
addons:
apt:
packages:
- check
- libssl-dev
- python3-pip
- valgrind
env:
global:
- PYTHON=python3
install:
- $PYTHON -m pip install --user pytest ecdsa curve25519-donna pyasn1
script:
- make
- ./tests/aestst
- ./tests/test_check
- CK_TIMEOUT_MULTIPLIER=20 valgrind -q --error-exitcode=1 ./tests/test_check
- ./tests/test_openssl 1000
- ITERS=10 $PYTHON -m pytest tests/
notifications:
webhooks:
urls:
- http://ci-bot.satoshilabs.com:5000/travis
on_success: always
on_failure: always
on_start: always

View File

@ -63,6 +63,7 @@ SRCS += rc4.c
SRCS += nem.c
SRCS += segwit_addr.c cash_addr.c
SRCS += memzero.c
SRCS += schnorr.c
SRCS += shamir.c
OBJS = $(SRCS:.c=.o)

104
crypto/schnorr.c Normal file
View File

@ -0,0 +1,104 @@
/**
* Copyright (c) 2019 Anatolii Kurotych
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES
* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#include "schnorr.h"
#include "memzero.h"
// r = H(Q, kpub, m)
static void calc_r(const curve_point *Q, const uint8_t pub_key[33],
const uint8_t *msg, const uint32_t msg_len, bignum256 *r) {
uint8_t Q_compress[33];
compress_coords(Q, Q_compress);
SHA256_CTX ctx;
uint8_t digest[SHA256_DIGEST_LENGTH];
sha256_Init(&ctx);
sha256_Update(&ctx, Q_compress, 33);
sha256_Update(&ctx, pub_key, 33);
sha256_Update(&ctx, msg, msg_len);
sha256_Final(&ctx, digest);
bn_read_be(digest, r);
}
// returns 0 if signing succeeded
int schnorr_sign(const ecdsa_curve *curve, const uint8_t *priv_key,
const bignum256 *k, const uint8_t *msg, const uint32_t msg_len,
schnorr_sign_pair *result) {
bignum256 private_key_scalar;
bn_read_be(priv_key, &private_key_scalar);
uint8_t pub_key[33];
ecdsa_get_public_key33(curve, priv_key, pub_key);
/* Q = kG */
curve_point Q;
scalar_multiply(curve, k, &Q);
/* r = H(Q, kpub, m) */
calc_r(&Q, pub_key, msg, msg_len, &result->r);
/* s = k - r*kpriv mod(order) */
bignum256 s_temp;
bn_copy(&result->r, &s_temp);
bn_multiply(&private_key_scalar, &s_temp, &curve->order);
bn_subtractmod(k, &s_temp, &result->s, &curve->order);
memzero(&private_key_scalar, sizeof(private_key_scalar));
while (bn_is_less(&curve->order, &result->s)) {
bn_mod(&result->s, &curve->order);
}
if (bn_is_zero(&result->s) || bn_is_zero(&result->r)) {
return 1;
}
return 0;
}
// returns 0 if verification succeeded
int schnorr_verify(const ecdsa_curve *curve, const uint8_t *pub_key,
const uint8_t *msg, const uint32_t msg_len,
const schnorr_sign_pair *sign) {
if (msg_len == 0) return 1;
if (bn_is_zero(&sign->r)) return 2;
if (bn_is_zero(&sign->s)) return 3;
if (bn_is_less(&curve->order, &sign->r)) return 4;
if (bn_is_less(&curve->order, &sign->s)) return 5;
curve_point pub_key_point;
if (!ecdsa_read_pubkey(curve, pub_key, &pub_key_point)) {
return 6;
}
// Compute Q = sG + r*kpub
curve_point sG, Q;
scalar_multiply(curve, &sign->s, &sG);
point_multiply(curve, &sign->r, &pub_key_point, &Q);
point_add(curve, &sG, &Q);
/* r = H(Q, kpub, m) */
bignum256 r;
calc_r(&Q, pub_key, msg, msg_len, &r);
if (bn_is_equal(&r, &sign->r)) return 0; // success
return 10;
}

42
crypto/schnorr.h Normal file
View File

@ -0,0 +1,42 @@
/**
* Copyright (c) 2019 Anatolii Kurotych
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES
* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef __SCHNORR_H__
#define __SCHNORR_H__
#include "ecdsa.h"
// result of sign operation
typedef struct {
bignum256 r, s;
} schnorr_sign_pair;
// sign/verify returns 0 if operation succeeded
// k is a random from [1, ..., order-1]
int schnorr_sign(const ecdsa_curve *curve, const uint8_t *priv_key,
const bignum256 *k, const uint8_t *msg, const uint32_t msg_len,
schnorr_sign_pair *result);
int schnorr_verify(const ecdsa_curve *curve, const uint8_t *pub_key,
const uint8_t *msg, const uint32_t msg_len,
const schnorr_sign_pair *sign);
#endif

View File

@ -61,6 +61,7 @@
#include "rand.h"
#include "rc4.h"
#include "rfc6979.h"
#include "schnorr.h"
#include "script.h"
#include "secp256k1.h"
#include "sha2.h"
@ -8448,6 +8449,195 @@ START_TEST(test_compress_coords) {
}
END_TEST
// vectors generated using Schnorr::Sign function defined in
// https://github.com/Zilliqa/Zilliqa/blob/master/src/libCrypto/Schnorr.cpp#L88
START_TEST(test_schnorr_sign_verify) {
static struct {
const char *message;
const char *priv_key;
const char *k_hex;
const char *s_hex;
const char *r_hex;
} test_cases[] = {
{
"123",
"3382266517e2ebe6df51faf4bfe612236ad46fb8bd59ac982a223b045e080ac6",
"669301F724C555D7BB1185C04909E9CACA3EC7A292B3A1C92DDCCD5A5A7DDDD3",
"FFD72C290B98C93A4BCEDC0EDCDF040C35579BE962FE83E6821D4F3CB4B795D2",
"74AAE9C3E069E2806E1B0D890970BE387AEBED8040F37991AACAD70B27895E39",
},
{
"1234",
"51a2758eed776c40b367364909c8a9c98cc969104f69ff316f7a287495c37c9b",
"A0A1A9B3570AAE963535B8D4376C58A61646C18182C9FDDA5FB13703F88D4D1E",
"99A0CB942C81571B77C682F79CD3CB663CE9E1C55BB425BA24B9F11A0DE84FE2",
"C3C10363E38158BBA20556A36DE9358DFD81A31C180ABC9E7617C1CC1CAF03B3",
},
{
"12345",
"2685adffdbb4b2c515054cffc25cfcbfe2e462df65bbe82fb50f71e1e68dd285",
"38DE7B3315F201433D271E91FBE62966576CA05CBFEC1770B77D7EC9D6A01D6D",
"28982FA6C2B620CBC550F7EF9EAB605F409C584FBE5A765678877B79AB517086",
"9A0788E5B0947DEDEDE386DF57A006CF3FE43919A74D9CA630F8A1A9D97B4650",
},
{
"fun",
"7457dc574d927e5dae84b05264a5b637b5a68e34a85b3965084ed6fed5b7f12d",
"E005ABD242C7C602AB5EED080C5083C7C5F8DAEC6D046A54F384A8B8CDECF740",
"51070ABCA039DAC294F6BA3BFC8C36CFC66020EDF66D1ACF1A9B545B0BF09F52",
"330A924525EF722FA20E8E25CB6E8BD7DF4394886FA4414E4A0B6812AA25BBC0",
},
{
"funny",
"52c395a6d304de1a959e73e4604e32c5ad3f2bf01c8f730af426b38d7d5dd908",
"0CF28B5C40A8830F3195BB99A9F0E2808F576105F41D16ABCF596AC5A8CFE88A",
"3D60FB4664C994AD956378B9402BC68F7B4799D74F4783A6199C0D74865EA2B6",
"5ED5EDEE0314DFFBEE39EE4E9C76DE8BC3EB8CB891AEC32B83957514284B205B",
},
{
"What is great in man is that he is a bridge and not a goal",
"52c395a6d304de1a959e73e4604e32c5ad3f2bf01c8f730af426b38d7d5dd908",
"000000000000000000000000000000000000000000000000000000000000007B",
"546F70AA1FEE3718C95508240CDC073B9FEFED05959C5319DD8E2BF07A1DD028",
"B8667BE5E10B113608BFE5327C44E9F0462BE26F789177E10DCE53019AA33DAA",
},
{
"123456789147258369qwertyuiopasdfghjklzxcvbnm,",
"2685adffdbb4b2c515054cffc25cfcbfe2e462df65bbe82fb50f71e1e68dd285",
"1D0CB70310C4D793A4561FE592B7C156771E3E26283B28AB588E968243B52DD0",
"54D7A435E5E3F2811AA542F8895C20CCB760F2713DBDDB7291DAB6DA4E4F927E",
"20A3BDABFFF2C1BF8E2AF709F6CDCAFE70DA9A1DBC22305B6332E36844092984",
},
{
"11111111111111111111111111111111111111111111111111111111111111111"
"11111111111111111111111111111111111111111111111111111111111111111"
"111111111111111111",
"3382266517e2ebe6df51faf4bfe612236ad46fb8bd59ac982a223b045e080ac6",
"A669F372B3C2EEA351210082CAEC3B96767A7B222D19FF2EE3D814860F0D703A",
"4890F9AC3A8D102EE3A2A473930C01CAD29DCE3860ACB7A5DADAEF16FE808991",
"979F088E58F1814D5E462CB9F935D2924ABD8D32211D8F02DD7E0991726DF573",
},
{
"qwertyuiop[]asdfghjkl;'zxcvbnm,./1234567890-=",
"7457dc574d927e5dae84b05264a5b637b5a68e34a85b3965084ed6fed5b7f12d",
"000000000000000000000000000000000000000000000000000000000000007C",
"0AA595A649E517133D3448CA657424DD07BBED289030F0C0AA6738D26AB9A910",
"83812632F1443A70B198D112D075D886BE7BBC6EC6275AE52661E52B7358BB8B",
},
};
const ecdsa_curve *curve = &secp256k1;
bignum256 k;
uint8_t priv_key[32], buf_raw[32];
schnorr_sign_pair result;
for (size_t i = 0; i < sizeof(test_cases) / sizeof(*test_cases); i++) {
memcpy(priv_key, fromhex(test_cases[i].priv_key), 32);
memcpy(&buf_raw, fromhex(test_cases[i].k_hex), 32);
bn_read_be(buf_raw, &k);
schnorr_sign(curve, priv_key, &k, (const uint8_t *)test_cases[i].message,
strlen(test_cases[i].message), &result);
schnorr_sign_pair expected;
memcpy(&buf_raw, fromhex(test_cases[i].s_hex), 32);
bn_read_be(buf_raw, &expected.s);
memcpy(&buf_raw, fromhex(test_cases[i].r_hex), 32);
bn_read_be(buf_raw, &expected.r);
ck_assert_mem_eq(&expected.r, &result.r, 32);
ck_assert_mem_eq(&expected.s, &result.s, 32);
uint8_t pub_key[33];
ecdsa_get_public_key33(curve, priv_key, pub_key);
int res =
schnorr_verify(curve, pub_key, (const uint8_t *)test_cases[i].message,
strlen(test_cases[i].message), &result);
ck_assert_int_eq(res, 0);
}
}
END_TEST
// vectors generated using Schnorr::Sign function defined in
// https://github.com/Zilliqa/Zilliqa/blob/master/src/libCrypto/Schnorr.cpp#L88
START_TEST(test_schnorr_fail_verify) {
static struct {
const char *message;
const char *priv_key;
const char *k_hex;
const char *s_hex;
const char *r_hex;
} test_case = {
"123",
"3382266517e2ebe6df51faf4bfe612236ad46fb8bd59ac982a223b045e080ac6",
"669301F724C555D7BB1185C04909E9CACA3EC7A292B3A1C92DDCCD5A5A7DDDD3",
"FFD72C290B98C93A4BCEDC0EDCDF040C35579BE962FE83E6821D4F3CB4B795D2",
"74AAE9C3E069E2806E1B0D890970BE387AEBED8040F37991AACAD70B27895E39",
};
const ecdsa_curve *curve = &secp256k1;
bignum256 k;
uint8_t priv_key[32], buf_raw[32];
memcpy(priv_key, fromhex(test_case.priv_key), 32);
memcpy(&buf_raw, fromhex(test_case.k_hex), 32);
bn_read_be(buf_raw, &k);
schnorr_sign_pair result;
schnorr_sign(curve, priv_key, &k, (const uint8_t *)test_case.message,
strlen(test_case.message), &result);
uint8_t pub_key[33];
ecdsa_get_public_key33(curve, priv_key, pub_key);
// OK
int res = schnorr_verify(curve, pub_key, (const uint8_t *)test_case.message,
strlen(test_case.message), &result);
ck_assert_int_eq(res, 0);
res = schnorr_verify(curve, pub_key, (const uint8_t *)test_case.message, 0,
&result);
ck_assert_int_eq(res, 1);
schnorr_sign_pair bad_result;
bn_copy(&result.s, &bad_result.s);
bn_zero(&bad_result.r);
// r == 0
res = schnorr_verify(curve, pub_key, (const uint8_t *)test_case.message,
strlen(test_case.message), &bad_result);
ck_assert_int_eq(res, 2);
bn_copy(&result.r, &bad_result.r);
bn_zero(&bad_result.s);
// s == 0
res = schnorr_verify(curve, pub_key, (const uint8_t *)test_case.message,
strlen(test_case.message), &bad_result);
ck_assert_int_eq(res, 3);
bn_copy(&result.s, &bad_result.s);
bn_copy(&curve->order, &bad_result.r);
bn_addi(&bad_result.r, 1);
// r == curve->order + 1
res = schnorr_verify(curve, pub_key, (const uint8_t *)test_case.message,
strlen(test_case.message), &bad_result);
ck_assert_int_eq(res, 4);
bn_copy(&result.r, &bad_result.r);
bn_copy(&curve->order, &bad_result.s);
bn_addi(&bad_result.s, 1);
// s == curve->order + 1
res = schnorr_verify(curve, pub_key, (const uint8_t *)test_case.message,
strlen(test_case.message), &bad_result);
ck_assert_int_eq(res, 5);
bn_copy(&result.r, &bad_result.r);
bn_copy(&result.s, &bad_result.s);
// change message
test_case.message = "12";
res = schnorr_verify(curve, pub_key, (const uint8_t *)test_case.message,
strlen(test_case.message), &bad_result);
ck_assert_int_eq(res, 10);
}
END_TEST
static int my_strncasecmp(const char *s1, const char *s2, size_t n) {
size_t i = 0;
while (i < n) {
@ -8729,6 +8919,11 @@ Suite *test_suite(void) {
tcase_add_test(tc, test_compress_coords);
suite_add_tcase(s, tc);
tc = tcase_create("schnorr");
tcase_add_test(tc, test_schnorr_sign_verify);
tcase_add_test(tc, test_schnorr_fail_verify);
suite_add_tcase(s, tc);
#if USE_CARDANO
tc = tcase_create("bip32-cardano");

View File

@ -5,9 +5,7 @@ START_TEST(test_ed25519_cardano_sign_vectors) {
ed25519_secret_key secret_key_extension;
ed25519_signature signature;
static const char
*vectors[] =
{
static const char *vectors[] = {
"6065a956b1b34145c4416fdc3ba3276801850e91a77a31a7be782463288aea5"
"3", // private key
"60ba6e25b1a02157fb69c5d1d7b96c4619736e545447069a6a6f0ba90844bc8"

View File

@ -30,48 +30,48 @@ class Point:
points = [
Point(
"secp256k1",
0x79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798,
0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8,
0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798,
0x483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8,
),
Point(
"secp256k1",
0x1,
0x4218f20ae6c646b363db68605822fb14264ca8d2587fdd6fbc750d587e76a7ee,
0x4218F20AE6C646B363DB68605822FB14264CA8D2587FDD6FBC750D587E76A7EE,
),
Point(
"secp256k1",
0x2,
0x66fbe727b2ba09e09f5a98d70a5efce8424c5fa425bbda1c511f860657b8535e,
0x66FBE727B2BA09E09F5A98D70A5EFCE8424C5FA425BBDA1C511F860657B8535E,
),
Point(
"secp256k1",
0x1b,
0x1adcea1cf831b0ad1653e769d1a229091d0cc68d4b0328691b9caacc76e37c90,
0x1B,
0x1ADCEA1CF831B0AD1653E769D1A229091D0CC68D4B0328691B9CAACC76E37C90,
),
Point(
"nist256p1",
0x6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296,
0x4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5,
0x6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296,
0x4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5,
),
Point(
"nist256p1",
0x0,
0x66485c780e2f83d72433bd5d84a06bb6541c2af31dae871728bf856a174f93f4,
0x66485C780E2F83D72433BD5D84A06BB6541C2AF31DAE871728BF856A174F93F4,
),
Point(
"nist256p1",
0x0,
0x99b7a386f1d07c29dbcc42a27b5f9449abe3d50de25178e8d7407a95e8b06c0b,
0x99B7A386F1D07C29DBCC42A27B5F9449ABE3D50DE25178E8D7407A95E8B06C0B,
),
Point(
"nist256p1",
0xaf8bbdfe8cdd5577acbf345b543d28cf402f4e94d3865b97ea0787f2d3aa5d22,
0x35802b8b376b995265918b078bc109c21a535176585c40f519aca52d6afc147c,
0xAF8BBDFE8CDD5577ACBF345B543D28CF402F4E94D3865B97EA0787F2D3AA5D22,
0x35802B8B376B995265918B078BC109C21A535176585C40F519ACA52D6AFC147C,
),
Point(
"nist256p1",
0x80000,
0x580610071f440f0dcc14a22e2d5d5afc1224c0cd11a3b4b51b8ecd2224ee1ce2,
0x580610071F440F0DCC14A22E2D5D5AFC1224C0CD11A3B4B51B8ECD2224EE1CE2,
),
]

View File

@ -102,7 +102,7 @@ def is_valid_der(data):
try:
structure, _ = der_decode(data)
return data == der_encode(structure)
except:
except Exception:
return False
@ -140,7 +140,7 @@ def parse_ec_pubkey(public_key):
try:
public_key = bytes(public_key["public_key"].asOctets())
except:
except Exception:
raise ParseError("Not a BER encoded named elliptic curve public key")
return curve_name, public_key
@ -152,13 +152,13 @@ def parse_ecdsa256_signature(signature):
raise ParseError("Not a valid DER")
try:
signature, _ = der_decode(signature, asn1Spec=EcSignature())
except:
except Exception:
raise ParseError("Not a valid DER encoded ECDSA signature")
try:
r = int(signature["r"]).to_bytes(32, byteorder="big")
s = int(signature["s"]).to_bytes(32, byteorder="big")
signature = r + s
except:
except Exception:
raise ParseError("Not a valid DER encoded 256 bit ECDSA signature")
return signature
@ -281,7 +281,7 @@ def aes_cbc_decrypt(key, iv, ciphertext):
def load_json_testvectors(filename):
try:
result = json.loads(open(os.path.join(testvectors_directory, filename)).read())
except:
except Exception:
raise DataError()
return result
@ -310,7 +310,7 @@ def generate_aes(filename):
plaintext = unhexlify(test["msg"])
ciphertext = unhexlify(test["ct"])
result = parse_result(test["result"])
except:
except Exception:
raise DataError()
if len(key) not in [128 / 8, 192 / 8, 256 / 8]:
@ -359,7 +359,7 @@ def generate_chacha_poly(filename):
ciphertext = unhexlify(test["ct"])
tag = unhexlify(test["tag"])
result = parse_result(test["result"])
except:
except Exception:
raise DataError()
if result is None:
@ -406,7 +406,7 @@ def generate_curve25519_dh(filename):
private_key = unhexlify(test["private"])
shared = unhexlify(test["shared"])
result = parse_result(test["result"])
except:
except Exception:
raise DataError()
if curve_name != "curve25519":
@ -448,7 +448,7 @@ def generate_ecdh(filename):
private_key = parse_signed_hex(test["private"])
shared = unhexlify(test["shared"])
result = parse_result(test["result"])
except:
except Exception:
raise DataError()
try:
@ -498,7 +498,7 @@ def generate_ecdsa(filename):
try:
public_key = unhexlify(test_group["keyDer"])
except:
except Exception:
raise DataError()
try:
@ -521,7 +521,7 @@ def generate_ecdsa(filename):
signature = unhexlify(test["sig"])
message = unhexlify(test["msg"])
result = parse_result(test["result"])
except:
except Exception:
raise DataError()
if result is None:
@ -563,7 +563,7 @@ def generate_eddsa(filename):
try:
public_key = unhexlify(test_group["keyDer"])
except:
except Exception:
raise DataError()
try:
@ -579,7 +579,7 @@ def generate_eddsa(filename):
signature = unhexlify(test["sig"])
message = unhexlify(test["msg"])
result = parse_result(test["result"])
except:
except Exception:
raise DataError()
if result is None:

View File

@ -1,2 +0,0 @@
---
BasedOnStyle: Google

View File

@ -1,63 +0,0 @@
sudo: false
dist: trusty
language: c
addons:
apt:
sources:
- deadsnakes
packages:
- build-essential
- python3.6
- python3.6-dev
- python3.6-venv
env:
global:
- MAKEFLAGS=-j2
- PYTHON=python3.6
- PROTOBUF_VERSION=3.4.0
- TOOLCHAIN_SHORTVER=8-2018q4
- TOOLCHAIN_LONGVER=gcc-arm-none-eabi-8-2018-q4-major
matrix:
- DEBUG_LINK=0
- DEBUG_LINK=1
matrix:
include:
- name: "Emulator GCC"
env: EMULATOR=1 HEADLESS=1 DEBUG_LINK=1
compiler: gcc
script: pipenv run ./script/cibuild && pipenv run script/test
- name: "Emulator Clang"
env: EMULATOR=1 HEADLESS=1 DEBUG_LINK=1
compiler: clang
script: pipenv run ./script/cibuild && pipenv run script/test
before_install:
- $PYTHON -m ensurepip --user
- $PYTHON -m pip install --user pipenv
install:
- wget "https://github.com/google/protobuf/releases/download/v${PROTOBUF_VERSION}/protoc-${PROTOBUF_VERSION}-linux-x86_64.zip"
- unzip "protoc-${PROTOBUF_VERSION}-linux-x86_64.zip" -d protoc
- export PATH="$(pwd)/protoc/bin:$PATH"
- pipenv install
before_script:
- test "$EMULATOR" = "1" || wget https://developer.arm.com/-/media/Files/downloads/gnu-rm/$TOOLCHAIN_SHORTVER/$TOOLCHAIN_LONGVER-linux.tar.bz2
- test "$EMULATOR" = "1" || tar xfj $TOOLCHAIN_LONGVER-linux.tar.bz2
- test "$EMULATOR" = "1" || export PATH=$PWD/$TOOLCHAIN_LONGVER/bin:$PATH
script:
- pipenv run script/cibuild
- pipenv run make -C bootloader
- pipenv run make -C demo
notifications:
webhooks:
urls:
- http://ci-bot.satoshilabs.com:5000/travis
on_success: always
on_failure: always
on_start: always

View File

@ -132,6 +132,14 @@ LDLIBS += -lopencm3_stm32f2
LIBDEPS += $(TOOLCHAIN_DIR)/lib/libopencm3_stm32f2.a
endif
ifeq ($(BITCOIN_ONLY), 1)
CFLAGS += -DBITCOIN_ONLY=1
CFLAGS += -DU2F_ENABLED=0
else
CFLAGS += -DBITCOIN_ONLY=0
CFLAGS += -DU2F_ENABLED=1
endif
ifeq ($(MEMORY_PROTECT), 0)
CFLAGS += -DMEMORY_PROTECT=0
$(info MEMORY_PROTECT=0)

View File

@ -1,14 +0,0 @@
[[source]]
url = "https://pypi.org/simple"
name = "pypi"
verify_ssl = true
[packages]
setuptools = ">=24.2.0"
trezor = {git = "https://github.com/trezor/python-trezor", editable = true, ref = "master"}
pytest = "*"
mock = "*"
typing = "*"
protobuf = "==3.4.0"
mako = "*"
munch = "*"

214
legacy/Pipfile.lock generated
View File

@ -1,214 +0,0 @@
{
"_meta": {
"hash": {
"sha256": "0c77aa21c1e385d7c3833a2f95bc6129394f6d9ce67e1181700a76a5e15074cb"
},
"pipfile-spec": 6,
"requires": {},
"sources": [
{
"name": "pypi",
"url": "https://pypi.org/simple",
"verify_ssl": true
}
]
},
"default": {
"atomicwrites": {
"hashes": [
"sha256:240831ea22da9ab882b551b31d4225591e5e447a68c5e188db5b89ca1d487585",
"sha256:a24da68318b08ac9c9c45029f4a10371ab5b20e4226738e150e6e7c571630ae6"
],
"version": "==1.1.5"
},
"attrs": {
"hashes": [
"sha256:4b90b09eeeb9b88c35bc642cbac057e45a5fd85367b985bd2809c62b7b939265",
"sha256:e0d0eb91441a3b53dab4d9b743eafc1ac44476296a2053b6ca3af0b139faf87b"
],
"version": "==18.1.0"
},
"certifi": {
"hashes": [
"sha256:13e698f54293db9f89122b0581843a782ad0934a4fe0172d2a980ba77fc61bb7",
"sha256:9fa520c1bacfb634fa7af20a76bcbd3d5fb390481724c597da32c719a7dca4b0"
],
"version": "==2018.4.16"
},
"chardet": {
"hashes": [
"sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae",
"sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691"
],
"version": "==3.0.4"
},
"click": {
"hashes": [
"sha256:29f99fc6125fbc931b758dc053b3114e55c77a6e4c6c3a2674a2dc986016381d",
"sha256:f15516df478d5a56180fbf80e68f206010e6d160fc39fa508b65e035fd75130b"
],
"version": "==6.7"
},
"ecdsa": {
"hashes": [
"sha256:40d002cf360d0e035cf2cb985e1308d41aaa087cbfc135b2dc2d844296ea546c",
"sha256:64cf1ee26d1cde3c73c6d7d107f835fed7c6a2904aef9eac223d57ad800c43fa"
],
"version": "==0.13"
},
"idna": {
"hashes": [
"sha256:156a6814fb5ac1fc6850fb002e0852d56c0c8d2531923a51032d1b70760e186e",
"sha256:684a38a6f903c1d71d6d5fac066b58d7768af4de2b832e426ec79c30daa94a16"
],
"version": "==2.7"
},
"libusb1": {
"hashes": [
"sha256:4707f81e933a97fed1c5bf7d4957f07bae1139cb8084bdee1f50201a40e3fd7c"
],
"version": "==1.6.5"
},
"mako": {
"hashes": [
"sha256:4e02fde57bd4abb5ec400181e4c314f56ac3e49ba4fb8b0d50bba18cb27d25ae"
],
"index": "pypi",
"version": "==1.0.7"
},
"markupsafe": {
"hashes": [
"sha256:a6be69091dac236ea9c6bc7d012beab42010fa914c459791d627dad4910eb665"
],
"version": "==1.0"
},
"mnemonic": {
"hashes": [
"sha256:02a7306a792370f4a0c106c2cf1ce5a0c84b9dbd7e71c6792fdb9ad88a727f1d"
],
"version": "==0.18"
},
"mock": {
"hashes": [
"sha256:5ce3c71c5545b472da17b72268978914d0252980348636840bd34a00b5cc96c1",
"sha256:b158b6df76edd239b8208d481dc46b6afd45a846b7812ff0ce58971cf5bc8bba"
],
"index": "pypi",
"version": "==2.0.0"
},
"more-itertools": {
"hashes": [
"sha256:2b6b9893337bfd9166bee6a62c2b0c9fe7735dcf85948b387ec8cba30e85d8e8",
"sha256:6703844a52d3588f951883005efcf555e49566a48afd4db4e965d69b883980d3",
"sha256:a18d870ef2ffca2b8463c0070ad17b5978056f403fb64e3f15fe62a52db21cc0"
],
"version": "==4.2.0"
},
"munch": {
"hashes": [
"sha256:6ae3d26b837feacf732fb8aa5b842130da1daf221f5af9f9d4b2a0a6414b0d51"
],
"index": "pypi",
"version": "==2.3.2"
},
"pbkdf2": {
"hashes": [
"sha256:ac6397369f128212c43064a2b4878038dab78dab41875364554aaf2a684e6979"
],
"version": "==1.3"
},
"pbr": {
"hashes": [
"sha256:1b8be50d938c9bb75d0eaf7eda111eec1bf6dc88a62a6412e33bf077457e0f45",
"sha256:b486975c0cafb6beeb50ca0e17ba047647f229087bd74e37f4a7e2cac17d2caa"
],
"version": "==4.2.0"
},
"pluggy": {
"hashes": [
"sha256:6e3836e39f4d36ae72840833db137f7b7d35105079aee6ec4a62d9f80d594dd1",
"sha256:95eb8364a4708392bae89035f45341871286a333f749c3141c20573d2b3876e1"
],
"markers": "python_version != '3.2.*' and python_version != '3.1.*' and python_version >= '2.7' and python_version != '3.0.*' and python_version != '3.3.*'",
"version": "==0.7.1"
},
"protobuf": {
"hashes": [
"sha256:1fcb9b704bc2e30767352d86b2664d8f65f8ed49654d7a80e7a150739724e80a",
"sha256:41c4555d9754b985352ce5289fa3ba6b21ed715f595111e46e2b90ca53112475",
"sha256:4d4815467f8a61b06d648699842b233017b201f7a16275d680ec5480f10e30e9",
"sha256:5b816951df388f4ab2adbd3f9ae5619b9a5d7033d14b005c345dc3ee88a7faf4",
"sha256:61dbf86993a9312c3a0816b5252079a3943856003bf0380fea3098c929084ad4",
"sha256:9f3be25ad48b051186ee88f9567a3f3f548facd360e0cb62568e2736d9cfda11",
"sha256:ef02609ef445987976a3a26bff77119c518e0915c96661c3a3b17856d0ef6374"
],
"index": "pypi",
"version": "==3.4.0"
},
"py": {
"hashes": [
"sha256:3fd59af7435864e1a243790d322d763925431213b6b8529c6ca71081ace3bbf7",
"sha256:e31fb2767eb657cbde86c454f02e99cb846d3cd9d61b318525140214fdc0e98e"
],
"version": "==1.5.4"
},
"pyblake2": {
"hashes": [
"sha256:3757f7ad709b0e1b2a6b3919fa79fe3261f166fc375cd521f2be480f8319dde9",
"sha256:407e02c7f8f36fcec1b7aa114ddca0c1060c598142ea6f6759d03710b946a7e3",
"sha256:4d47b4a2c1d292b1e460bde1dda4d13aa792ed2ed70fcc263b6bc24632c8e902",
"sha256:5ccc7eb02edb82fafb8adbb90746af71460fbc29aa0f822526fc976dff83e93f",
"sha256:8043267fbc0b2f3748c6920591cd0b8b5609dcce60c504c32858aa36206386f2",
"sha256:982295a87907d50f4723db6bc724660da76b6547826d52160171d54f95b919ac",
"sha256:baa2190bfe549e36163aa44664d4ee3a9080b236fc5d42f50dc6fd36bbdc749e",
"sha256:c53417ee0bbe77db852d5fd1036749f03696ebc2265de359fe17418d800196c4",
"sha256:fbc9fcde75713930bc2a91b149e97be2401f7c9c56d735b46a109210f58d7358"
],
"version": "==1.1.2"
},
"pytest": {
"hashes": [
"sha256:341ec10361b64a24accaec3c7ba5f7d5ee1ca4cebea30f76fad3dd12db9f0541",
"sha256:952c0389db115437f966c4c2079ae9d54714b9455190e56acebe14e8c38a7efa"
],
"index": "pypi",
"version": "==3.6.4"
},
"requests": {
"hashes": [
"sha256:63b52e3c866428a224f97cab011de738c36aec0185aa91cfacd418b5d58911d1",
"sha256:ec22d826a36ed72a7358ff3fe56cbd4ba69dd7a6718ffd450ff0e9df7a47ce6a"
],
"version": "==2.19.1"
},
"six": {
"hashes": [
"sha256:70e8a77beed4562e7f14fe23a786b54f6296e34344c23bc42f07b15018ff98e9",
"sha256:832dc0e10feb1aa2c68dcc57dbb658f1c7e65b9b61af69048abc87a2db00a0eb"
],
"version": "==1.11.0"
},
"trezor": {
"editable": true,
"git": "https://github.com/trezor/python-trezor",
"ref": "master"
},
"typing": {
"hashes": [
"sha256:3a887b021a77b292e151afb75323dea88a7bc1b3dfa92176cff8e44c8b68bddf",
"sha256:b2c689d54e1144bbcfd191b0832980a21c2dbcf7b5ff7a66248a60c90e951eb8",
"sha256:d400a9344254803a2368533e4533a4200d21eb7b6b729c173bc38201a74db3f2"
],
"index": "pypi",
"version": "==3.6.4"
},
"urllib3": {
"hashes": [
"sha256:a68ac5e15e76e7e5dd2b8f94007233e01effe3e50e8daddf69acfd81cb686baf",
"sha256:b5725a0bd4ba422ab0e66e89e030c806576753ea3ee08554382c14e685d117b5"
],
"version": "==1.23"
}
},
"develop": {}
}

Some files were not shown because too many files have changed in this diff Show More