trezor-firmware icon indicating copy to clipboard operation
trezor-firmware copied to clipboard

feat(core): add Zcash Rust primitives

Open krnak opened this issue 3 years ago • 3 comments
trafficstars

This PR adds

  • pasta curves arithmetic (from pasta_curves crate)
  • redpallas signature scheme (from reddsa crate)
  • poseidon hash function (my own tested implementation)

Three pasta curves struct (Fp, Scalar and Point) are exposed to micropython using generic container Wrapped<T> defined in micropython/wrap.rs.

Newly imported crates depend on blake2b_simd crate. Since there is already a C implementation of blake2b, I just added a Rust interface to it (in rust/blake2b_hal) and then I overwrote blake2b_simd by blake2b_hal via [crates-io.patch].

Poseidon function requires some precomputed round constants. Since the generating algorithm is pretty lightweight (it is based on LSFR), I decided to replace the constants table (6144 bytes) by my own highly optimized implementation of the generator itself (circa 512 kb). Generator is tested on all expected constants. Poseidon implementation is tested on official zcash test vectors.

Crate reddsa is patched to include this minor fix

  • https://github.com/ZcashFoundation/reddsa/pull/28

Crate pasta_curves is patched, because these issue and pr are pending:

  • https://github.com/zcash/pasta_curves/issues/46
  • https://github.com/zcash/pasta_curves/pull/47

Related links:

krnak avatar Sep 12 '22 13:09 krnak

It would be great if you introduced FEATURE_FLAGS["ZCASH_SHIELDED"] so we could easily turn on/off the feature

prusnak avatar Sep 12 '22 14:09 prusnak

How to deal with this ? @prusnak

ZCASH_SHIELDED
ERROR: Altcoin strings found in Bitcoin-only firmware.

I will need this flag to be accessible from python to disable some functionalities in module zcash/signer.py.

krnak avatar Sep 19 '22 10:09 krnak

I will need this flag to be accessible from python to disable some functionalities in module zcash/signer.py.

We need to replace utils.ZCASH_SHIELDED with a True/False literal, similarly to what we do here:

https://github.com/trezor/trezor-firmware/blob/4bed278e80d23077676128eba8cb2478fcd31120/core/site_scons/site_tools/micropython/init.py#L31

Maybe this does the trick?

diff --git a/core/SConscript.firmware b/core/SConscript.firmware
index 96ffec17d..3d0d30cb4 100644
--- a/core/SConscript.firmware
+++ b/core/SConscript.firmware
@@ -678,7 +678,7 @@ if FROZEN:
         SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'apps/bitcoin/sign_tx/zcash_v4.py'))
         SOURCE_PY.extend(Glob(SOURCE_PY_DIR + 'trezor/enums/Zcash*.py'))
 
-    source_mpy = env.FrozenModule(source=SOURCE_PY, source_dir=SOURCE_PY_DIR, bitcoin_only=BITCOIN_ONLY)
+    source_mpy = env.FrozenModule(source=SOURCE_PY, source_dir=SOURCE_PY_DIR, bitcoin_only=BITCOIN_ONLY, zcash_shielded=FEATURE_FLAGS['ZCASH_SHIELDED'])
 
     source_mpyc = env.FrozenCFile(
         target='frozen_mpy.c', source=source_mpy, qstr_header=qstr_preprocessed)
diff --git a/core/site_scons/site_tools/micropython/__init__.py b/core/site_scons/site_tools/micropython/__init__.py
index 38c40880f..8f897a3ca 100644
--- a/core/site_scons/site_tools/micropython/__init__.py
+++ b/core/site_scons/site_tools/micropython/__init__.py
@@ -26,9 +26,11 @@ def generate(env):
         # replace "utils.BITCOIN_ONLY" with literal constant (True/False)
         # so the compiler can optimize out the things we don't want
         btc_only = env['bitcoin_only'] == '1'
+        zcash_shielded = env['zcash_shielded'] == '1'
         interim = f"{target[:-4]}.i"  # replace .mpy with .i
         sed_scripts = " ".join([
             rf"-e 's/utils\.BITCOIN_ONLY/{btc_only}/g'",
+            rf"-e 's/utils\.ZCASH_SHIELDED/{zcash_shielded}/g'",
             r"-e 's/if TYPE_CHECKING/if False/'",
             r"-e 's/import typing/# \0/'",
             r"-e '/from typing import (/,/^\s*)/ {s/^/# /}'",

If we do the change above I guess we can drop this change completely? Not sure if that's what we want or we want to add exception for this to the check. Maybe @matejcik can help?

Screenshot 2022-09-21 at 13 13 39

prusnak avatar Sep 21 '22 11:09 prusnak

I made changes suggested by @prusnak , but I'm still getting ERROR: Altcoin strings found in Bitcoin-only firmware..

I isolated all new code by ZCASH_SHIELDED flag and tried to define this flag. Since I'm not a creator of TT flag system, neither bitcoin-only edition, resolving this issue could take me hours. I would appreciate if I could let this issue up to you.

krnak avatar Sep 29 '22 09:09 krnak

I made changes suggested by @prusnak , but I'm still getting ERROR: Altcoin strings found in Bitcoin-only firmware..

178d06b597134cc3f7fd81ada1be9952d2dc4c19 should fix it.

If we do the change above I guess we can drop this change completely? Not sure if that's what we want or we want to add exception for this to the check. Maybe @matejcik can help?

Screenshot 2022-09-21 at 13 13 39

I dropped the QSTR, which means that from trezorutils import ZCASH_SHIELDED is importing something that doesn't exist, but it's only for TYPE_CHECKING, so that seems OK. It seems cleaner than adding an exception to tools/check-bitcoin-only.

andrewkozlik avatar Oct 07 '22 08:10 andrewkozlik

thank you andrew

krnak avatar Oct 07 '22 08:10 krnak

178d06b should fix it.

Darn, I hadn't realized this would break the unit tests:

File "../src/trezor/crypto/hashlib.py", line 16, in <module>
AttributeError: 'module' object has no attribute 'ZCASH_SHIELDED'

I think there is no way around that, is there? Adding an exception to tools/check-bitcoin-only: https://github.com/trezor/trezor-firmware/pull/2510/commits/017bb4f54d8f189d2fef01b96f0f1204e3d8583c.

andrewkozlik avatar Oct 07 '22 09:10 andrewkozlik

I think there is no way around that, is there? Adding an exception to tools/check-bitcoin-only: 017bb4f.

Yeah, I guess 017bb4f is the best way how we can fix this.

prusnak avatar Oct 07 '22 09:10 prusnak

istm we could keep ZCASH_SHIELDED qstr only for emulator build? device build is always frozen so the fixed bool replacement is always applied

matejcik avatar Oct 20 '22 11:10 matejcik

Tentative approve, pending review of the Rust dependencies.

matejcik avatar Nov 18 '22 12:11 matejcik

@jarys just to clarify, the only thing you need patched into pasta_curves for this PR is the alloc-free hash-to-curve implementation? If so, I'll try and find some time to work on it.

str4d avatar Dec 06 '22 02:12 str4d

Yes, I confirm. The only thing I need to be patched in pasta_curves is alloc-free hash-to-curve implementation.

krnak avatar Dec 06 '22 03:12 krnak