Merge pull request #4 from zcash/scan-blocks

Scan CompactBlocks from an SQLite cache
This commit is contained in:
str4d 2018-12-01 01:54:42 +00:00 committed by GitHub
commit 560638971c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 620 additions and 103 deletions

View File

@ -1,2 +0,0 @@
[build]
target-dir = "build/rust/target"

2
.gitignore vendored
View File

@ -9,9 +9,11 @@
*.class
# Generated files
.cargo/
bin/
gen/
out/
src/main/rust/protos/
target/
jniLibs/

99
Cargo.lock generated
View File

@ -28,6 +28,21 @@ dependencies = [
"stream-cipher 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "android_log-sys"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "android_logger"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"android_log-sys 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "arrayvec"
version = "0.4.7"
@ -284,6 +299,21 @@ name = "libc"
version = "0.2.43"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "libsqlite3-sys"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)",
"pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
"vcpkg 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "linked-hash-map"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "log"
version = "0.4.6"
@ -292,6 +322,22 @@ dependencies = [
"cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "log-panics"
version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "lru-cache"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"linked-hash-map 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "memchr"
version = "2.1.1"
@ -351,6 +397,11 @@ dependencies = [
"rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "pkg-config"
version = "0.3.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "proc-macro2"
version = "0.4.24"
@ -399,6 +450,22 @@ dependencies = [
"winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "redox_syscall"
version = "0.1.42"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "rusqlite"
version = "0.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
"libsqlite3-sys 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
"lru-cache 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rustc-demangle"
version = "0.1.9"
@ -454,6 +521,16 @@ dependencies = [
"unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "time"
version = "0.1.40"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
"redox_syscall 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "typenum"
version = "1.10.0"
@ -472,6 +549,11 @@ dependencies = [
"void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "vcpkg"
version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "version_check"
version = "0.1.5"
@ -523,8 +605,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
name = "zcash-wallet-sdk-poc"
version = "0.0.1"
dependencies = [
"android_logger 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
"jni 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
"log-panics 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"protobuf 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"protobuf-codegen-pure 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
"rusqlite 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)",
"zcash_client_backend 0.0.0 (git+https://github.com/str4d/librustzcash.git?rev=63ec78bb857a258a97d25a5a6e747389996e566a)",
"zip32 0.0.0 (git+https://github.com/str4d/librustzcash.git?rev=63ec78bb857a258a97d25a5a6e747389996e566a)",
]
@ -582,6 +670,8 @@ dependencies = [
"checksum aes 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e6fb1737cdc8da3db76e90ca817a194249a38fcb500c2e6ecec39b29448aa873"
"checksum aes-soft 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "67cc03b0a090a05cb01e96998a01905d7ceedce1bc23b756c0bb7faa0682ccb1"
"checksum aesni 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6810b7fb9f2bb4f76f05ac1c170b8dde285b6308955dc3afd89710268c958d9e"
"checksum android_log-sys 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b8052e2d8aabbb8d556d6abbcce2a22b9590996c5f849b9c7ce4544a2e3b984e"
"checksum android_logger 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bad99185bc195e796e1591740c26716667b58ac9210a48731f71f803fc6ca43a"
"checksum arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)" = "a1e964f9e24d588183fcb43503abda40d288c8657dfc27311516ce2f05675aef"
"checksum ascii 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a5fc969a8ce2c9c0c4b0429bb8431544f6658283c8326ba5ff8c762b75369335"
"checksum backtrace 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "89a47830402e9981c5c41223151efcced65a0510c13097c769cede7efb34782a"
@ -617,7 +707,11 @@ dependencies = [
"checksum jni-sys 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130"
"checksum lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a374c89b9db55895453a74c1e38861d9deec0b01b405a82516e9d5de4820dea1"
"checksum libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)" = "76e3a3ef172f1a0b9a9ff0dd1491ae5e6c948b94479a3021819ba7d860c8645d"
"checksum libsqlite3-sys 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "742b695cbfb89e549dca6960a55e6802f67d352e33e97859ee46dee835211b0f"
"checksum linked-hash-map 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7860ec297f7008ff7a1e3382d7f7e1dcd69efc94751a2284bafc3d013c2aa939"
"checksum log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c84ec4b527950aa83a329754b01dbe3f58361d1c5efacd1f6d68c494d08a17c6"
"checksum log-panics 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ae0136257df209261daa18d6c16394757c63e032e27aafd8b07788b051082bef"
"checksum lru-cache 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4d06ff7ff06f729ce5f4e227876cb88d10bc59cd4ae1e09fbb2bde15c850dc21"
"checksum memchr 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0a3eb002f0535929f1199681417029ebea04aadc0c7a4224b46be99c7f5d6a16"
"checksum nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9667ddcc6cc8a43afc9b7917599d7216aa09c463919ea32c59ed6cac8bc945"
"checksum num-bigint 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "10b8423ea72ec64751198856a853e07b37087cfc9b53a87ecb19bff67b6d1320"
@ -626,21 +720,26 @@ dependencies = [
"checksum num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c51a3322e4bca9d212ad9a158a02abc6934d005490c054a2778df73a70aa0a30"
"checksum opaque-debug 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d620c9c26834b34f039489ac0dfdb12c7ac15ccaf818350a64c9b5334a452ad7"
"checksum pairing 0.14.2 (git+https://github.com/str4d/librustzcash.git?rev=63ec78bb857a258a97d25a5a6e747389996e566a)" = "<none>"
"checksum pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)" = "676e8eb2b1b4c9043511a9b7bea0915320d7e502b0a079fb03f9635a5252b18c"
"checksum proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)" = "77619697826f31a02ae974457af0b29b723e5619e113e9397b8b82c6bd253f09"
"checksum protobuf 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cbd08d128db199b1c6bb662e343d7d1a8f6d0060b411675766d88e5146a4bb38"
"checksum protobuf-codegen 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c5730e51a78ee86d308caaafeb4b01a0bd79fb92b9ab5a8fd4b94c56786e0862"
"checksum protobuf-codegen-pure 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9b0e4940ec64bbd5a7379b315b97452ca9182f3db697ff630f2bb19b3f9fa379"
"checksum quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "53fa22a1994bd0f9372d7a816207d8a2677ad0325b073f5c5332760f0fb62b5c"
"checksum rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8356f47b32624fef5b3301c1be97e5944ecdd595409cc5da11d05f211db6cfbd"
"checksum redox_syscall 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "cf8fb82a4d1c9b28f1c26c574a5b541f5ffb4315f6c9a791fa47b6a04438fe93"
"checksum rusqlite 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)" = "39bae767eb27866f5c0be918635ae54af705bc09db11be2c43a3c6b361cf3462"
"checksum rustc-demangle 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "bcfe5b13211b4d78e5c2cadfebd7769197d95c639c35a50057eb4c05de811395"
"checksum same-file 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8f20c4be53a8a1ff4c1f1b2bd14570d2f634628709752f0702ecdd2b3f9a5267"
"checksum sapling-crypto 0.0.1 (git+https://github.com/str4d/librustzcash.git?rev=63ec78bb857a258a97d25a5a6e747389996e566a)" = "<none>"
"checksum stream-cipher 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "30dc6118470d69ce0fdcf7e6f95e95853f7f4f72f80d835d4519577c323814ab"
"checksum syn 0.15.21 (registry+https://github.com/rust-lang/crates.io-index)" = "816b7af21405b011a23554ea2dc3f6576dc86ca557047c34098c1d741f10f823"
"checksum synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "73687139bf99285483c96ac0add482c3776528beac1d97d444f6e91f203a2015"
"checksum time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "d825be0eb33fda1a7e68012d51e9c7f451dc1a69391e7fdc197060bb8c56667b"
"checksum typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "612d636f949607bdf9b123b4a6f6d966dedf3ff669f7f045890d3a4a73948169"
"checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc"
"checksum unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56"
"checksum vcpkg 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "def296d3eb3b12371b2c7d0e83bfe1403e4db2d7a0bba324a12b21c4ee13143d"
"checksum version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd"
"checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
"checksum walkdir 2.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "9d9d7ed3431229a144296213105a390676cc49c9b6a72bd19f3176c98e129fa1"

View File

@ -6,7 +6,10 @@ description = "Simple PoC that rust can work with protobufs over JNI"
publish = false
[dependencies]
protobuf = "2"
rand = "0.4"
rusqlite = { version = "0.15", features = ["bundled"] }
log = "0.4"
[dependencies.zcash_client_backend]
git = "https://github.com/str4d/librustzcash.git"
@ -18,6 +21,11 @@ rev = "63ec78bb857a258a97d25a5a6e747389996e566a"
[target.'cfg(target_os="android")'.dependencies]
jni = { version = "0.10", default-features = false }
android_logger = "0.6"
log-panics = "2.0.0"
[build-dependencies]
protobuf-codegen-pure = "2"
[lib]
name = "zcashwalletsdk"

View File

@ -9,6 +9,15 @@ if "%DIRNAME%" == "" set DIRNAME=.
@rem put this somewhere that's often ignored by git
set output_dir=%DIRNAME%\out\ndk\standalone
call :generate_standalone_ndk
call :generate_config
echo Done
exit /b %ERRORLEVEL%
:generate_standalone_ndk
@rem check for NDK standalone
if exist "%output_dir%" echo Standalone NDK files found! && exit /b 0
@ -22,7 +31,7 @@ cd %DIRNAME%
if exist "%standalone_script%" goto standaloneScriptFound
echo NDK not found. Please make sure that ANDROID_HOME is set and the NDK has been installed there
exit 1
exit /b 1
:standaloneScriptFound
echo Standalone NDK files appear to be missing.
@ -43,20 +52,45 @@ mkdir %output_dir%
"%standalone_script%" --arch arm --api 16 --install-dir "%output_dir%\arm"
"%standalone_script%" --arch arm64 --api 21 --install-dir "%output_dir%\arm64"
@rem check for our generated cargo file
set cargo_dir=%DIRNAME%\..\.cargo
set generated_cargo_config=%cargo_dir%\config
@rem end of generate_standalone_ndk
exit /b 0
if exist "%generated_cargo_config%" goto backup
:generate_config
@rem check for our generated cargo file
set cargo_dir=%DIRNAME%\.cargo
set generated_cargo_config=%cargo_dir%\config
set generated_cargo_config_hash=%cargo_dir%\.config-windows.hash
set generated_cargo_config_hash_tmp=%cargo_dir%\.config-windows.hash.tmp
if exist "%generated_cargo_config%" goto configExists
goto notFound
:configExists
if exist "%generated_cargo_config_hash%" goto checkConfig
goto notFound
:checkConfig
echo Cargo config found!
certutil -hashfile %generated_cargo_config% > %generated_cargo_config_hash_tmp%
comp %generated_cargo_config_hash% %generated_cargo_config_hash_tmp% /m
if %ERRORLEVEL% equ 0 exit /b 0
echo.
echo but it does not appear to be correct! Regenerating it.
set backup_config=%cargo_dir%\config.backup
echo First, backing it up from %generated_cargo_config% to %backup_config%
copy %generated_cargo_config% %backup_config%
goto generate
:backup
set backup_config=%cargo_dir%\config.backup
echo existing config found. Backing it up from %generated_cargo_config% to %backup_config%
copy %generated_cargo_config% %backup_config%
:notFound
echo Cargo config not found!
:generate
echo generating cargo config at %generated_cargo_config%
echo Generating cargo config at %generated_cargo_config%
mkdir %cargo_dir% 2>NUL
@ -65,7 +99,10 @@ set output_dir=%output_dir:\=/%
(
echo #auto-generated by build-ndk-standalone.bat
echo #auto-generated by build-ndk-standalone.bat. Modifications may get replaced.
echo.
echo [build]
echo target-dir = "build/rust/target"
echo.
echo [target.i686-linux-android]
echo ar = "%output_dir%/x86/bin/i686-linux-android-ar.exe"
@ -81,7 +118,7 @@ set output_dir=%output_dir:\=/%
) > %generated_cargo_config%
echo Done
certutil -hashfile %generated_cargo_config% > %generated_cargo_config_hash%
@rem end of generate_config
exit /b 0

View File

@ -1,59 +1,91 @@
#!/usr/bin/zsh
# put this somewhere that's often ignored by git
# put this somewhere that will be ignored by git
output_dir=out/ndk/standalone
script_name=$0
# check for NDK standalone
[[ -d "$output_dir" ]] && echo "Standalone NDK files found!" && exit 0
function generate_standalone_ndk()
{
# check for NDK standalone
[[ -d "$output_dir" ]] && echo "Standalone NDK files found!" && return 0
standalone_script=$(find $ANDROID_HOME -name "*make_standalone_toolchain.py")
standalone_script=$(find $ANDROID_HOME -name "*make_standalone_toolchain.py")
# Try to find and print some info about the NDK based on the location of the toolchain script
if [ ! -f "$standalone_script" ]; then
echo "NDK not found. Please make sure that ANDROID_HOME is set and the NDK has been installed there"
else
echo "Standalone NDK files appear to be missing.\n Attempting to install them..."
ndk_dir=$(dirname $(dirname $(dirname $standalone_script 2>/dev/null) 2>/dev/null) 2>/dev/null)
ndk_version=$(grep -oE "[0-9.]{5,}" $ndk_dir/source.properties 2>/dev/null)
echo " NDK version $ndk_version found at $ndk_dir"
fi
# Try to find and print some info about the NDK based on the location of the toolchain script
if [ ! -f "$standalone_script" ]; then
echo "NDK not found. Please make sure that ANDROID_HOME is set and the NDK has been installed there"
else
echo "Standalone NDK files appear to be missing.\n Attempting to install them..."
ndk_dir=$(dirname $(dirname $(dirname $standalone_script 2>/dev/null) 2>/dev/null) 2>/dev/null)
ndk_version=$(grep -oE "[0-9.]{5,}" $ndk_dir/source.properties 2>/dev/null)
echo " NDK version $ndk_version found at $ndk_dir"
fi
echo " Installing the standalone NDK for x86|arm|arm64 into $output_dir"
mkdir -p $output_dir
"$standalone_script" --arch x86 --api 16 --install-dir "$output_dir/x86"
"$standalone_script" --arch arm --api 16 --install-dir "$output_dir/arm"
"$standalone_script" --arch arm64 --api 21 --install-dir "$output_dir/arm64"
echo " Installing the standalone NDK for x86|arm|arm64 into $output_dir"
mkdir -p $output_dir
"$standalone_script" --arch x86 --api 16 --install-dir "$output_dir/x86"
"$standalone_script" --arch arm --api 16 --install-dir "$output_dir/arm"
"$standalone_script" --arch arm64 --api 21 --install-dir "$output_dir/arm64"
}
# check for our generated cargo file
generated_cargo_config=../.cargo/config
function generate_config()
{
# check for our generated cargo file
generated_cargo_config=.cargo/config
generated_cargo_config_hash=.cargo/.config.hash
expected_lines=17
if [ -f "$generated_cargo_config" ]; then
backup_config_filename="config.$(date +%s).backup"
echo " existing config found. Backing it up from $generated_cargo_config to $(dirname $generated_cargo_config)/$backup_config_filename"
cp $generated_cargo_config $(dirname $generated_cargo_config)/$backup_config_filename
fi
if [ -f "$generated_cargo_config" -a -f "$generated_cargo_config_hash" ]; then
echo "Cargo config found!"
echo " generating cargo config at $generated_cargo_config"
line_count=$(wc -l < "$generated_cargo_config")
mkdir -p $(dirname $generated_cargo_config)
sha256sum -c "$generated_cargo_config_hash" && [[ "$line_count" -eq "$expected_lines" ]] && return 0
awk -v SA_NDK=$output_dir -v SCRIPT_DIR=$PWD 'BEGIN{
echo " but it does not appear to be correct! Regenerating it."
printf "#auto-generated by build-ndk-standalone.sh\n\n"
if [ -f "$generated_cargo_config" ]; then
backup_config_filename="config-$(date +%s).backup"
echo " first, backing it up from $generated_cargo_config to $(dirname $generated_cargo_config)/$backup_config_filename"
echo " *** NOTE: if this keeps happening, update the 'expected_lines' value in $script_name : "$(basename "$0")
echo
cp $generated_cargo_config $(dirname $generated_cargo_config)/$backup_config_filename
fi
else
echo "Cargo config not found!"
fi
printf "[target.i686-linux-android]\n"
printf "ar = \"%s/%s/x86/bin/i686-linux-android-ar\"\n", SCRIPT_DIR, SA_NDK
printf "linker = \"%s/%s/x86/bin/i686-linux-android-clang\"\n\n", SCRIPT_DIR, SA_NDK
echo " Generating cargo config at $generated_cargo_config"
printf "[target.armv7-linux-androideabi]\n"
printf "ar = \"%s/%s/arm/bin/arm-linux-androideabi-ar\"\n", SCRIPT_DIR, SA_NDK
printf "linker = \"%s/%s/arm/bin/arm-linux-androideabi-clang\"\n\n", SCRIPT_DIR, SA_NDK
mkdir -p $(dirname $generated_cargo_config)
printf "[target.aarch64-linux-android]\n"
printf "ar = \"%s/%s/arm64/bin/aarch64-linux-android-ar\"\n", SCRIPT_DIR, SA_NDK
printf "linker = \"%s/%s/arm64/bin/aarch64-linux-android-clang\"\n\n", SCRIPT_DIR, SA_NDK
awk -v SA_NDK=$output_dir -v SCRIPT_DIR=$PWD 'BEGIN{
}' > $generated_cargo_config
printf "#auto-generated by build-ndk-standalone.sh. Modifications will get replaced.\n\n"
printf "[build]\n"
printf "target-dir = \"build/rust/target\"\n\n"
printf "[target.i686-linux-android]\n"
printf "ar = \"%s/%s/x86/bin/i686-linux-android-ar\"\n", SCRIPT_DIR, SA_NDK
printf "linker = \"%s/%s/x86/bin/i686-linux-android-clang\"\n\n", SCRIPT_DIR, SA_NDK
printf "[target.armv7-linux-androideabi]\n"
printf "ar = \"%s/%s/arm/bin/arm-linux-androideabi-ar\"\n", SCRIPT_DIR, SA_NDK
printf "linker = \"%s/%s/arm/bin/arm-linux-androideabi-clang\"\n\n", SCRIPT_DIR, SA_NDK
printf "[target.aarch64-linux-android]\n"
printf "ar = \"%s/%s/arm64/bin/aarch64-linux-android-ar\"\n", SCRIPT_DIR, SA_NDK
printf "linker = \"%s/%s/arm64/bin/aarch64-linux-android-clang\"\n\n", SCRIPT_DIR, SA_NDK
}' > $generated_cargo_config
sha256sum $generated_cargo_config > $generated_cargo_config_hash
}
generate_standalone_ndk
generate_config
echo "Done"

View File

@ -5,14 +5,15 @@ buildscript {
'targetSdkVersion': 28
]
ext.versions = [
'kotlin': '1.3.0'
'kotlin': '1.3.10',
'architectureComponents': '2.0.0'
]
repositories {
google()
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.4.0-alpha04'
classpath 'com.android.tools.build:gradle:3.4.0-alpha05'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:${versions.kotlin}"
classpath "com.github.ben-manes:gradle-versions-plugin:0.20.0"
classpath 'com.github.dcendents:android-maven-gradle-plugin:2.1'
@ -23,11 +24,12 @@ apply from: 'custom-tasks.gradle'
apply plugin: 'com.android.library'
apply plugin: "kotlin-android-extensions"
apply plugin: "kotlin-android"
apply plugin: 'kotlin-kapt'
apply plugin: 'com.github.ben-manes.versions'
apply plugin: 'com.github.dcendents.android-maven'
group = 'cash.z.android.wallet'
version = '1.1.1'
version = '1.2.0'
repositories {
google()
@ -40,9 +42,9 @@ android {
defaultConfig {
minSdkVersion 16
targetSdkVersion 28
versionCode = 1_01_01
versionName = "1.1.1"
testInstrumentationRunner = "android.support.test.runner.AndroidJUnitRunner"
versionCode = 1_02_00
versionName = "1.2.0"
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
@ -61,16 +63,28 @@ android {
}
dependencies {
// Square
api "com.squareup.wire:wire-runtime:2.2.0"
// Architecture components
implementation "androidx.lifecycle:lifecycle-runtime:${versions.architectureComponents}"
implementation "androidx.lifecycle:lifecycle-extensions:${versions.architectureComponents}"
implementation "androidx.room:room-runtime:${versions.architectureComponents}"
kapt "androidx.lifecycle:lifecycle-compiler:${versions.architectureComponents}"
kapt "androidx.room:room-compiler:${versions.architectureComponents}"
// Other
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:${versions.kotlin}"
implementation "com.android.support:appcompat-v7:28.0.0"
// Tests
testImplementation "junit:junit:4.12"
androidTestImplementation "com.android.support.test:runner:1.0.2"
androidTestImplementation "com.android.support.test.espresso:espresso-core:3.0.2"
androidTestImplementation "androidx.test:runner:1.1.0"
androidTestImplementation "androidx.test.espresso:espresso-core:3.1.0"
androidTestImplementation "androidx.test:core:1.0.0"
androidTestImplementation "androidx.arch.core:core-testing:${versions.architectureComponents}"
}
preBuild.dependsOn generateProtobufClasses
preBuild.dependsOn generateJniLibs
preBuild.dependsOn copyLibArmeabi
preBuild.dependsOn copyAllJniLibs

10
build.rs Normal file
View File

@ -0,0 +1,10 @@
extern crate protobuf_codegen_pure;
fn main() {
protobuf_codegen_pure::run(protobuf_codegen_pure::Args {
out_dir: "src/main/rust/protos",
input: &["src/main/proto/ValueReceived.proto"],
includes: &["src/main/proto"],
customize: Default::default(),
}).expect("protoc");
}

View File

@ -20,7 +20,7 @@ buildscript {
}
}
tasks.register("generateProtobufClasses").configure {
tasks.register("generateProtobufClasses") {
doFirst {
println("**** CREATING PROTOS ****")
delete(protoDestDir)
@ -41,7 +41,7 @@ tasks.register("generateProtobufClasses").configure {
outputs.files(fileTree(dir: protoDestDir, include: '**'))
}
tasks.register("generateJniLibs").configure {
tasks.register("generateJniLibs") {
doFirst {
println("**** CREATING JNI LIBS ****")
delete(jniDestDir)
@ -59,20 +59,25 @@ tasks.register("generateJniLibs").configure {
}
}
}
inputs.files(fileTree(dir: jniSrcDir, include: '**/*'))
inputs.files(fileTree(dir: jniSrcDir, include: '**/*.rs'))
outputs.files(fileTree(dir: jniDestDir, include: '**/*.so'))
}
tasks.register("copyLibX86", Copy) {
dependsOn generateJniLibs
from libX86File
into libX86Dir
}
tasks.register("copyLibArm64", Copy) {
dependsOn generateJniLibs
from libArm64File
into libArm64Dir
}
tasks.register("copyLibArmeabi", Copy) {
dependsOn copyLibArm64, copyLibX86
dependsOn generateJniLibs
from libArmeabiFile
into libArmeabiDir
}
tasks.register("copyAllJniLibs") {
dependsOn copyLibX86, copyLibArm64, copyLibArmeabi
}

View File

@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-5.0-milestone-1-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-5.0-all.zip

View File

@ -1,26 +0,0 @@
package cash.z.wallet.sdk;
import android.content.Context;
import android.support.test.InstrumentationRegistry;
import android.support.test.runner.AndroidJUnit4;
import org.junit.Test;
import org.junit.runner.RunWith;
import static org.junit.Assert.*;
/**
* Instrumented test, which will execute on an Android device.
*
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
*/
@RunWith(AndroidJUnit4.class)
public class ExampleInstrumentedTest {
@Test
public void useAppContext() {
// Context of the app under test.
Context appContext = InstrumentationRegistry.getTargetContext();
assertEquals("cash.z.wallet.sdk.test", appContext.getPackageName());
}
}

View File

@ -0,0 +1,55 @@
package cash.z.wallet.sdk.dao
import androidx.arch.core.executor.testing.InstantTaskExecutorRule
import androidx.room.Room
import androidx.test.platform.app.InstrumentationRegistry
import cash.z.wallet.sdk.db.CompactBlockDb
import cash.z.wallet.sdk.vo.CompactBlock
import org.junit.*
import org.junit.Assert.*
class ComplactBlockDaoTest {
@get:Rule
var instantTaskExecutorRule = InstantTaskExecutorRule()
private lateinit var dao: CompactBlockDao
private lateinit var db: CompactBlockDb
@Before
fun initDb() {
db = Room.inMemoryDatabaseBuilder(
InstrumentationRegistry.getInstrumentation().context,
CompactBlockDb::class.java
)
.build()
.apply { dao = complactBlockDao() }
}
@After
fun close() {
db.close()
}
@Test
fun testDbExists() {
assertNotNull(db)
}
@Test
fun testDaoExists() {
assertNotNull(dao)
}
@Test
fun testDaoInsert() {
CompactBlock(343899, "sample".toByteArray()).let { block ->
dao.insert(block)
val result = dao.findById(block.height)
assertEquals(block.height, result?.height)
assertTrue(block.data.contentEquals(result!!.data))
dao.delete(block)
}
}
}

View File

@ -0,0 +1,55 @@
package cash.z.wallet.sdk.db
import androidx.arch.core.executor.testing.InstantTaskExecutorRule
import androidx.room.Room
import androidx.room.RoomDatabase
import androidx.test.core.app.ApplicationProvider
import cash.z.wallet.sdk.dao.CompactBlockDao
import cash.z.wallet.sdk.vo.CompactBlock
import org.junit.*
import org.junit.Assert.*
class DbIntegrationTest {
@get:Rule
var instantTaskExecutorRule = InstantTaskExecutorRule()
@Test
fun testDbExists() {
assertNotNull(db)
}
@Test
fun testDaoExists() {
assertNotNull(dao)
}
@Test
fun testDaoPrepopulated() {
dao.findById(343900).apply {
assertEquals(343900, this?.height)
}
}
companion object {
private lateinit var dao: CompactBlockDao
private lateinit var db: CompactBlockDb
@BeforeClass
@JvmStatic
fun setup() {
// TODO: put this database in the assets directory and open it from there via .openHelperFactory(new AssetSQLiteOpenHelperFactory()) seen here https://github.com/albertogiunta/sqliteAsset
db = Room
.databaseBuilder(ApplicationProvider.getApplicationContext(), CompactBlockDb::class.java, "compact-blocks.db")
.setJournalMode(RoomDatabase.JournalMode.TRUNCATE)
.fallbackToDestructiveMigration()
.build()
.apply { dao = complactBlockDao() }
}
@AfterClass
@JvmStatic
fun close() {
db.close()
}
}
}

View File

@ -0,0 +1,44 @@
package cash.z.wallet.sdk.jni
import org.junit.Assert.assertEquals
import org.junit.Assert.assertNotNull
import org.junit.BeforeClass
import org.junit.Test
class JniConverterTest {
@Test
fun testGetAddress_exists() {
assertNotNull(converter.getAddress("dummyseed".toByteArray()))
}
@Test
fun testGetAddress_valid() {
val address = converter.getAddress("dummyseed".toByteArray())
val expectedAddress = "ztestsapling1snmqdnfqnc407pvqw7sld8w5zxx6nd0523kvlj4jf39uvxvh7vn0hs3q38n07806dwwecqwke3t"
assertEquals("Invalid address", expectedAddress, address)
}
@Test
fun testScanBlocks() {
// note: for this to work, the db file below must be uploaded to the device. Eventually, this test will be self-contained and remove that requirement.
val result = converter.scanBlocks(
"/data/user/0/cash.z.wallet.sdk.test/databases/compact-block.db",
343900,
344855,
"dummyseed".toByteArray()
)
assertEquals("Invalid number of results", 2, result.size)
}
companion object {
val converter: JniConverter = JniConverter()
@BeforeClass
@JvmStatic
fun setup() {
converter.initLogs()
}
}
}

View File

@ -0,0 +1,19 @@
package cash.z.wallet.sdk.dao
import androidx.room.*
import cash.z.wallet.sdk.vo.CompactBlock
@Dao
interface CompactBlockDao {
@Insert(onConflict = OnConflictStrategy.REPLACE)
fun insert(block: CompactBlock)
@Query("SELECT * FROM compactblocks WHERE height = :height")
fun findById(height: Int): CompactBlock?
@Query("DELETE FROM compactblocks WHERE height = :height")
fun deleteById(height: Int)
@Delete
fun delete(block: CompactBlock)
}

View File

@ -0,0 +1,16 @@
package cash.z.wallet.sdk.db
import androidx.room.Database
import androidx.room.RoomDatabase
import cash.z.wallet.sdk.dao.CompactBlockDao
import cash.z.wallet.sdk.vo.CompactBlock
@Database(
entities = [
CompactBlock::class],
version = 1,
exportSchema = false
)
abstract class CompactBlockDb : RoomDatabase() {
abstract fun complactBlockDao(): CompactBlockDao
}

View File

@ -4,6 +4,10 @@ class JniConverter {
external fun getAddress(seed: ByteArray): String
external fun scanBlocks(db: String, start: Int, end: Int, seed: ByteArray): Array<ByteArray>
external fun initLogs()
companion object {
init {
System.loadLibrary("zcashwalletsdk")

View File

@ -0,0 +1,27 @@
package cash.z.wallet.sdk.vo
import androidx.room.ColumnInfo
import androidx.room.Entity
@Entity(primaryKeys = ["height"], tableName = "compactblocks")
data class CompactBlock(
val height: Int,
@ColumnInfo(typeAffinity = ColumnInfo.BLOB)
val data: ByteArray
) {
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other !is CompactBlock) return false
if (height != other.height) return false
if (!data.contentEquals(other.data)) return false
return true
}
override fun hashCode(): Int {
var result = height
result = 31 * result + data.contentHashCode()
return result
}
}

View File

@ -0,0 +1,9 @@
syntax = "proto3";
package cash.z.wallet.sdk.proto;
message ValueReceived {
uint64 blockHeight = 1;
bytes txHash = 2;
uint64 value = 3;
}

View File

@ -1,12 +1,23 @@
#[macro_use]
extern crate log;
extern crate protobuf;
extern crate rusqlite;
extern crate zcash_client_backend;
extern crate zip32;
mod protos;
use rusqlite::Connection;
use zcash_client_backend::{
address::encode_payment_address, constants::HRP_SAPLING_EXTENDED_SPENDING_KEY_TEST,
welding_rig::scan_block_from_bytes,
};
use zip32::{ChildIndex, ExtendedSpendingKey};
use zip32::{ChildIndex, ExtendedFullViewingKey, ExtendedSpendingKey};
fn address_from_seed(seed: &[u8]) -> String {
use protos::ValueReceived::ValueReceived;
fn extfvk_from_seed(seed: &[u8]) -> ExtendedFullViewingKey {
let master = ExtendedSpendingKey::master(seed);
let extsk = ExtendedSpendingKey::from_path(
&master,
@ -16,21 +27,85 @@ fn address_from_seed(seed: &[u8]) -> String {
ChildIndex::Hardened(0),
],
);
let addr = extsk.default_address().unwrap().1;
ExtendedFullViewingKey::from(&extsk)
}
fn address_from_extfvk(extfvk: &ExtendedFullViewingKey) -> String {
let addr = extfvk.default_address().unwrap().1;
encode_payment_address(HRP_SAPLING_EXTENDED_SPENDING_KEY_TEST, &addr)
}
struct CompactBlockRow {
height: i32,
data: Vec<u8>,
}
/// Scans the given block range for any transactions received by the given
/// ExtendedFullViewingKeys. Returns a Vec of block height, txid and value.
fn scan_cached_blocks(
db: String,
start: i32,
end: i32,
extfvks: &[ExtendedFullViewingKey],
) -> Vec<ValueReceived> {
let conn = Connection::open(db).unwrap();
let mut stmt = conn
.prepare("SELECT height, data FROM compactblocks WHERE height >= ? AND height <= ?")
.unwrap();
let rows = stmt
.query_map(&[start, end], |row| CompactBlockRow {
height: row.get(0),
data: row.get(1),
}).unwrap();
let mut received = vec![];
for row in rows {
let row = row.unwrap();
for tx in scan_block_from_bytes(&row.data, &extfvks) {
for output in tx.shielded_outputs {
let mut vr = ValueReceived::new();
vr.set_blockHeight(row.height as u64);
vr.set_txHash(tx.txid.0.to_vec());
vr.set_value(output.value);
received.push(vr);
}
}
}
received
}
/// JNI interface
#[cfg(target_os = "android")]
#[allow(non_snake_case)]
pub mod android {
extern crate android_logger;
extern crate jni;
extern crate log_panics;
use self::jni::objects::JClass;
use self::jni::sys::{jbyteArray, jstring};
use log::Level;
use protobuf::Message;
use self::android_logger::Filter;
use self::jni::objects::{JClass, JString};
use self::jni::sys::{jbyteArray, jint, jobjectArray, jsize, jstring};
use self::jni::JNIEnv;
use super::address_from_seed;
use super::{address_from_extfvk, extfvk_from_seed, scan_cached_blocks};
#[no_mangle]
pub unsafe extern "C" fn Java_cash_z_wallet_sdk_jni_JniConverter_initLogs(
_env: JNIEnv,
_: JClass,
) {
android_logger::init_once(
Filter::default().with_min_level(Level::Trace),
Some("cash.z.rust.logs"),
);
log_panics::init();
debug!("logs have been initialized successfully");
}
#[no_mangle]
pub unsafe extern "C" fn Java_cash_z_wallet_sdk_jni_JniConverter_getAddress(
@ -40,9 +115,42 @@ pub mod android {
) -> jstring {
let seed = env.convert_byte_array(seed).unwrap();
let addr = address_from_seed(&seed);
let addr = address_from_extfvk(&extfvk_from_seed(&seed));
let output = env.new_string(addr).expect("Couldn't create Java string!");
output.into_inner()
}
#[no_mangle]
pub unsafe extern "C" fn Java_cash_z_wallet_sdk_jni_JniConverter_scanBlocks(
env: JNIEnv,
_: JClass,
db: JString,
start: jint,
end: jint,
seed: jbyteArray,
) -> jobjectArray {
let db = env
.get_string(db)
.expect("Couldn't get Java string!")
.into();
let seed = env.convert_byte_array(seed).unwrap();
let received = scan_cached_blocks(db, start, end, &[extfvk_from_seed(&seed)]);
let jreceived = env
.new_object_array(
received.len() as jsize,
"[B",
env.new_byte_array(0).unwrap().into(),
).unwrap();
for (i, vr) in received.into_iter().enumerate() {
let jvr = env
.byte_array_from_slice(&vr.write_to_bytes().unwrap())
.unwrap();
env.set_object_array_element(jreceived, i as jsize, jvr.into())
.unwrap();
}
jreceived
}
}

View File

@ -0,0 +1 @@
pub mod ValueReceived;