From 75b6a31e87ae7ae293cc95f1e4da8afd586edfc7 Mon Sep 17 00:00:00 2001 From: Fredrik Harrysson Date: Thu, 14 Sep 2017 19:28:43 +0200 Subject: [PATCH 1/9] Trezor Support (#6403) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Copy modal from keepkey branch and generalize The keepkey PinMatrix modal needs to be the same for Trezor, but we should probably try to keep it general since it can be used for both. * Add trezor communication code This is a result of much trial-and-error and a couple of dead-ends in how to communicate and wire everything up. Code here is still a bit WIP with lots of debug prints and stuff. The test works though, it is possible to sign a transaction. * Extend the basic lib to allow Trezor This is kind of ugly and needs some cleanup and generalization. I’ve just copy-pasted some things to bring in the trezor wallets. I’ve also had to add a lock to the USB API so that only one thing talks to the USB at once. * Add RPC plumbing needed We need to be able to get “locked” devices from the frontend to figure out if we’re going to display the PinMatrix or not. Then we need to be able to send a pin to a device. * Add logic to query backend for Trezor and display PinMatrix There’s a bug somewhere here because signing a transaction fails if you take too long to press the confirm button on the device. * Change back to paritytech branch As my fork has been merged in. * Converting spaces to tabs, as it should be * Incorporate correct handling of EIP-155 Turns out the Trezor was adjusting the v part of the signature, and we’re already doing that so it was done twice. * Some circular logic here that was incorrect BE-encoded U256 is almost the same as RLP encoded without the size-byte, except for " "checksum jsonrpc-http-server 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)" = "" "checksum jsonrpc-ipc-server 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)" = "" @@ -3466,50 +3565,50 @@ dependencies = [ "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" "checksum language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a91d884b6667cd606bb5a69aa0c99ba811a115fc68915e7056ec08a46e93199a" "checksum lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "3b37545ab726dd833ec6420aaba8231c5b320814b9029ad585555d2a03e94fbf" -"checksum lazycell 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ce12306c4739d86ee97c23139f3a34ddf0387bbf181bc7929d287025a8c3ef6b" -"checksum lazycell 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ec38a5c22f1ef3e30d2642aa875620d60edeef36cef43c4739d86215ce816331" -"checksum libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)" = "88ee81885f9f04bff991e306fea7c1c60a5f0f9e409e99f6b40e3311a3363135" -"checksum libflate 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "59fa4619e0f202f63fde6046eafe0e754e829369c5e892abeca0c22a12dcfec9" +"checksum lazycell 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3b585b7a6811fb03aa10e74b278a0f00f8dd9b45dc681f148bb29fa5cb61859b" +"checksum libc 0.2.30 (registry+https://github.com/rust-lang/crates.io-index)" = "2370ca07ec338939e356443dac2296f581453c35fe1e3a3ed06023c49435f915" +"checksum libflate 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "a2aa04ec0100812d31a5366130ff9e793291787bc31da845bede4a00ea329830" "checksum libusb 0.3.0 (git+https://github.com/paritytech/libusb-rs)" = "" "checksum libusb-sys 0.2.3 (git+https://github.com/paritytech/libusb-sys)" = "" -"checksum linked-hash-map 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bda158e0dabeb97ee8a401f4d17e479d6b891a14de0bba79d5cc2d4d325b5e48" "checksum linked-hash-map 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6d262045c5b87c0861b3f004610afd0e2c851e2908d08b6c870cbb9d5f494ecd" +"checksum linked-hash-map 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7860ec297f7008ff7a1e3382d7f7e1dcd69efc94751a2284bafc3d013c2aa939" "checksum local-encoding 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e1ceb20f39ff7ae42f3ff9795f3986b1daad821caaa1e1732a0944103a5a1a66" -"checksum log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "5141eca02775a762cc6cd564d8d2c50f67c0ea3a372cbf1c51592b3e029e10ad" -"checksum lru-cache 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "656fa4dfcb02bcf1063c592ba3ff6a5303ee1f2afe98c8a889e8b1a77c6dfdb7" -"checksum matches 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "15305656809ce5a4805b1ff2946892810992197ce1270ff79baded852187942e" +"checksum log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "880f77541efa6e5cc74e76910c9884d9859683118839d6a1dc3b11e63512565b" +"checksum lru-cache 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4d06ff7ff06f729ce5f4e227876cb88d10bc59cd4ae1e09fbb2bde15c850dc21" +"checksum magenta 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4bf0336886480e671965f794bc9b6fce88503563013d1bfb7a502c81fe3ac527" +"checksum magenta-sys 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "40d014c7011ac470ae28e2f76a02bfea4a8480f73e701353b49ad7a8d75f4699" +"checksum matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "100aabe6b8ff4e4a7e32c1c13523379802df0772b82466207ac25b013f193376" "checksum memchr 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1dbccc0e46f1ea47b9f17e6d67c5a96bd27030519c519c9c91327e31275a47b4" -"checksum mime 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a74cc2587bf97c49f3f5bab62860d6abf3902ca73b66b51d9b049fbdcd727bd2" -"checksum mime_guess 1.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5e50bf542f81754ef69e5cea856946a3819f7c09ea97b4903c8bc8a89f74e7b6" +"checksum mime 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ba626b8a6de5da682e1caa06bdb42a335aee5a84db8e5046a3e8ab17ba0a3ae0" +"checksum mime_guess 1.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bbee1a836f344ac39d4a59bfe7be2bd3150353ff71678afb740216f8270b333e" "checksum miniz-sys 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "28eaee17666671fa872e567547e8428e83308ebe5808cdf6a0e28397dbe2c726" -"checksum mio 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)" = "c8ba718a36791275c6782c0445a5f79b5ef4e68c01a4e60ac04aae28290e4957" +"checksum mio 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "dbd91d3bfbceb13897065e97b2ef177a09a438cb33612b2d371bf568819a9313" "checksum mio-named-pipes 0.1.4 (git+https://github.com/alexcrichton/mio-named-pipes)" = "" -"checksum mio-uds 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "78437f00d9615c366932cbfe79790b5c2945706ba67cf78378ffacc0069ed9de" -"checksum miow 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "3e690c5df6b2f60acd45d56378981e827ff8295562fc8d34f573deb267a59cd1" +"checksum mio-uds 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "1731a873077147b626d89cc6c2a0db6288d607496c5d10c0cfcf3adc697ec673" "checksum miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919" -"checksum msdos_time 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "c04b68cc63a8480fb2550343695f7be72effdec953a9d4508161c3e69041c7d8" +"checksum msdos_time 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "65ba9d75bcea84e07812618fedf284a64776c2f2ea0cad6bca7f69739695a958" "checksum multibase 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b9c35dac080fd6e16a99924c8dfdef0af89d797dd851adab25feaffacf7850d6" "checksum multihash 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d14363c7695e2e5adbbb8fe139d806a19b8b13f02b9b1fb770fab0c12edaff58" "checksum nanomsg 0.5.1 (git+https://github.com/paritytech/nanomsg.rs.git?branch=parity-1.7)" = "" "checksum nanomsg-sys 0.5.0 (git+https://github.com/paritytech/nanomsg.rs.git?branch=parity-1.7)" = "" -"checksum native-tls 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1e94a2fc65a44729fe969cc973da87c1052ae3f000b2cb33029f14aeb85550d5" -"checksum net2 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)" = "bc01404e7568680f1259aa5729539f221cb1e6d047a0d9053cab4be8a73b5d67" +"checksum native-tls 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "04b781c9134a954c84f0594b9ab3f5606abc516030388e8511887ef4c204a1e5" +"checksum net2 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)" = "3a80f842784ef6c9a958b68b7516bc7e35883c614004dd94959a4dca1b716c09" "checksum nodrop 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "52cd74cd09beba596430cc6e3091b74007169a56246e1262f0ba451ea95117b2" -"checksum nom 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6caab12c5f97aa316cb249725aa32115118e1522b445e26c257dd77cad5ffd4e" +"checksum nom 1.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "a5b8c256fd9471521bcb84c3cdba98921497f1a331cbc15b8030fc63b82050ce" "checksum ntp 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d23f30ae7da76e2c6c2f5de53f298aa9a3911d3955ab2c349eb944caedceb088" -"checksum num 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)" = "c04bd954dbf96f76bab6e5bd6cef6f1ce1262d15268ce4f926d2b5b778fa7af2" -"checksum num-bigint 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)" = "41655c8d667be847a0b72fe0888857a7b3f052f691cf40852be5fcf87b274a65" -"checksum num-complex 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)" = "ccac67baf893ac97474f8d70eff7761dabb1f6c66e71f8f1c67a6859218db810" -"checksum num-integer 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)" = "fb24d9bfb3f222010df27995441ded1e954f8f69cd35021f6bef02ca9552fb92" -"checksum num-iter 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)" = "287a1c9969a847055e1122ec0ea7a5c5d6f72aad97934e131c83d5c08ab4e45c" -"checksum num-rational 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)" = "48cdcc9ff4ae2a8296805ac15af88b3d88ce62128ded0cb74ffb63a587502a84" -"checksum num-traits 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)" = "51eab148f171aefad295f8cece636fc488b9b392ef544da31ea4b8ef6b9e9c39" -"checksum num_cpus 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "55aabf4e2d6271a2e4e4c0f2ea1f5b07cc589cc1a9e9213013b54a76678ca4f3" -"checksum number_prefix 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "084d05f4bf60621a9ac9bde941a410df548f4de9545f06e5ee9d3aef4b97cd77" -"checksum odds 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)" = "b28c06e81b0f789122d415d6394b5fe849bde8067469f4c2980d3cdc10c78ec1" +"checksum num 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "a311b77ebdc5dd4cf6449d81e4135d9f0e3b153839ac90e648a8ef538f923525" +"checksum num-bigint 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "8fd0f8dbb4c0960998958a796281d88c16fbe68d87b1baa6f31e2979e81fd0bd" +"checksum num-complex 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "503e668405c5492d67cf662a81e05be40efe2e6bcf10f7794a07bd9865e704e6" +"checksum num-integer 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)" = "d1452e8b06e448a07f0e6ebb0bb1d92b8890eea63288c0b627331d53514d0fba" +"checksum num-iter 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)" = "7485fcc84f85b4ecd0ea527b14189281cf27d60e583ae65ebc9c088b13dffe01" +"checksum num-rational 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "288629c76fac4b33556f4b7ab57ba21ae202da65ba8b77466e6d598e31990790" +"checksum num-traits 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "99843c856d68d8b4313b03a17e33c4bb42ae8f6610ea81b28abe076ac721b9b0" +"checksum num_cpus 1.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "aec53c34f2d0247c5ca5d32cca1478762f301740468ee9ee6dcb7a0dd7a0c584" +"checksum number_prefix 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "59a14be9c211cb9c602bad35ac99f41e9a84b44d71b8cbd3040e3bd02a214902" +"checksum odds 0.2.25 (registry+https://github.com/rust-lang/crates.io-index)" = "c3df9b730298cea3a1c3faa90b7e2f9df3a9c400d0936d6015e6165734eefcba" "checksum ole32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5d2c49021782e5233cd243168edfa8037574afed4eba4bbaf538b3d8d1789d8c" -"checksum openssl 0.9.13 (registry+https://github.com/rust-lang/crates.io-index)" = "b34cd77cf91301fff3123fbd46b065c3b728b17a392835de34c397315dce5586" -"checksum openssl-sys 0.9.13 (registry+https://github.com/rust-lang/crates.io-index)" = "e035022a50faa380bd7ccdbd184d946ce539ebdb0a358780de92a995882af97a" +"checksum openssl 0.9.17 (registry+https://github.com/rust-lang/crates.io-index)" = "085aaedcc89a2fac1eb2bc19cd66f29d4ea99fec60f82a5f3a88a6be7dbd90b5" +"checksum openssl-sys 0.9.17 (registry+https://github.com/rust-lang/crates.io-index)" = "7e3a9845a4c9fdb321931868aae5549e96bb7b979bf9af7de03603d74691b5f3" "checksum order-stat 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "efa535d5117d3661134dbf1719b6f0ffe06f2375843b13935db186cd094105eb" "checksum ordered-float 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "58d25b6c0e47b20d05226d288ff434940296e7e2f8b877975da32f862152241f" "checksum owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "cdf84f41639e037b484f93433aa3897863b561ed65c6e59c7073d7c561710f37" @@ -3517,128 +3616,136 @@ dependencies = [ "checksum parity-tokio-ipc 0.1.5 (git+https://github.com/nikvolf/parity-tokio-ipc)" = "" "checksum parity-ui-precompiled 1.4.0 (git+https://github.com/paritytech/js-precompiled.git)" = "" "checksum parity-wasm 0.14.3 (registry+https://github.com/rust-lang/crates.io-index)" = "466c01423614bbf89a37b0fc081e1ed3523dfd9064497308ad3f9c7c9f0092bb" -"checksum parity-wordlist 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "52142d717754f7ff7ef0fc8da1bdce4f302dd576fb9bf8b727d6a5fdef33348d" -"checksum parking_lot 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "aebb68eebde2c99f89592d925288600fde220177e46b5c9a91ca218d245aeedf" -"checksum parking_lot_core 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fb1b97670a2ffadce7c397fb80a3d687c4f3060140b885621ef1653d0e5d5068" -"checksum phf 0.7.14 (registry+https://github.com/rust-lang/crates.io-index)" = "447d9d45f2e0b4a9b532e808365abf18fc211be6ca217202fcd45236ef12f026" -"checksum phf_codegen 0.7.14 (registry+https://github.com/rust-lang/crates.io-index)" = "8af7ae7c3f75a502292b491e5cc0a1f69e3407744abe6e57e2a3b712bb82f01d" -"checksum phf_generator 0.7.14 (registry+https://github.com/rust-lang/crates.io-index)" = "db005608fd99800c8c74106a7c894cf582055b689aa14a79462cefdcb7dc1cc3" -"checksum phf_shared 0.7.14 (registry+https://github.com/rust-lang/crates.io-index)" = "fee4d039930e4f45123c9b15976cf93a499847b6483dc09c42ea0ec4940f2aa6" +"checksum parity-wordlist 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "81451bfab101d186f8fc4a0aa13cb5539b31b02c4ed96425a0842e2a413daba6" +"checksum parking_lot 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)" = "fa3ebeb90814c5c7965885f0d29a540387f0589804b3b0f4acbb065af8c1df5f" +"checksum parking_lot_core 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "4f610cb9664da38e417ea3225f23051f589851999535290e077939838ab7a595" +"checksum percent-encoding 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "de154f638187706bde41d9b4738748933d64e6b37bdbffc0b47a97d16a6ae356" +"checksum phf 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)" = "cb325642290f28ee14d8c6201159949a872f220c62af6e110a56ea914fbe42fc" +"checksum phf_codegen 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)" = "d62594c0bb54c464f633175d502038177e90309daf2e0158be42ed5f023ce88f" +"checksum phf_generator 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)" = "6b07ffcc532ccc85e3afc45865469bf5d9e4ef5bfcf9622e3cfe80c2d275ec03" +"checksum phf_shared 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)" = "07e24b0ca9643bdecd0632f2b3da6b1b89bbb0030e0b992afc1113b23a7bc2f2" "checksum pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "3a8b4c6b8165cd1a1cd4b9b120978131389f64bdaf456435caa41e630edba903" "checksum podio 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e5422a1ee1bc57cc47ae717b0137314258138f38fd5f3cea083f43a9725383a0" "checksum pretty_assertions 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2412f3332a07c7a2a50168988dcc184f32180a9758ad470390e5f55e089f6b6e" "checksum primal 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0e31b86efadeaeb1235452171a66689682783149a6249ff334a2c5d8218d00a4" -"checksum primal-bit 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "464a91febc06166783d4f5ba3577b5ed8dda8e421012df80bfe48a971ed7be8f" +"checksum primal-bit 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "686a64e2f50194c64942992af5799e6b6e8775b8f88c607d72ed0a2fd58b9b21" "checksum primal-check 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "647c81b67bb9551a7b88d0bcd785ac35b7d0bf4b2f358683d7c2375d04daec51" "checksum primal-estimate 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "56ea4531dde757b56906493c8604641da14607bf9cdaa80fb9c9cabd2429f8d5" -"checksum primal-sieve 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "7aa73fd87e5984a00bdb4c1b14d3d5d6d0bad01b2caaaf924c16ab7260ac946c" +"checksum primal-sieve 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "e058e7a369c70c0103d138ef71f052a48b102592aadb8ca38ee80d85d303e1de" +"checksum protobuf 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "568a15e4d572d9a5e63ae3a55f84328c984842887db179b40b4cc6a608bac6a4" +"checksum pulldown-cmark 0.0.15 (registry+https://github.com/rust-lang/crates.io-index)" = "378e941dbd392c101f2cb88097fa4d7167bc421d4b88de3ff7dbee503bc3233b" "checksum pulldown-cmark 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8361e81576d2e02643b04950e487ec172b687180da65c731c03cf336784e6c07" "checksum quasi 0.32.0 (registry+https://github.com/rust-lang/crates.io-index)" = "18c45c4854d6d1cf5d531db97c75880feb91c958b0720f4ec1057135fec358b3" "checksum quasi_codegen 0.32.0 (registry+https://github.com/rust-lang/crates.io-index)" = "51b9e25fa23c044c1803f43ca59c98dac608976dd04ce799411edd58ece776d4" "checksum quasi_macros 0.32.0 (registry+https://github.com/rust-lang/crates.io-index)" = "29cec87bc2816766d7e4168302d505dd06b0a825aed41b00633d296e922e02dd" -"checksum quick-error 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0aad603e8d7fb67da22dbdf1f4b826ce8829e406124109e73cf1b2454b93a71c" -"checksum quine-mc_cluskey 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a6683b0e23d80813b1a535841f0048c1537d3f86d63c999e8373b39a9b0eb74a" +"checksum quick-error 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "eda5fe9b71976e62bc81b781206aaa076401769b2143379d3eb2118388babac4" +"checksum quine-mc_cluskey 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "07589615d719a60c8dd8a4622e7946465dfef20d1a428f969e3443e7386d5f45" "checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a" -"checksum rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)" = "2791d88c6defac799c3f20d74f094ca33b9332612d9aef9078519c82e4fe04a5" +"checksum rand 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)" = "eb250fd207a4729c976794d03db689c9be1d634ab5a1c9da9492a13d8fecbcdf" "checksum rayon 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a77c51c07654ddd93f6cb543c7a849863b03abc7e82591afda6dc8ad4ac3ac4a" "checksum rayon 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b614fe08b6665cb9a231d07ac1364b0ef3cb3698f1239ee0c4c3a88a524f54c8" "checksum rayon-core 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7febc28567082c345f10cddc3612c6ea020fc3297a1977d472cf9fdb73e6e493" -"checksum regex 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4278c17d0f6d62dfef0ab00028feb45bd7d2102843f80763474eeb1be8a10c01" -"checksum regex-syntax 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "841591b1e05609a643e3b4d0045fce04f701daba7151ddcd3ad47b080693d5a9" -"checksum regex-syntax 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9191b1f57603095f105d317e375d19b1c9c5c3185ea9633a99a6dcbed04457" +"checksum redox_syscall 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)" = "8dde11f18c108289bef24469638a04dce49da56084f2d50618b226e47eb04509" +"checksum regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1731164734096285ec2a5ec7fea5248ae2f5485b3feeb0115af4fda2183b2d1b" +"checksum regex-syntax 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "f9ec002c35e86791825ed294b50008eea9ddfc8def4420124fbc6b08db834957" +"checksum regex-syntax 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ad890a5eef7953f55427c50575c680c42841653abd2b028b68cd223d157f62db" "checksum reqwest 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1d56dbe269dbe19d716b76ec8c3efce8ef84e974f5b7e5527463e8c0507d4e17" -"checksum ring 0.9.5 (registry+https://github.com/rust-lang/crates.io-index)" = "873ec7c2b7c9bf58024eb8f1bbc40a6499cd23c1adc59532f4af9e355f1de0f3" +"checksum ring 0.9.7 (registry+https://github.com/rust-lang/crates.io-index)" = "24293de46bac74c9b9c05b40ff8496bbc8b9ae242a9b89f754e1154a43bc7c4c" "checksum rocksdb 0.4.5 (git+https://github.com/paritytech/rust-rocksdb)" = "" "checksum rocksdb-sys 0.3.0 (git+https://github.com/paritytech/rust-rocksdb)" = "" "checksum rotor 0.6.3 (git+https://github.com/tailhook/rotor)" = "" -"checksum rpassword 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "5d3a99497c5c544e629cc8b359ae5ede321eba5fa8e5a8078f3ced727a976c3f" -"checksum rpassword 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ab6e42be826e215f30ff830904f8f4a0933c6e2ae890e1af8b408f5bae60081e" +"checksum rpassword 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "320da1dfcf5c570a6c07ff60bb7cd4cdc986d2ea89caea139f2247371ab6a1df" +"checksum rpassword 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ec4bdede957362ec6fdd550f7e79c6d14cad2bc26b2d062786234c6ee0cb27bb" "checksum rust-crypto 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)" = "f76d05d3993fd5f4af9434e8e436db163a12a9d40e1a58a726f27a01dfd12a2a" -"checksum rustc-demangle 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "3058a43ada2c2d0b92b3ae38007a2d0fa5e9db971be260e0171408a4ff471c95" +"checksum rustc-demangle 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "aee45432acc62f7b9a108cc054142dac51f979e69e71ddce7d6fc7adf29e817e" "checksum rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0ceb8ce7a5e520de349e1fa172baeba4a9e8d5ef06c47471863530bc4972ee1e" -"checksum rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)" = "6159e4e6e559c81bd706afe9c8fd68f547d3e851ce12e76b1de7914bab61691b" +"checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda" "checksum rustc_version 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "c5f5376ea5e30ce23c03eb77cbe4962b988deead10910c372b226388b594c084" -"checksum rustc_version 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1e114e275f7c9b5d50bb52b28f9aac1921209f02aa6077c8b255e21eefaf8ffa" -"checksum schannel 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "4e45ac5e9e4698c1c138d2972bedcd90b81fe1efeba805449d2bdd54512de5f9" +"checksum rustc_version 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b9743a7670d88d5d52950408ecdb7c71d8986251ab604d4689dd2ca25c9bca69" +"checksum safemem 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e27a8b19b835f7aea908818e871f5cc3a5a186550c30773be987e155e8163d8f" +"checksum schannel 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "14a5f8491ae5fc8c51aded1f5806282a0218b4d69b1b76913a0559507e559b90" "checksum scoped-tls 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f417c22df063e9450888a7561788e9bd46d3bb3c1466435b4eccb903807f147d" "checksum scopeguard 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c79eb2c3ac4bc2507cda80e7f3ac5b88bd8eae4c0914d5663e6a8933994be918" "checksum secur32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3f412dfa83308d893101dd59c10d6fda8283465976c28c287c5c855bf8d216bc" -"checksum security-framework 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "42ddf098d78d0b64564b23ee6345d07573e7d10e52ad86875d89ddf5f8378a02" -"checksum security-framework-sys 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "5bacdada57ea62022500c457c8571c17dfb5e6240b7c8eac5916ffa8c7138a55" +"checksum security-framework 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "dfa44ee9c54ce5eecc9de7d5acbad112ee58755239381f687e564004ba4a2332" +"checksum security-framework-sys 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "5421621e836278a0b139268f36eee0dc7e389b784dc3f79d8f11aabadf41bead" "checksum semver 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)" = "d4f410fedcf71af0345d7607d246e7ad15faaadd49d240ee3b24e5dc21a820ac" "checksum semver 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2d5b7638a1f03815d94e88cb3b3c08e87f0db4d683ef499d1836aaf70a45623f" "checksum semver 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a3186ec9e65071a2095434b1f5bb24838d4e8e130f584c790f6033c79943537" "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" -"checksum serde 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)" = "6a7c6b751a2e8d5df57a5ff71b5b4fc8aaee9ee28ff1341d640dd130bb5f4f7a" -"checksum serde_derive 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)" = "2f6ca58905ebd3c3b285a8a6d4f3ac92b92c0d7951d5649b1bdd212549c06639" -"checksum serde_derive_internals 0.15.1 (registry+https://github.com/rust-lang/crates.io-index)" = "37aee4e0da52d801acfbc0cc219eb1eda7142112339726e427926a6f6ee65d3a" +"checksum serde 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)" = "bcb6a7637a47663ee073391a139ed07851f27ed2532c2abc88c6bf27a16cdf34" +"checksum serde_derive 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)" = "812ff66056fd9a9a5b7c119714243b0862cf98340e7d4b5ee05a932c40d5ea6c" +"checksum serde_derive_internals 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bd381f6d01a6616cdba8530492d453b7761b456ba974e98768a18cad2cd76f58" "checksum serde_ignored 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "190e9765dcedb56be63b6e0993a006c7e3b071a016a304736e4a315dc01fb142" -"checksum serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "48b04779552e92037212c3615370f6bd57a40ebba7f20e554ff9f55e41a69a7b" +"checksum serde_json 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d243424e06f9f9c39e3cd36147470fd340db785825e367625f79298a6ac6b7ac" "checksum serde_urlencoded 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ce0fd303af908732989354c6f02e05e2e6d597152870f2c6990efb0577137480" "checksum sha1 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cc30b1e1e8c40c121ca33b86c23308a090d19974ef001b4bf6e61fd1a0fb095c" "checksum shell32-sys 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "72f20b8f3c060374edb8046591ba28f62448c369ccbdc7b02075103fb3a9e38d" -"checksum siphasher 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5c44e42fa187b5a8782489cf7740cc27c3125806be2bf33563cf5e02e9533fcd" +"checksum siphasher 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "833011ca526bd88f16778d32c699d325a9ad302fa06381cd66f7be63351d3f6d" +"checksum siphasher 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0df90a788073e8d0235a67e50441d47db7c8ad9debd91cbf43736a2a92d36537" "checksum skeptic 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "24ebf8a06f5f8bae61ae5bbc7af7aac4ef6907ae975130faba1199e5fe82256a" "checksum slab 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6dbdd334bd28d328dad1c41b0ea662517883d8880d8533895ef96c8003dec9c4" "checksum slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "17b4fcaed89ab08ef143da37bc52adbcc04d4a69014f4c1208d6b51f0c47bc23" -"checksum smallvec 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "fcc8d19212aacecf95e4a7a2179b26f7aeb9732a915cf01f05b0d3e044865410" "checksum smallvec 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4c8cbcd6df1e117c2210e13ab5109635ad68a929fcbb8964dc965b76cb5ee013" -"checksum smallvec 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2e40af10aafe98b4d8294ae8388d8a5cd0707c65d364872efe72d063ec44bee0" -"checksum spmc 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "93bdab61c1a413e591c4d17388ffa859eaff2df27f1e13a5ec8b716700605adf" +"checksum smallvec 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8fcd03faf178110ab0334d74ca9631d77f94c8c11cc77fcb59538abf0025695d" +"checksum spmc 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "cd1f11d1fb5fd41834e55ce0b85a186efbf2f2afd9fdb09e2c8d72f9bff1ad1a" "checksum stable_deref_trait 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "15132e0e364248108c5e2c02e3ab539be8d6f5d52a01ca9bbf27ed657316f02b" "checksum strsim 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b4d15c810519a91cf877e7e36e63fe068815c678181439f2f29e2562147c3694" "checksum subtle 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b811576c12506ff3f6da145585dc833edc32ee34c9fc021127d90e8134cc05c" "checksum syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d3b891b9015c88c576343b9b3e41c2c11a51c219ef067b264bd9c8aa9b441dad" "checksum synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6" -"checksum syntex 0.58.0 (registry+https://github.com/rust-lang/crates.io-index)" = "35f3cc9d446323ef8fefad933b65cd6de271d29fa14a2e9d036a084770c6d6d5" -"checksum syntex_errors 0.58.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3af03823ea45d420dd2c1a44bb074e13ea55f9b99afe960fd58eb4069b7f6cad" -"checksum syntex_pos 0.58.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1e502a4a904d9f37cf975dbdbb0b08f2d111322f6792bda6eb095b4112c9a24b" -"checksum syntex_syntax 0.58.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6cf936464c3863952ea3fab848860ea891eba8647b6008b04c36f0bb007192a3" +"checksum syntex 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a8f5e3aaa79319573d19938ea38d068056b826db9883a5d47f86c1cecc688f0e" +"checksum syntex_errors 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)" = "867cc5c2d7140ae7eaad2ae9e8bf39cb18a67ca651b7834f88d46ca98faadb9c" +"checksum syntex_pos 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)" = "13ad4762fe52abc9f4008e85c4fb1b1fe3aa91ccb99ff4826a439c7c598e1047" +"checksum syntex_syntax 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6e0e4dbae163dd98989464c23dd503161b338790640e11537686f2ef0f25c791" "checksum take 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b157868d8ac1f56b64604539990685fa7611d8fa9e5476cf0c02cf34d32917c5" "checksum target_info 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c63f48baada5c52e65a29eef93ab4f8982681b67f9e8d29c7b05abcfec2b9ffe" "checksum tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "87974a6f5c1dfb344d733055601650059a3363de2a6104819293baff662132d6" -"checksum term 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d168af3930b369cfe245132550579d47dfd873d69470755a19c2c6568dbbd989" +"checksum term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "fa63644f74ce96fbeb9b794f66aff2a52d601cbd5e80f4b97123e3899f4570f1" "checksum term_size 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2b6b55df3198cc93372e85dd2ed817f0e38ce8cc0f22eb32391bfad9c4bf209" "checksum termios 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d5d9cf598a6d7ce700a4e6a9199da127e6819a61e64b68609683cc9a01b5683a" -"checksum thread-id 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4437c97558c70d129e40629a5b385b3fb1ffac301e63941335e4d354081ec14a" -"checksum thread_local 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c85048c6260d17cf486ceae3282d9fb6b90be220bf5b28c400f5485ffc29f0c7" -"checksum time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)" = "3c7ec6d62a20df54e07ab3b78b9a3932972f4b7981de295563686849eb3989af" +"checksum textwrap 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f728584ea33b0ad19318e20557cb0a39097751dbb07171419673502f848c7af6" +"checksum thread_local 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "1697c4b57aeeb7a536b647165a2825faddffb1d3bad386d507709bd51a90bb14" +"checksum time 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)" = "d5d788d3aa77bc0ef3e9621256885555368b47bd495c13dd2e7413c89f845520" "checksum tiny-keccak 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d52d12ad79e4063e0cb0ca5efa202ed7244b6ce4d25f4d3abe410b2a66128292" -"checksum tokio-core 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "99e958104a67877907c1454386d5482fe8e965a55d60be834a15a44328e7dc76" -"checksum tokio-io 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "48f55df1341bb92281f229a6030bc2abffde2c7a44c6d6b802b7687dd8be0775" +"checksum tokio-core 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e85d419699ec4b71bfe35bbc25bb8771e52eff0471a7f75c853ad06e200b4f86" +"checksum tokio-io 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b4ab83e7adb5677e42e405fa4ceff75659d93c4d7d7dd22f52fcec59ee9f02af" "checksum tokio-minihttp 0.1.0 (git+https://github.com/tomusdrw/tokio-minihttp)" = "" "checksum tokio-named-pipes 0.1.0 (git+https://github.com/nikvolf/tokio-named-pipes)" = "" "checksum tokio-proto 0.1.0 (git+https://github.com/tomusdrw/tokio-proto)" = "" -"checksum tokio-proto 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7c0d6031f94d78d7b4d509d4a7c5e1cdf524a17e7b08d1c188a83cf720e69808" +"checksum tokio-proto 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8fbb47ae81353c63c487030659494b295f6cb6576242f907f203473b191b0389" "checksum tokio-service 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "24da22d077e0f15f55162bdbdc661228c1581892f52074fb242678d015b45162" -"checksum tokio-timer 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "86f33def658c14724fc13ec6289b3875a8152ee8ae767a5b1ccbded363b03db8" -"checksum tokio-uds 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "bd209039933255ea77c6d7a1d18abc20b997d161acb900acca6eb74cdd049f31" -"checksum toml 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)" = "fcd27a04ca509aff336ba5eb2abc58d456f52c4ff64d9724d88acb85ead560b6" -"checksum toml 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b0601da6c97135c8d330c7a13a013ca6cd4143221b01de2f8d4edc50a9e551c7" +"checksum tokio-timer 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6131e780037787ff1b3f8aad9da83bca02438b72277850dd6ad0d455e0e20efc" +"checksum tokio-uds 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6116c71be48f8f1656551fd16458247fdd6c03201d7893ad81189055fcde03e8" +"checksum toml 0.1.30 (registry+https://github.com/rust-lang/crates.io-index)" = "0590d72182e50e879c4da3b11c6488dae18fccb1ae0c7a3eda18e16795844796" +"checksum toml 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "a7540f4ffc193e0d3c94121edb19b055670d369f77d5804db11ae053a45b6e7e" "checksum traitobject 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "efd1f82c56340fdf16f2a953d7bda4f8fdffba13d93b00844c25572110b26079" "checksum transient-hashmap 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "715254c8f0811be1a79ad3ea5e6fa3c8eddec2b03d7f5ba78cf093e56d79c24f" +"checksum trezor-sys 1.0.0 (git+https://github.com/paritytech/trezor-sys)" = "" "checksum typeable 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1410f6f91f21d1612654e7cc69193b0334f909dcf2c790c4826254fbb86f8887" -"checksum unicase 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "13a5906ca2b98c799f4b1ab4557b76367ebd6ae5ef14930ec841c74aed5f3764" -"checksum unicode-bidi 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c1f7ceb96afdfeedee42bade65a0d585a6a0106f681b6749c8ff4daa8df30b3f" -"checksum unicode-normalization 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "26643a2f83bac55f1976fb716c10234485f9202dcd65cfbdf9da49867b271172" -"checksum unicode-segmentation 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "18127285758f0e2c6cf325bb3f3d138a12fee27de4f23e146cd6a179f26c2cf3" +"checksum unicase 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7f4765f83163b74f957c797ad9253caf97f103fb064d3999aea9568d09fc8a33" +"checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5" +"checksum unicode-normalization 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "51ccda9ef9efa3f7ef5d91e8f9b83bbe6955f9bf86aec89d5cce2c874625920f" +"checksum unicode-segmentation 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a8083c594e02b8ae1654ae26f0ade5158b119bd88ad0e8227a5d8fcd72407946" "checksum unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "bf3a113775714a22dcb774d8ea3655c53a32debae63a063acc00a91cc586245f" "checksum unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc" "checksum unreachable 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1f2ae5ddb18e1c92664717616dd9549dde73f539f01bd7b77c2edb2446bdff91" -"checksum untrusted 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6b65243989ef6aacd9c0d6bd2b822765c3361d8ed352185a6f3a41f3a718c673" -"checksum url 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "afe9ec54bc4db14bc8744b7fed060d785ac756791450959b2248443319d5b119" -"checksum user32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4ef4711d107b21b410a3a974b1204d9accc8b10dad75d8324b5d755de1617d47" +"checksum unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56" +"checksum untrusted 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f392d7819dbe58833e26872f5f6f0d68b7bbbe90fc3667e98731c4a15ad9a7ae" +"checksum url 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "eeb819346883532a271eb626deb43c4a1bb4c4dd47c519bd78137c3e72a4fe27" "checksum utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "662fab6525a98beff2921d7f61a39e7d59e0b425ebc7d0d9e66d316e55124122" +"checksum vcpkg 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9e0a7d8bed3178a8fb112199d466eeca9ed09a14ba8ad67718179b4fd5487d0b" "checksum vec_map 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "887b5b631c2ad01628bbbaa7dd4c869f80d3186688f8d0b6f58774fbe324988c" "checksum vecio 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0795a11576d29ae80525a3fda315bf7b534f8feb9d34101e5fe63fb95bb2fd24" -"checksum vergen 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "56b639f935488eb40f06d17c3e3bcc3054f6f75d264e187b1107c8d1cba8d31c" +"checksum vergen 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c3365f36c57e5df714a34be40902b27a992eeddb9996eca52d0584611cf885d" +"checksum version_check 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6b772017e347561807c1aa192438c5fd74242a670a6cffacc40f2defd1dc069d" "checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" "checksum wasm-utils 0.1.0 (git+https://github.com/paritytech/wasm-utils)" = "" "checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" "checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" "checksum ws 0.7.1 (git+https://github.com/tomusdrw/ws-rs)" = "" "checksum ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e" -"checksum xdg 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "77b831a5ba77110f438f0ac5583aafeb087f70432998ba6b7dcb1d32185db453" -"checksum xml-rs 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "65e74b96bd3179209dc70a980da6df843dff09e46eee103a0376c0949257e3ef" +"checksum xdg 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a66b7c2281ebde13cf4391d70d4c7e5946c3c25e72a7b859ca8f677dcd0b0c61" +"checksum xml-rs 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7ec6c39eaa68382c8e31e35239402c0a9489d4141a8ceb0c716099a0b515b562" "checksum xmltree 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "472a9d37c7c53ab2391161df5b89b1f3bf76dab6ab150d7941ecbdd832282082" -"checksum zip 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)" = "3ceb33a75b3d0608942302eed325b59d2c3ed777cc6c01627ae14e5697c6a31c" +"checksum zip 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)" = "c0deac03fc7d43abcf19f2c2db6bd9289f9ea3d31f350e26eb0ed8b4117983c1" diff --git a/ethcore/src/account_provider/mod.rs b/ethcore/src/account_provider/mod.rs index 393236919..8e77a414f 100755 --- a/ethcore/src/account_provider/mod.rs +++ b/ethcore/src/account_provider/mod.rs @@ -31,7 +31,8 @@ use ethstore::{ use ethstore::dir::MemoryDirectory; use ethstore::ethkey::{Address, Message, Public, Secret, Random, Generator}; use ethjson::misc::AccountMeta; -use hardware_wallet::{Error as HardwareError, HardwareWalletManager, KeyPath}; +use hardware_wallet::{Error as HardwareError, HardwareWalletManager, KeyPath, TransactionInfo}; +use super::transaction::{Action, Transaction}; pub use ethstore::ethkey::Signature; pub use ethstore::{Derivation, IndexDerivation, KeyFile}; @@ -288,6 +289,24 @@ impl AccountProvider { Ok(accounts.into_iter().map(|a| a.address).collect()) } + /// Get a list of paths to locked hardware wallets + pub fn locked_hardware_accounts(&self) -> Result, SignError> { + match self.hardware_store.as_ref().map(|h| h.list_locked_wallets()) { + None => Err(SignError::NotFound), + Some(Err(e)) => Err(SignError::Hardware(e)), + Some(Ok(s)) => Ok(s), + } + } + + /// Provide a pin to a locked hardware wallet on USB path to unlock it + pub fn hardware_pin_matrix_ack(&self, path: &str, pin: &str) -> Result { + match self.hardware_store.as_ref().map(|h| h.pin_matrix_ack(path, pin)) { + None => Err(SignError::NotFound), + Some(Err(e)) => Err(SignError::Hardware(e)), + Some(Ok(s)) => Ok(s), + } + } + /// Sets addresses of accounts exposed for unknown dapps. /// `None` means that all accounts will be visible. /// If not `None` or empty it will also override default account. @@ -779,8 +798,20 @@ impl AccountProvider { } /// Sign transaction with hardware wallet. - pub fn sign_with_hardware(&self, address: Address, transaction: &[u8]) -> Result { - match self.hardware_store.as_ref().map(|s| s.sign_transaction(&address, transaction)) { + pub fn sign_with_hardware(&self, address: Address, transaction: &Transaction, chain_id: Option, rlp_encoded_transaction: &[u8]) -> Result { + let t_info = TransactionInfo { + nonce: transaction.nonce, + gas_price: transaction.gas_price, + gas_limit: transaction.gas, + to: match transaction.action { + Action::Create => None, + Action::Call(ref to) => Some(to.clone()), + }, + value: transaction.value, + data: transaction.data.to_vec(), + chain_id: chain_id, + }; + match self.hardware_store.as_ref().map(|s| s.sign_transaction(&address, &t_info, rlp_encoded_transaction)) { None | Some(Err(HardwareError::KeyNotFound)) => Err(SignError::NotFound), Some(Err(e)) => Err(From::from(e)), Some(Ok(s)) => Ok(s), diff --git a/hw/Cargo.toml b/hw/Cargo.toml index 345b1c3bb..b762d697c 100644 --- a/hw/Cargo.toml +++ b/hw/Cargo.toml @@ -9,8 +9,10 @@ authors = ["Parity Technologies "] [dependencies] log = "0.3" parking_lot = "0.4" +protobuf = "1.4" hidapi = { git = "https://github.com/paritytech/hidapi-rs" } libusb = { git = "https://github.com/paritytech/libusb-rs" } +trezor-sys = { git = "https://github.com/paritytech/trezor-sys" } ethkey = { path = "../ethkey" } ethcore-bigint = { path = "../util/bigint" } diff --git a/hw/src/ledger.rs b/hw/src/ledger.rs index 0d787588d..b7c01a049 100644 --- a/hw/src/ledger.rs +++ b/hw/src/ledger.rs @@ -17,19 +17,23 @@ //! Ledger hardware wallet module. Supports Ledger Blue and Nano S. /// See https://github.com/LedgerHQ/blue-app-eth/blob/master/doc/ethapp.asc for protocol details. -use hidapi; -use std::fmt; -use std::cmp::min; -use std::str::FromStr; -use std::time::Duration; -use super::WalletInfo; -use ethkey::{Address, Signature}; +use super::{WalletInfo, KeyPath}; + use bigint::hash::H256; +use ethkey::{Address, Signature}; +use hidapi; +use parking_lot::{Mutex, RwLock}; + +use std::cmp::min; +use std::fmt; +use std::str::FromStr; +use std::sync::Arc; +use std::time::Duration; const LEDGER_VID: u16 = 0x2c97; const LEDGER_PIDS: [u16; 2] = [0x0000, 0x0001]; // Nano S and Blue -const ETH_DERIVATION_PATH_BE: [u8; 17] = [ 4, 0x80, 0, 0, 44, 0x80, 0, 0, 60, 0x80, 0, 0, 0, 0, 0, 0, 0 ]; // 44'/60'/0'/0 -const ETC_DERIVATION_PATH_BE: [u8; 21] = [ 5, 0x80, 0, 0, 44, 0x80, 0, 0, 60, 0x80, 0x02, 0x73, 0xd0, 0x80, 0, 0, 0, 0, 0, 0, 0 ]; // 44'/60'/160720'/0'/0 +const ETH_DERIVATION_PATH_BE: [u8; 17] = [4, 0x80, 0, 0, 44, 0x80, 0, 0, 60, 0x80, 0, 0, 0, 0, 0, 0, 0]; // 44'/60'/0'/0 +const ETC_DERIVATION_PATH_BE: [u8; 21] = [5, 0x80, 0, 0, 44, 0x80, 0, 0, 60, 0x80, 0x02, 0x73, 0xd0, 0x80, 0, 0, 0, 0, 0, 0, 0]; // 44'/60'/160720'/0'/0 const APDU_TAG: u8 = 0x05; const APDU_CLA: u8 = 0xe0; @@ -43,16 +47,7 @@ mod commands { pub const SIGN_ETH_TRANSACTION: u8 = 0x04; } -/// Key derivation paths used on ledger wallets. -#[derive(Debug, Clone, Copy)] -pub enum KeyPath { - /// Ethereum. - Ethereum, - /// Ethereum classic. - EthereumClassic, -} - -/// Hardware waller error. +/// Hardware wallet error. #[derive(Debug)] pub enum Error { /// Ethereum wallet protocol error. @@ -84,9 +79,9 @@ impl From for Error { /// Ledger device manager. pub struct Manager { - usb: hidapi::HidApi, - devices: Vec, - key_path: KeyPath, + usb: Arc>, + devices: RwLock>, + key_path: RwLock, } #[derive(Debug)] @@ -97,19 +92,19 @@ struct Device { impl Manager { /// Create a new instance. - pub fn new() -> Result { - let manager = Manager { - usb: hidapi::HidApi::new()?, - devices: Vec::new(), - key_path: KeyPath::Ethereum, - }; - Ok(manager) + pub fn new(hidapi: Arc>) -> Manager { + Manager { + usb: hidapi, + devices: RwLock::new(Vec::new()), + key_path: RwLock::new(KeyPath::Ethereum), + } } /// Re-populate device list. Only those devices that have Ethereum app open will be added. - pub fn update_devices(&mut self) -> Result { - self.usb.refresh_devices(); - let devices = self.usb.devices(); + pub fn update_devices(&self) -> Result { + let mut usb = self.usb.lock(); + usb.refresh_devices(); + let devices = usb.devices(); let mut new_devices = Vec::new(); let mut num_new_devices = 0; for device in devices { @@ -117,30 +112,30 @@ impl Manager { if device.vendor_id != LEDGER_VID || !LEDGER_PIDS.contains(&device.product_id) { continue; } - match self.read_device_info(&device) { + match self.read_device_info(&usb, &device) { Ok(info) => { debug!("Found device: {:?}", info); - if !self.devices.iter().any(|d| d.path == info.path) { + if !self.devices.read().iter().any(|d| d.path == info.path) { num_new_devices += 1; } new_devices.push(info); - }, + } Err(e) => debug!("Error reading device info: {}", e), }; } - self.devices = new_devices; + *self.devices.write() = new_devices; Ok(num_new_devices) } /// Select key derivation path for a known chain. - pub fn set_key_path(&mut self, key_path: KeyPath) { - self.key_path = key_path; + pub fn set_key_path(&self, key_path: KeyPath) { + *self.key_path.write() = key_path; } - fn read_device_info(&self, dev_info: &hidapi::HidDeviceInfo) -> Result { - let mut handle = self.open_path(&dev_info.path)?; - let address = Self::read_wallet_address(&mut handle, self.key_path)?; + fn read_device_info(&self, usb: &hidapi::HidApi, dev_info: &hidapi::HidDeviceInfo) -> Result { + let mut handle = self.open_path(|| usb.open_path(&dev_info.path))?; + let address = Self::read_wallet_address(&mut handle, *self.key_path.read())?; let manufacturer = dev_info.manufacturer_string.clone().unwrap_or("Unknown".to_owned()); let name = dev_info.product_string.clone().unwrap_or("Unknown".to_owned()); let serial = dev_info.serial_number.clone().unwrap_or("Unknown".to_owned()); @@ -187,24 +182,24 @@ impl Manager { /// List connected wallets. This only returns wallets that are ready to be used. pub fn list_devices(&self) -> Vec { - self.devices.iter().map(|d| d.info.clone()).collect() + self.devices.read().iter().map(|d| d.info.clone()).collect() } /// Get wallet info. pub fn device_info(&self, address: &Address) -> Option { - self.devices.iter().find(|d| &d.info.address == address).map(|d| d.info.clone()) + self.devices.read().iter().find(|d| &d.info.address == address).map(|d| d.info.clone()) } /// Sign transaction data with wallet managing `address`. pub fn sign_transaction(&self, address: &Address, data: &[u8]) -> Result { - let device = self.devices.iter().find(|d| &d.info.address == address) - .ok_or(Error::KeyNotFound)?; - - let handle = self.open_path(&device.path)?; + let usb = self.usb.lock(); + let devices = self.devices.read(); + let device = devices.iter().find(|d| &d.info.address == address).ok_or(Error::KeyNotFound)?; + let handle = self.open_path(|| usb.open_path(&device.path))?; let eth_path = Ð_DERIVATION_PATH_BE[..]; let etc_path = &ETC_DERIVATION_PATH_BE[..]; - let derivation_path = match self.key_path { + let derivation_path = match *self.key_path.read() { KeyPath::Ethereum => eth_path, KeyPath::EthereumClassic => etc_path, }; @@ -218,7 +213,7 @@ impl Manager { let p1 = if data_pos == 0 { 0x00 } else { 0x80 }; let dest_left = MAX_CHUNK_SIZE - dest_offset; let chunk_data_size = min(dest_left, data.len() - data_pos); - &mut chunk [dest_offset..][0..chunk_data_size].copy_from_slice(&data[data_pos..][0..chunk_data_size]); + &mut chunk[dest_offset..][0..chunk_data_size].copy_from_slice(&data[data_pos..][0..chunk_data_size]); result = Self::send_apdu(&handle, commands::SIGN_ETH_TRANSACTION, p1, 0, &chunk[0..(dest_offset + chunk_data_size)])?; dest_offset = 0; data_pos += chunk_data_size; @@ -236,11 +231,13 @@ impl Manager { Ok(Signature::from_rsv(&r, &s, v)) } - fn open_path(&self, path: &str) -> Result { + fn open_path(&self, f: F) -> Result + where F: Fn() -> Result + { let mut err = Error::KeyNotFound; /// Try to open device a few times. for _ in 0..10 { - match self.usb.open_path(&path) { + match f() { Ok(handle) => return Ok(handle), Err(e) => err = From::from(e), } @@ -253,33 +250,33 @@ impl Manager { const HID_PACKET_SIZE: usize = 64 + HID_PREFIX_ZERO; let mut offset = 0; let mut chunk_index = 0; - loop { - let mut hid_chunk: [u8; HID_PACKET_SIZE] = [0; HID_PACKET_SIZE]; - let mut chunk_size = if chunk_index == 0 { 12 } else { 5 }; - let size = min(64 - chunk_size, data.len() - offset); - { - let mut chunk = &mut hid_chunk[HID_PREFIX_ZERO..]; - &mut chunk[0..5].copy_from_slice(&[0x01, 0x01, APDU_TAG, (chunk_index >> 8) as u8, (chunk_index & 0xff) as u8 ]); + loop { + let mut hid_chunk: [u8; HID_PACKET_SIZE] = [0; HID_PACKET_SIZE]; + let mut chunk_size = if chunk_index == 0 { 12 } else { 5 }; + let size = min(64 - chunk_size, data.len() - offset); + { + let mut chunk = &mut hid_chunk[HID_PREFIX_ZERO..]; + &mut chunk[0..5].copy_from_slice(&[0x01, 0x01, APDU_TAG, (chunk_index >> 8) as u8, (chunk_index & 0xff) as u8 ]); - if chunk_index == 0 { - let data_len = data.len() + 5; - &mut chunk[5..12].copy_from_slice(&[ (data_len >> 8) as u8, (data_len & 0xff) as u8, APDU_CLA, command, p1, p2, data.len() as u8 ]); - } + if chunk_index == 0 { + let data_len = data.len() + 5; + &mut chunk[5..12].copy_from_slice(&[ (data_len >> 8) as u8, (data_len & 0xff) as u8, APDU_CLA, command, p1, p2, data.len() as u8 ]); + } - &mut chunk[chunk_size..chunk_size + size].copy_from_slice(&data[offset..offset + size]); - offset += size; - chunk_size += size; - } - trace!("writing {:?}", &hid_chunk[..]); - let n = handle.write(&hid_chunk[..])?; - if n < chunk_size { - return Err(Error::Protocol("Write data size mismatch")); - } - if offset == data.len() { - break; - } - chunk_index += 1; + &mut chunk[chunk_size..chunk_size + size].copy_from_slice(&data[offset..offset + size]); + offset += size; + chunk_size += size; } + trace!("writing {:?}", &hid_chunk[..]); + let n = handle.write(&hid_chunk[..])?; + if n < chunk_size { + return Err(Error::Protocol("Write data size mismatch")); + } + if offset == data.len() { + break; + } + chunk_index += 1; + } // read response chunk_index = 0; @@ -303,7 +300,7 @@ impl Manager { if chunk_size < 7 { return Err(Error::Protocol("Unexpected chunk header")); } - message_size = (chunk[5] as usize) << 8 | (chunk[6] as usize); + message_size = (chunk[5] as usize) << 8 | (chunk[6] as usize); offset += 2; } message.extend_from_slice(&chunk[offset..chunk_size]); @@ -311,12 +308,12 @@ impl Manager { if message.len() == message_size { break; } - chunk_index +=1; + chunk_index += 1; } if message.len() < 2 { return Err(Error::Protocol("No status word")); } - let status = (message[message.len() - 2] as usize) << 8 | (message[message.len() - 1] as usize); + let status = (message[message.len() - 2] as usize) << 8 | (message[message.len() - 1] as usize); debug!("Read status {:x}", status); match status { 0x6700 => Err(Error::Protocol("Incorrect length")), @@ -341,9 +338,10 @@ impl Manager { #[test] fn smoke() { use rustc_hex::FromHex; - let mut manager = Manager::new().unwrap(); + let hidapi = Arc::new(Mutex::new(hidapi::HidApi::new().unwrap())); + let manager = Manager::new(hidapi.clone()); manager.update_devices().unwrap(); - for d in &manager.devices { + for d in &*manager.devices.read() { println!("Device: {:?}", d); } diff --git a/hw/src/lib.rs b/hw/src/lib.rs index e4b5c9f54..ef58f2d52 100644 --- a/hw/src/lib.rs +++ b/hw/src/lib.rs @@ -16,39 +16,59 @@ //! Hardware wallet management. -extern crate parking_lot; +extern crate ethcore_bigint as bigint; +extern crate ethkey; extern crate hidapi; extern crate libusb; -extern crate ethkey; -extern crate ethcore_bigint as bigint; +extern crate parking_lot; +extern crate protobuf; +extern crate trezor_sys; #[macro_use] extern crate log; #[cfg(test)] extern crate rustc_hex; mod ledger; +mod trezor; -use std::fmt; -use std::thread; -use std::sync::atomic; -use std::sync::{Arc, Weak}; -use std::sync::atomic::AtomicBool; -use std::time::Duration; -use parking_lot::Mutex; use ethkey::{Address, Signature}; -pub use ledger::KeyPath; +use parking_lot::Mutex; +use std::fmt; +use std::sync::{Arc, Weak}; +use std::sync::atomic; +use std::sync::atomic::AtomicBool; +use std::thread; +use std::time::Duration; +use bigint::prelude::uint::U256; -/// Hardware waller error. +/// Hardware wallet error. #[derive(Debug)] pub enum Error { /// Ledger device error. LedgerDevice(ledger::Error), + /// Trezor device error + TrezorDevice(trezor::Error), /// USB error. Usb(libusb::Error), + /// HID error + Hid(String), /// Hardware wallet not found for specified key. KeyNotFound, } -/// Hardware waller information. +/// This is the transaction info we need to supply to Trezor message. It's more +/// or less a duplicate of ethcore::transaction::Transaction, but we can't +/// import ethcore here as that would be a circular dependency. +pub struct TransactionInfo { + pub nonce: U256, + pub gas_price: U256, + pub gas_limit: U256, + pub to: Option
, + pub value: U256, + pub data: Vec, + pub chain_id: Option, +} + +/// Hardware wallet information. #[derive(Debug, Clone)] pub struct WalletInfo { /// Wallet device name. @@ -61,12 +81,23 @@ pub struct WalletInfo { pub address: Address, } +/// Key derivation paths used on hardware wallets. +#[derive(Debug, Clone, Copy)] +pub enum KeyPath { + /// Ethereum. + Ethereum, + /// Ethereum classic. + EthereumClassic, +} + impl fmt::Display for Error { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { Error::KeyNotFound => write!(f, "Key not found for given address."), Error::LedgerDevice(ref e) => write!(f, "{}", e), + Error::TrezorDevice(ref e) => write!(f, "{}", e), Error::Usb(ref e) => write!(f, "{}", e), + Error::Hid(ref e) => write!(f, "{}", e), } } } @@ -80,6 +111,15 @@ impl From for Error { } } +impl From for Error { + fn from(err: trezor::Error) -> Error { + match err { + trezor::Error::KeyNotFound => Error::KeyNotFound, + _ => Error::TrezorDevice(err), + } + } +} + impl From for Error { fn from(err: libusb::Error) -> Error { Error::Usb(err) @@ -90,23 +130,29 @@ impl From for Error { pub struct HardwareWalletManager { update_thread: Option>, exiting: Arc, - ledger: Arc>, + ledger: Arc, + trezor: Arc, } struct EventHandler { - ledger: Weak>, + ledger: Weak, + trezor: Weak, } impl libusb::Hotplug for EventHandler { fn device_arrived(&mut self, _device: libusb::Device) { debug!("USB Device arrived"); - if let Some(l) = self.ledger.upgrade() { + if let (Some(l), Some(t)) = (self.ledger.upgrade(), self.trezor.upgrade()) { for _ in 0..10 { - // The device might not be visible right away. Try a few times. - if l.lock().update_devices().unwrap_or_else(|e| { + let l_devices = l.update_devices().unwrap_or_else(|e| { debug!("Error enumerating Ledger devices: {}", e); 0 - }) > 0 { + }); + let t_devices = t.update_devices().unwrap_or_else(|e| { + debug!("Error enumerating Trezor devices: {}", e); + 0 + }); + if l_devices + t_devices > 0 { break; } thread::sleep(Duration::from_millis(200)); @@ -116,10 +162,9 @@ impl libusb::Hotplug for EventHandler { fn device_left(&mut self, _device: libusb::Device) { debug!("USB Device lost"); - if let Some(l) = self.ledger.upgrade() { - if let Err(e) = l.lock().update_devices() { - debug!("Error enumerating Ledger devices: {}", e); - } + if let (Some(l), Some(t)) = (self.ledger.upgrade(), self.trezor.upgrade()) { + l.update_devices().unwrap_or_else(|e| {debug!("Error enumerating Ledger devices: {}", e); 0}); + t.update_devices().unwrap_or_else(|e| {debug!("Error enumerating Trezor devices: {}", e); 0}); } } } @@ -127,47 +172,88 @@ impl libusb::Hotplug for EventHandler { impl HardwareWalletManager { pub fn new() -> Result { let usb_context = Arc::new(libusb::Context::new()?); - let ledger = Arc::new(Mutex::new(ledger::Manager::new()?)); - usb_context.register_callback(None, None, None, Box::new(EventHandler { ledger: Arc::downgrade(&ledger) }))?; + let hidapi = Arc::new(Mutex::new(hidapi::HidApi::new().map_err(|e| Error::Hid(e.to_string().clone()))?)); + let ledger = Arc::new(ledger::Manager::new(hidapi.clone())); + let trezor = Arc::new(trezor::Manager::new(hidapi.clone())); + usb_context.register_callback( + None, None, None, + Box::new(EventHandler { + ledger: Arc::downgrade(&ledger), + trezor: Arc::downgrade(&trezor), + }), + )?; let exiting = Arc::new(AtomicBool::new(false)); let thread_exiting = exiting.clone(); let l = ledger.clone(); - let thread = thread::Builder::new().name("hw_wallet".to_string()).spawn(move || { - if let Err(e) = l.lock().update_devices() { - debug!("Error updating ledger devices: {}", e); - } - loop { - usb_context.handle_events(Some(Duration::from_millis(500))).unwrap_or_else(|e| debug!("Error processing USB events: {}", e)); - if thread_exiting.load(atomic::Ordering::Acquire) { - break; + let t = trezor.clone(); + let thread = thread::Builder::new() + .name("hw_wallet".to_string()) + .spawn(move || { + if let Err(e) = l.update_devices() { + debug!("Error updating ledger devices: {}", e); } - } - }).ok(); + if let Err(e) = t.update_devices() { + debug!("Error updating trezor devices: {}", e); + } + loop { + usb_context.handle_events(Some(Duration::from_millis(500))) + .unwrap_or_else(|e| debug!("Error processing USB events: {}", e)); + if thread_exiting.load(atomic::Ordering::Acquire) { + break; + } + } + }) + .ok(); Ok(HardwareWalletManager { update_thread: thread, exiting: exiting, ledger: ledger, + trezor: trezor, }) } /// Select key derivation path for a chain. pub fn set_key_path(&self, key_path: KeyPath) { - self.ledger.lock().set_key_path(key_path); + self.ledger.set_key_path(key_path); + self.trezor.set_key_path(key_path); } /// List connected wallets. This only returns wallets that are ready to be used. pub fn list_wallets(&self) -> Vec { - self.ledger.lock().list_devices() + let mut wallets = Vec::new(); + wallets.extend(self.ledger.list_devices()); + wallets.extend(self.trezor.list_devices()); + wallets + } + + /// Return a list of paths to locked hardware wallets + pub fn list_locked_wallets(&self) -> Result, Error> { + Ok(self.trezor.list_locked_devices()) } /// Get connected wallet info. pub fn wallet_info(&self, address: &Address) -> Option { - self.ledger.lock().device_info(address) + if let Some(info) = self.ledger.device_info(address) { + Some(info) + } else { + self.trezor.device_info(address) + } } /// Sign transaction data with wallet managing `address`. - pub fn sign_transaction(&self, address: &Address, data: &[u8]) -> Result { - Ok(self.ledger.lock().sign_transaction(address, data)?) + pub fn sign_transaction(&self, address: &Address, t_info: &TransactionInfo, encoded_transaction: &[u8]) -> Result { + if self.ledger.device_info(address).is_some() { + Ok(self.ledger.sign_transaction(address, encoded_transaction)?) + } else if self.trezor.device_info(address).is_some() { + Ok(self.trezor.sign_transaction(address, t_info)?) + } else { + Err(Error::KeyNotFound) + } + } + + /// Send a pin to a device at a certain path to unlock it + pub fn pin_matrix_ack(&self, path: &str, pin: &str) -> Result { + self.trezor.pin_matrix_ack(path, pin).map_err(Error::TrezorDevice) } } diff --git a/hw/src/trezor.rs b/hw/src/trezor.rs new file mode 100644 index 000000000..a89d26f66 --- /dev/null +++ b/hw/src/trezor.rs @@ -0,0 +1,440 @@ +// Copyright 2015-2017 Parity Technologies (UK) Ltd. +// This file is part of Parity. + +// Parity is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity. If not, see . + +//! Trezor hardware wallet module. Supports Trezor v1. +//! See http://doc.satoshilabs.com/trezor-tech/api-protobuf.html +//! and https://github.com/trezor/trezor-common/blob/master/protob/protocol.md +//! for protocol details. + +use super::{WalletInfo, TransactionInfo, KeyPath}; + +use bigint::hash::H256; +use ethkey::{Address, Signature}; +use hidapi; +use parking_lot::{Mutex, RwLock}; +use protobuf; +use protobuf::{Message, ProtobufEnum}; +use std::cmp::{min, max}; +use std::fmt; +use std::sync::Arc; +use std::time::Duration; +use bigint::prelude::uint::U256; + +use trezor_sys::messages::{EthereumAddress, PinMatrixAck, MessageType, EthereumTxRequest, EthereumSignTx, EthereumGetAddress, EthereumTxAck, ButtonAck}; + +const TREZOR_VID: u16 = 0x534c; +const TREZOR_PIDS: [u16; 1] = [0x0001]; // Trezor v1, keeping this as an array to leave room for Trezor v2 which is in progress +const ETH_DERIVATION_PATH: [u32; 4] = [0x8000002C, 0x8000003C, 0x80000000, 0]; // m/44'/60'/0'/0 +const ETC_DERIVATION_PATH: [u32; 4] = [0x8000002C, 0x8000003D, 0x80000000, 0]; // m/44'/61'/0'/0 + + +/// Hardware wallet error. +#[derive(Debug)] +pub enum Error { + /// Ethereum wallet protocol error. + Protocol(&'static str), + /// Hidapi error. + Usb(hidapi::HidError), + /// Device with request key is not available. + KeyNotFound, + /// Signing has been cancelled by user. + UserCancel, + /// The Message Type given in the trezor RPC call is not something we recognize + BadMessageType, + /// Trying to read from a closed device at the given path + ClosedDevice(String), +} + +impl fmt::Display for Error { + fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { + match *self { + Error::Protocol(ref s) => write!(f, "Trezor protocol error: {}", s), + Error::Usb(ref e) => write!(f, "USB communication error: {}", e), + Error::KeyNotFound => write!(f, "Key not found"), + Error::UserCancel => write!(f, "Operation has been cancelled"), + Error::BadMessageType => write!(f, "Bad Message Type in RPC call"), + Error::ClosedDevice(ref s) => write!(f, "Device is closed, needs PIN to perform operations: {}", s), + } + } +} + +impl From for Error { + fn from(err: hidapi::HidError) -> Error { + Error::Usb(err) + } +} + +impl From for Error { + fn from(_: protobuf::ProtobufError) -> Error { + Error::Protocol(&"Could not read response from Trezor Device") + } +} + +/// Ledger device manager. +pub struct Manager { + usb: Arc>, + devices: RwLock>, + closed_devices: RwLock>, + key_path: RwLock, +} + +#[derive(Debug)] +struct Device { + path: String, + info: WalletInfo, +} + +/// HID Version used for the Trezor device +enum HidVersion { + V1, + V2, +} + +impl Manager { + /// Create a new instance. + pub fn new(hidapi: Arc>) -> Manager { + Manager { + usb: hidapi, + devices: RwLock::new(Vec::new()), + closed_devices: RwLock::new(Vec::new()), + key_path: RwLock::new(KeyPath::Ethereum), + } + } + + /// Re-populate device list + pub fn update_devices(&self) -> Result { + let mut usb = self.usb.lock(); + usb.refresh_devices(); + let devices = usb.devices(); + let mut new_devices = Vec::new(); + let mut closed_devices = Vec::new(); + let mut error = None; + for usb_device in devices { + let is_trezor = usb_device.vendor_id == TREZOR_VID; + let is_supported_product = TREZOR_PIDS.contains(&usb_device.product_id); + let is_valid = usb_device.usage_page == 0xFF00 || usb_device.interface_number == 0; + + trace!( + "Checking device: {:?}, trezor: {:?}, prod: {:?}, valid: {:?}", + usb_device, + is_trezor, + is_supported_product, + is_valid, + ); + if !is_trezor || !is_supported_product || !is_valid { + continue; + } + match self.read_device_info(&usb, &usb_device) { + Ok(device) => new_devices.push(device), + Err(Error::ClosedDevice(path)) => closed_devices.push(path.to_string()), + Err(e) => { + warn!("Error reading device: {:?}", e); + error = Some(e); + } + } + } + let count = new_devices.len(); + trace!("Got devices: {:?}, closed: {:?}", new_devices, closed_devices); + *self.devices.write() = new_devices; + *self.closed_devices.write() = closed_devices; + match error { + Some(e) => Err(e), + None => Ok(count), + } + } + + fn read_device_info(&self, usb: &hidapi::HidApi, dev_info: &hidapi::HidDeviceInfo) -> Result { + let handle = self.open_path(|| usb.open_path(&dev_info.path))?; + let manufacturer = dev_info.manufacturer_string.clone().unwrap_or("Unknown".to_owned()); + let name = dev_info.product_string.clone().unwrap_or("Unknown".to_owned()); + let serial = dev_info.serial_number.clone().unwrap_or("Unknown".to_owned()); + match self.get_address(&handle) { + Ok(Some(addr)) => { + Ok(Device { + path: dev_info.path.clone(), + info: WalletInfo { + name: name, + manufacturer: manufacturer, + serial: serial, + address: addr, + }, + }) + } + Ok(None) => Err(Error::ClosedDevice(dev_info.path.clone())), + Err(e) => Err(e), + } + } + + /// Select key derivation path for a known chain. + pub fn set_key_path(&self, key_path: KeyPath) { + *self.key_path.write() = key_path; + } + + /// List connected wallets. This only returns wallets that are ready to be used. + pub fn list_devices(&self) -> Vec { + self.devices.read().iter().map(|d| d.info.clone()).collect() + } + + pub fn list_locked_devices(&self) -> Vec { + (*self.closed_devices.read()).clone() + } + + /// Get wallet info. + pub fn device_info(&self, address: &Address) -> Option { + self.devices.read().iter().find(|d| &d.info.address == address).map(|d| d.info.clone()) + } + + fn open_path(&self, f: F) -> Result + where F: Fn() -> Result + { + let mut err = Error::KeyNotFound; + /// Try to open device a few times. + for _ in 0..10 { + match f() { + Ok(handle) => return Ok(handle), + Err(e) => err = From::from(e), + } + ::std::thread::sleep(Duration::from_millis(200)); + } + Err(err) + } + + pub fn pin_matrix_ack(&self, device_path: &str, pin: &str) -> Result { + let unlocked = { + let usb = self.usb.lock(); + let device = self.open_path(|| usb.open_path(&device_path))?; + let t = MessageType::MessageType_PinMatrixAck; + let mut m = PinMatrixAck::new(); + m.set_pin(pin.to_string()); + self.send_device_message(&device, &t, &m)?; + let (resp_type, _) = self.read_device_response(&device)?; + match resp_type { + // Getting an Address back means it's unlocked, this is undocumented behavior + MessageType::MessageType_EthereumAddress => Ok(true), + // Getting anything else means we didn't unlock it + _ => Ok(false), + + } + }; + self.update_devices()?; + unlocked + } + + fn get_address(&self, device: &hidapi::HidDevice) -> Result, Error> { + let typ = MessageType::MessageType_EthereumGetAddress; + let mut message = EthereumGetAddress::new(); + match *self.key_path.read() { + KeyPath::Ethereum => message.set_address_n(ETH_DERIVATION_PATH.to_vec()), + KeyPath::EthereumClassic => message.set_address_n(ETC_DERIVATION_PATH.to_vec()), + } + message.set_show_display(false); + self.send_device_message(&device, &typ, &message)?; + + let (resp_type, bytes) = self.read_device_response(&device)?; + match resp_type { + MessageType::MessageType_EthereumAddress => { + let response: EthereumAddress = protobuf::core::parse_from_bytes(&bytes)?; + Ok(Some(From::from(response.get_address()))) + } + _ => Ok(None), + } + } + + /// Sign transaction data with wallet managing `address`. + pub fn sign_transaction(&self, address: &Address, t_info: &TransactionInfo) -> Result { + let usb = self.usb.lock(); + let devices = self.devices.read(); + let device = devices.iter().find(|d| &d.info.address == address).ok_or(Error::KeyNotFound)?; + let handle = self.open_path(|| usb.open_path(&device.path))?; + let msg_type = MessageType::MessageType_EthereumSignTx; + let mut message = EthereumSignTx::new(); + match *self.key_path.read() { + KeyPath::Ethereum => message.set_address_n(ETH_DERIVATION_PATH.to_vec()), + KeyPath::EthereumClassic => message.set_address_n(ETC_DERIVATION_PATH.to_vec()), + } + message.set_nonce(self.u256_to_be_vec(&t_info.nonce)); + message.set_gas_limit(self.u256_to_be_vec(&t_info.gas_limit)); + message.set_gas_price(self.u256_to_be_vec(&t_info.gas_price)); + message.set_value(self.u256_to_be_vec(&t_info.value)); + + match t_info.to { + Some(addr) => { + message.set_to(addr.to_vec()) + } + None => (), + } + let first_chunk_length = min(t_info.data.len(), 1024); + let chunk = &t_info.data[0..first_chunk_length]; + message.set_data_initial_chunk(chunk.to_vec()); + message.set_data_length(t_info.data.len() as u32); + if let Some(c_id) = t_info.chain_id { + message.set_chain_id(c_id as u32); + } + + self.send_device_message(&handle, &msg_type, &message)?; + + self.signing_loop(&handle, &t_info.chain_id, &t_info.data[first_chunk_length..]) + } + + fn u256_to_be_vec(&self, val: &U256) -> Vec { + let mut buf = [0u8; 32]; + val.to_big_endian(&mut buf); + buf.iter().skip_while(|x| **x == 0).cloned().collect() + } + + fn signing_loop(&self, handle: &hidapi::HidDevice, chain_id: &Option, data: &[u8]) -> Result { + let (resp_type, bytes) = self.read_device_response(&handle)?; + match resp_type { + MessageType::MessageType_Cancel => Err(Error::UserCancel), + MessageType::MessageType_ButtonRequest => { + self.send_device_message(handle, &MessageType::MessageType_ButtonAck, &ButtonAck::new())?; + // Signing loop goes back to the top and reading blocks + // for up to 5 minutes waiting for response from the device + // if the user doesn't click any button within 5 minutes you + // get a signing error and the device sort of locks up on the signing screen + self.signing_loop(handle, chain_id, data) + } + MessageType::MessageType_EthereumTxRequest => { + let resp: EthereumTxRequest = protobuf::core::parse_from_bytes(&bytes)?; + if resp.has_data_length() { + let mut msg = EthereumTxAck::new(); + let len = resp.get_data_length() as usize; + msg.set_data_chunk(data[..len].to_vec()); + self.send_device_message(handle, &MessageType::MessageType_EthereumTxAck, &msg)?; + self.signing_loop(handle, chain_id, &data[len..]) + } else { + let v = resp.get_signature_v(); + let r = H256::from_slice(resp.get_signature_r()); + let s = H256::from_slice(resp.get_signature_s()); + if let Some(c_id) = *chain_id { + // If there is a chain_id supplied, Trezor will return a v + // part of the signature that is already adjusted for EIP-155, + // so v' = v + 2 * chain_id + 35, but code further down the + // pipeline will already do this transformation, so remove it here + let adjustment = 35 + 2 * c_id as u32; + Ok(Signature::from_rsv(&r, &s, (max(v, adjustment) - adjustment) as u8)) + } else { + // If there isn't a chain_id, v will be returned as v + 27 + let adjusted_v = if v < 27 { v } else { v - 27 }; + Ok(Signature::from_rsv(&r, &s, adjusted_v as u8)) + } + } + } + MessageType::MessageType_Failure => Err(Error::Protocol("Last message sent to Trezor failed")), + _ => Err(Error::Protocol("Unexpected response from Trezor device.")), + } + } + + fn send_device_message(&self, device: &hidapi::HidDevice, msg_type: &MessageType, msg: &Message) -> Result { + let msg_id = *msg_type as u16; + let mut message = msg.write_to_bytes()?; + let msg_size = message.len(); + let mut data = Vec::new(); + let hid_version = self.probe_hid_version(device)?; + // Magic constants + data.push('#' as u8); + data.push('#' as u8); + // Convert msg_id to BE and split into bytes + data.push(((msg_id >> 8) & 0xFF) as u8); + data.push((msg_id & 0xFF) as u8); + // Convert msg_size to BE and split into bytes + data.push(((msg_size >> 24) & 0xFF) as u8); + data.push(((msg_size >> 16) & 0xFF) as u8); + data.push(((msg_size >> 8) & 0xFF) as u8); + data.push((msg_size & 0xFF) as u8); + data.append(&mut message); + while data.len() % 63 > 0 { + data.push(0); + } + let mut total_written = 0; + for chunk in data.chunks(63) { + let mut padded_chunk = match hid_version { + HidVersion::V1 => vec!['?' as u8], + HidVersion::V2 => vec![0, '?' as u8], + }; + padded_chunk.extend_from_slice(&chunk); + total_written += device.write(&padded_chunk)?; + } + Ok(total_written) + } + + fn probe_hid_version(&self, device: &hidapi::HidDevice) -> Result { + let mut buf2 = [0xFFu8; 65]; + buf2[0] = 0; + buf2[1] = 63; + let mut buf1 = [0xFFu8; 64]; + buf1[0] = 63; + if device.write(&buf2)? == 65 { + Ok(HidVersion::V2) + } else if device.write(&buf1)? == 64 { + Ok(HidVersion::V1) + } else { + Err(Error::Usb("Unable to determine HID Version")) + } + } + + fn read_device_response(&self, device: &hidapi::HidDevice) -> Result<(MessageType, Vec), Error> { + let protocol_err = Error::Protocol(&"Unexpected wire response from Trezor Device"); + let mut buf = vec![0; 64]; + + let first_chunk = device.read_timeout(&mut buf, 300_000)?; + if first_chunk < 9 || buf[0] != '?' as u8 || buf[1] != '#' as u8 || buf[2] != '#' as u8 { + return Err(protocol_err); + } + let msg_type = MessageType::from_i32(((buf[3] as i32 & 0xFF) << 8) + (buf[4] as i32 & 0xFF)).ok_or(protocol_err)?; + let msg_size = ((buf[5] as u32 & 0xFF) << 24) + ((buf[6] as u32 & 0xFF) << 16) + ((buf[7] as u32 & 0xFF) << 8) + (buf[8] as u32 & 0xFF); + let mut data = Vec::new(); + data.extend_from_slice(&buf[9..]); + while data.len() < (msg_size as usize) { + device.read_timeout(&mut buf, 10_000)?; + data.extend_from_slice(&buf[1..]); + } + Ok((msg_type, data[..msg_size as usize].to_vec())) + } +} + +#[test] +#[ignore] +/// This test can't be run without an actual trezor device connected +/// (and unlocked) attached to the machine that's running the test +fn test_signature() { + use bigint::prelude::uint::U256; + use bigint::hash::{H160, H256}; + + let hidapi = Arc::new(Mutex::new(hidapi::HidApi::new().unwrap())); + let manager = Manager::new(hidapi.clone()); + let addr: Address = H160::from("some_addr"); + + manager.update_devices().unwrap(); + + let t_info = TransactionInfo { + nonce: U256::from(1), + gas_price: U256::from(100), + gas_limit: U256::from(21_000), + to: Some(H160::from("some_other_addr")), + chain_id: Some(17), + value: U256::from(1_000_000), + data: (&[1u8; 3000]).to_vec(), + }; + let signature = manager.sign_transaction(&addr, &t_info).unwrap(); + let expected = Signature::from_rsv( + &H256::from("device_specific_r"), + &H256::from("device_specific_s"), + 0x01 + ); + + assert_eq!(signature, expected) +} diff --git a/js/package-lock.json b/js/package-lock.json index 7b705b03f..e50b8e197 100644 --- a/js/package-lock.json +++ b/js/package-lock.json @@ -418,7 +418,7 @@ "glob": { "version": "7.1.2", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "integrity": "sha1-wZyd+aAocC1nhhI4SmVSQExjbRU=", "dev": true, "requires": { "fs.realpath": "1.0.0", @@ -706,7 +706,7 @@ "glob": { "version": "7.1.2", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "integrity": "sha1-wZyd+aAocC1nhhI4SmVSQExjbRU=", "dev": true, "requires": { "fs.realpath": "1.0.0", @@ -2176,6 +2176,7 @@ "requires": { "anymatch": "1.3.2", "async-each": "1.0.1", + "fsevents": "1.1.2", "glob-parent": "2.0.0", "inherits": "2.0.3", "is-binary-path": "1.0.1", @@ -4130,7 +4131,7 @@ "glob": { "version": "7.1.2", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "integrity": "sha1-wZyd+aAocC1nhhI4SmVSQExjbRU=", "dev": true, "requires": { "fs.realpath": "1.0.0", @@ -4968,6 +4969,905 @@ "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" }, + "fsevents": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.1.2.tgz", + "integrity": "sha512-Sn44E5wQW4bTHXvQmvSHwqbuiXtduD6Rrjm2ZtUEGbyrig+nUH3t/QD4M4/ZXViY556TBpRgZkHLDx3JxPwxiw==", + "dev": true, + "optional": true, + "requires": { + "nan": "2.6.2", + "node-pre-gyp": "0.6.36" + }, + "dependencies": { + "abbrev": { + "version": "1.1.0", + "bundled": true, + "dev": true, + "optional": true + }, + "ajv": { + "version": "4.11.8", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "co": "4.6.0", + "json-stable-stringify": "1.0.1" + } + }, + "ansi-regex": { + "version": "2.1.1", + "bundled": true, + "dev": true + }, + "aproba": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "are-we-there-yet": { + "version": "1.1.4", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "delegates": "1.0.0", + "readable-stream": "2.2.9" + } + }, + "asn1": { + "version": "0.2.3", + "bundled": true, + "dev": true, + "optional": true + }, + "assert-plus": { + "version": "0.2.0", + "bundled": true, + "dev": true, + "optional": true + }, + "asynckit": { + "version": "0.4.0", + "bundled": true, + "dev": true, + "optional": true + }, + "aws-sign2": { + "version": "0.6.0", + "bundled": true, + "dev": true, + "optional": true + }, + "aws4": { + "version": "1.6.0", + "bundled": true, + "dev": true, + "optional": true + }, + "balanced-match": { + "version": "0.4.2", + "bundled": true, + "dev": true + }, + "bcrypt-pbkdf": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "tweetnacl": "0.14.5" + } + }, + "block-stream": { + "version": "0.0.9", + "bundled": true, + "dev": true, + "requires": { + "inherits": "2.0.3" + } + }, + "boom": { + "version": "2.10.1", + "bundled": true, + "dev": true, + "requires": { + "hoek": "2.16.3" + } + }, + "brace-expansion": { + "version": "1.1.7", + "bundled": true, + "dev": true, + "requires": { + "balanced-match": "0.4.2", + "concat-map": "0.0.1" + } + }, + "buffer-shims": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "caseless": { + "version": "0.12.0", + "bundled": true, + "dev": true, + "optional": true + }, + "co": { + "version": "4.6.0", + "bundled": true, + "dev": true, + "optional": true + }, + "code-point-at": { + "version": "1.1.0", + "bundled": true, + "dev": true + }, + "combined-stream": { + "version": "1.0.5", + "bundled": true, + "dev": true, + "requires": { + "delayed-stream": "1.0.0" + } + }, + "concat-map": { + "version": "0.0.1", + "bundled": true, + "dev": true + }, + "console-control-strings": { + "version": "1.1.0", + "bundled": true, + "dev": true + }, + "core-util-is": { + "version": "1.0.2", + "bundled": true, + "dev": true + }, + "cryptiles": { + "version": "2.0.5", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "boom": "2.10.1" + } + }, + "dashdash": { + "version": "1.14.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "assert-plus": "1.0.0" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + } + } + }, + "debug": { + "version": "2.6.8", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "ms": "2.0.0" + } + }, + "deep-extend": { + "version": "0.4.2", + "bundled": true, + "dev": true, + "optional": true + }, + "delayed-stream": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "delegates": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "ecc-jsbn": { + "version": "0.1.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "jsbn": "0.1.1" + } + }, + "extend": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "extsprintf": { + "version": "1.0.2", + "bundled": true, + "dev": true + }, + "forever-agent": { + "version": "0.6.1", + "bundled": true, + "dev": true, + "optional": true + }, + "form-data": { + "version": "2.1.4", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "asynckit": "0.4.0", + "combined-stream": "1.0.5", + "mime-types": "2.1.15" + } + }, + "fs.realpath": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "fstream": { + "version": "1.0.11", + "bundled": true, + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "inherits": "2.0.3", + "mkdirp": "0.5.1", + "rimraf": "2.6.1" + } + }, + "fstream-ignore": { + "version": "1.0.5", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "fstream": "1.0.11", + "inherits": "2.0.3", + "minimatch": "3.0.4" + } + }, + "gauge": { + "version": "2.7.4", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "aproba": "1.1.1", + "console-control-strings": "1.1.0", + "has-unicode": "2.0.1", + "object-assign": "4.1.1", + "signal-exit": "3.0.2", + "string-width": "1.0.2", + "strip-ansi": "3.0.1", + "wide-align": "1.1.2" + } + }, + "getpass": { + "version": "0.1.7", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "assert-plus": "1.0.0" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + } + } + }, + "glob": { + "version": "7.1.2", + "bundled": true, + "dev": true, + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, + "graceful-fs": { + "version": "4.1.11", + "bundled": true, + "dev": true + }, + "har-schema": { + "version": "1.0.5", + "bundled": true, + "dev": true, + "optional": true + }, + "har-validator": { + "version": "4.2.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "ajv": "4.11.8", + "har-schema": "1.0.5" + } + }, + "has-unicode": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "hawk": { + "version": "3.1.3", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "boom": "2.10.1", + "cryptiles": "2.0.5", + "hoek": "2.16.3", + "sntp": "1.0.9" + } + }, + "hoek": { + "version": "2.16.3", + "bundled": true, + "dev": true + }, + "http-signature": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "assert-plus": "0.2.0", + "jsprim": "1.4.0", + "sshpk": "1.13.0" + } + }, + "inflight": { + "version": "1.0.6", + "bundled": true, + "dev": true, + "requires": { + "once": "1.4.0", + "wrappy": "1.0.2" + } + }, + "inherits": { + "version": "2.0.3", + "bundled": true, + "dev": true + }, + "ini": { + "version": "1.3.4", + "bundled": true, + "dev": true, + "optional": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "requires": { + "number-is-nan": "1.0.1" + } + }, + "is-typedarray": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "isarray": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "isstream": { + "version": "0.1.2", + "bundled": true, + "dev": true, + "optional": true + }, + "jodid25519": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "jsbn": "0.1.1" + } + }, + "jsbn": { + "version": "0.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "json-schema": { + "version": "0.2.3", + "bundled": true, + "dev": true, + "optional": true + }, + "json-stable-stringify": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "jsonify": "0.0.0" + } + }, + "json-stringify-safe": { + "version": "5.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "jsonify": { + "version": "0.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "jsprim": { + "version": "1.4.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.0.2", + "json-schema": "0.2.3", + "verror": "1.3.6" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + } + } + }, + "mime-db": { + "version": "1.27.0", + "bundled": true, + "dev": true + }, + "mime-types": { + "version": "2.1.15", + "bundled": true, + "dev": true, + "requires": { + "mime-db": "1.27.0" + } + }, + "minimatch": { + "version": "3.0.4", + "bundled": true, + "dev": true, + "requires": { + "brace-expansion": "1.1.7" + } + }, + "minimist": { + "version": "0.0.8", + "bundled": true, + "dev": true + }, + "mkdirp": { + "version": "0.5.1", + "bundled": true, + "dev": true, + "requires": { + "minimist": "0.0.8" + } + }, + "ms": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "node-pre-gyp": { + "version": "0.6.36", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "mkdirp": "0.5.1", + "nopt": "4.0.1", + "npmlog": "4.1.0", + "rc": "1.2.1", + "request": "2.81.0", + "rimraf": "2.6.1", + "semver": "5.3.0", + "tar": "2.2.1", + "tar-pack": "3.4.0" + } + }, + "nopt": { + "version": "4.0.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "abbrev": "1.1.0", + "osenv": "0.1.4" + } + }, + "npmlog": { + "version": "4.1.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "are-we-there-yet": "1.1.4", + "console-control-strings": "1.1.0", + "gauge": "2.7.4", + "set-blocking": "2.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "bundled": true, + "dev": true + }, + "oauth-sign": { + "version": "0.8.2", + "bundled": true, + "dev": true, + "optional": true + }, + "object-assign": { + "version": "4.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "once": { + "version": "1.4.0", + "bundled": true, + "dev": true, + "requires": { + "wrappy": "1.0.2" + } + }, + "os-homedir": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "os-tmpdir": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "osenv": { + "version": "0.1.4", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "os-homedir": "1.0.2", + "os-tmpdir": "1.0.2" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "bundled": true, + "dev": true + }, + "performance-now": { + "version": "0.2.0", + "bundled": true, + "dev": true, + "optional": true + }, + "process-nextick-args": { + "version": "1.0.7", + "bundled": true, + "dev": true + }, + "punycode": { + "version": "1.4.1", + "bundled": true, + "dev": true, + "optional": true + }, + "qs": { + "version": "6.4.0", + "bundled": true, + "dev": true, + "optional": true + }, + "rc": { + "version": "1.2.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "deep-extend": "0.4.2", + "ini": "1.3.4", + "minimist": "1.2.0", + "strip-json-comments": "2.0.1" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "bundled": true, + "dev": true, + "optional": true + } + } + }, + "readable-stream": { + "version": "2.2.9", + "bundled": true, + "dev": true, + "requires": { + "buffer-shims": "1.0.0", + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "1.0.7", + "string_decoder": "1.0.1", + "util-deprecate": "1.0.2" + } + }, + "request": { + "version": "2.81.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "aws-sign2": "0.6.0", + "aws4": "1.6.0", + "caseless": "0.12.0", + "combined-stream": "1.0.5", + "extend": "3.0.1", + "forever-agent": "0.6.1", + "form-data": "2.1.4", + "har-validator": "4.2.1", + "hawk": "3.1.3", + "http-signature": "1.1.1", + "is-typedarray": "1.0.0", + "isstream": "0.1.2", + "json-stringify-safe": "5.0.1", + "mime-types": "2.1.15", + "oauth-sign": "0.8.2", + "performance-now": "0.2.0", + "qs": "6.4.0", + "safe-buffer": "5.0.1", + "stringstream": "0.0.5", + "tough-cookie": "2.3.2", + "tunnel-agent": "0.6.0", + "uuid": "3.0.1" + } + }, + "rimraf": { + "version": "2.6.1", + "bundled": true, + "dev": true, + "requires": { + "glob": "7.1.2" + } + }, + "safe-buffer": { + "version": "5.0.1", + "bundled": true, + "dev": true + }, + "semver": { + "version": "5.3.0", + "bundled": true, + "dev": true, + "optional": true + }, + "set-blocking": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "signal-exit": { + "version": "3.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "sntp": { + "version": "1.0.9", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "hoek": "2.16.3" + } + }, + "sshpk": { + "version": "1.13.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "asn1": "0.2.3", + "assert-plus": "1.0.0", + "bcrypt-pbkdf": "1.0.1", + "dashdash": "1.14.1", + "ecc-jsbn": "0.1.1", + "getpass": "0.1.7", + "jodid25519": "1.0.2", + "jsbn": "0.1.1", + "tweetnacl": "0.14.5" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + } + } + }, + "string_decoder": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "requires": { + "safe-buffer": "5.0.1" + } + }, + "string-width": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "requires": { + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" + } + }, + "stringstream": { + "version": "0.0.5", + "bundled": true, + "dev": true, + "optional": true + }, + "strip-ansi": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "requires": { + "ansi-regex": "2.1.1" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "tar": { + "version": "2.2.1", + "bundled": true, + "dev": true, + "requires": { + "block-stream": "0.0.9", + "fstream": "1.0.11", + "inherits": "2.0.3" + } + }, + "tar-pack": { + "version": "3.4.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "debug": "2.6.8", + "fstream": "1.0.11", + "fstream-ignore": "1.0.5", + "once": "1.4.0", + "readable-stream": "2.2.9", + "rimraf": "2.6.1", + "tar": "2.2.1", + "uid-number": "0.0.6" + } + }, + "tough-cookie": { + "version": "2.3.2", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "punycode": "1.4.1" + } + }, + "tunnel-agent": { + "version": "0.6.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "safe-buffer": "5.0.1" + } + }, + "tweetnacl": { + "version": "0.14.5", + "bundled": true, + "dev": true, + "optional": true + }, + "uid-number": { + "version": "0.0.6", + "bundled": true, + "dev": true, + "optional": true + }, + "util-deprecate": { + "version": "1.0.2", + "bundled": true, + "dev": true + }, + "uuid": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "verror": { + "version": "1.3.6", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "extsprintf": "1.0.2" + } + }, + "wide-align": { + "version": "1.1.2", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "string-width": "1.0.2" + } + }, + "wrappy": { + "version": "1.0.2", + "bundled": true, + "dev": true + } + } + }, "fstream": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.11.tgz", @@ -7722,7 +8622,7 @@ "minimatch": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "integrity": "sha1-UWbihkV/AzBgZL5Ul+jbsMPTIIM=", "requires": { "brace-expansion": "1.1.8" } @@ -10081,7 +10981,7 @@ "react-qr-reader": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/react-qr-reader/-/react-qr-reader-1.1.3.tgz", - "integrity": "sha512-ruBF8KaSwUW9nbzjO4rA7/HOCGYZuNUz9od7uBRy8SRBi24nwxWWmwa2z8R6vPGDRglA0y2Qk1aVBuC1olTnHw==", + "integrity": "sha1-dDmnZvyZPLj17u/HLCnblh1AswI=", "requires": { "jsqr": "git+https://github.com/JodusNodus/jsQR.git#5ba1acefa1cbb9b2bc92b49f503f2674e2ec212b", "prop-types": "15.5.10", @@ -11654,7 +12554,7 @@ "string-width": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "integrity": "sha1-q5Pyeo3BPSjKyBXEYhQ6bZASrp4=", "dev": true, "requires": { "is-fullwidth-code-point": "2.0.0", @@ -12611,7 +13511,7 @@ "async": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/async/-/async-2.5.0.tgz", - "integrity": "sha512-e+lJAJeNWuPCNyxZKOBdaJGyLGHugXVQtrAwtuAe2vhxTYxFTKE73p8JuTmdH0qdQZtDvI4dhJwjZc5zsfIsYw==", + "integrity": "sha1-hDGQ/WtzV6C54clW7d3V7IRitU0=", "dev": true, "requires": { "lodash": "4.17.2" @@ -13016,7 +13916,7 @@ "commander": { "version": "2.11.0", "resolved": "https://registry.npmjs.org/commander/-/commander-2.11.0.tgz", - "integrity": "sha512-b0553uYA5YAEGgyYIGYROzKQ7X5RAqedkfjiZxwi0kL1g3bOaBNNZfYkzt/CL0umgD5wc9Jec2FbB98CjkMRvQ==" + "integrity": "sha1-FXFS/R56bI2YpbcVzzdt+SgARWM=" }, "detect-indent": { "version": "5.0.0", diff --git a/js/src/api/rpc/parity/parity.js b/js/src/api/rpc/parity/parity.js index 3a502afab..ece76f8b6 100644 --- a/js/src/api/rpc/parity/parity.js +++ b/js/src/api/rpc/parity/parity.js @@ -252,6 +252,16 @@ export default class Parity { .then(outHwAccountInfo); } + lockedHardwareAccountsInfo () { + return this._transport + .execute('parity_lockedHardwareAccountsInfo'); + } + + hardwarePinMatrixAck (path, pin) { + return this._transport + .execute('parity_hardwarePinMatrixAck', path, pin); + } + hashContent (url) { return this._transport .execute('parity_hashContent', url); diff --git a/js/src/jsonrpc/interfaces/parity.js b/js/src/jsonrpc/interfaces/parity.js index a1e6246e4..b1e568d5f 100644 --- a/js/src/jsonrpc/interfaces/parity.js +++ b/js/src/jsonrpc/interfaces/parity.js @@ -360,6 +360,37 @@ export default { } }, + lockedHardwareAccountsInfo: { + desc: 'Provides a list of paths to locked hardware wallets', + params: [], + returns: { + type: Array, + desc: 'Paths of all locked hardware wallets', + example: "['/dev/hidraw0']" + } + }, + + hardwarePinMatrixAck: { + desc: 'Send a pin to a hardware wallet at a specific path to unlock it', + params: [ + { + type: String, + desc: 'path to the device', + example: 'USB_2b24_0001_14100000' + }, + { + type: String, + desc: 'the pin as recieved from the pin matrix', + example: '1234' + } + ], + returns: { + type: Boolean, + desc: 'Whether or not the pin entry successfully unlocked the device', + example: true + } + }, + listOpenedVaults: { desc: 'Returns a list of all opened vaults', params: [], diff --git a/js/src/mobx/hardwareStore.js b/js/src/mobx/hardwareStore.js index 5a3960c2f..405853f5a 100644 --- a/js/src/mobx/hardwareStore.js +++ b/js/src/mobx/hardwareStore.js @@ -24,11 +24,14 @@ let instance = null; export default class HardwareStore { @observable isScanning = false; @observable wallets = {}; + @observable pinMatrixRequest = []; constructor (api) { this._api = api; this._ledger = Ledger.create(api); this._pollId = null; + this.hwAccounts = {}; + this.ledgerAccounts = {}; this._pollScan(); this._subscribeParity(); @@ -49,12 +52,31 @@ export default class HardwareStore { this.wallets = wallets; } + @action setPinMatrixRequest = (requests) => { + this.pinMatrixRequest = requests; + } + _pollScan = () => { this._pollId = setTimeout(() => { this.scan().then(this._pollScan); }, HW_SCAN_INTERVAL); } + scanTrezor () { + return this._api.parity + .lockedHardwareAccountsInfo() + .then((paths) => { + this.setPinMatrixRequest(paths.map((path) => { + return { path: path, manufacturer: 'Trezor' }; + })); + return {}; + }) + .catch((err) => { + console.warn('HardwareStore::scanTrezor', err); + return {}; + }); + } + scanLedger () { if (!this._ledger.isSupported) { return Promise.resolve({}); @@ -101,7 +123,8 @@ export default class HardwareStore { info.address = address; info.via = 'parity'; }); - this.setWallets(hwInfo); + this.hwAccounts = hwInfo; + this.updateWallets(); return hwInfo; }, onError @@ -110,6 +133,9 @@ export default class HardwareStore { scan () { this.setScanning(true); + // This only scans for locked devices and does not return open devices, + // so no need to actually wait for any results here. + this.scanTrezor(); // NOTE: Depending on how the hardware is configured and how the local env setup // is done, different results will be retrieved via Parity vs. the browser APIs @@ -117,13 +143,18 @@ export default class HardwareStore { // not intended as a network call, i.e. hw wallet is with the user) return this.scanLedger() .then((ledgerAccounts) => { + this.ledgerAccounts = ledgerAccounts; transaction(() => { - this.setWallets(Object.assign({}, ledgerAccounts)); + this.updateWallets(); this.setScanning(false); }); }); } + updateWallets () { + this.setWallets(Object.assign({}, this.hwAccounts, this.ledgerAccounts)); + } + createAccountInfo (entry, original = {}) { const { address, manufacturer, name } = entry; @@ -151,6 +182,15 @@ export default class HardwareStore { return this._ledger.signTransaction(transaction); } + pinMatrixAck (device, passcode) { + return this._api.parity + .hardwarePinMatrixAck(device.path, passcode) + .then((success) => { + this.scan(); + return success; + }); + } + static get (api) { if (!instance) { instance = new HardwareStore(api); diff --git a/js/src/modals/PinMatrix/index.js b/js/src/modals/PinMatrix/index.js new file mode 100644 index 000000000..fc4ae0a14 --- /dev/null +++ b/js/src/modals/PinMatrix/index.js @@ -0,0 +1,17 @@ +// Copyright 2015-2017 Parity Technologies (UK) Ltd. +// This file is part of Parity. + +// Parity is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity. If not, see . + +export default from './pinMatrix'; diff --git a/js/src/modals/PinMatrix/pinMatrix.css b/js/src/modals/PinMatrix/pinMatrix.css new file mode 100644 index 000000000..cc0d82c19 --- /dev/null +++ b/js/src/modals/PinMatrix/pinMatrix.css @@ -0,0 +1,142 @@ +/* Copyright 2015-2017 Parity Technologies (UK) Ltd. +/* This file is part of Parity. +/* +/* Parity is free software: you can redistribute it and/or modify +/* it under the terms of the GNU General Public License as published by +/* the Free Software Foundation, either version 3 of the License, or +/* (at your option) any later version. +/* +/* Parity is distributed in the hope that it will be useful, +/* but WITHOUT ANY WARRANTY; without even the implied warranty of +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +/* GNU General Public License for more details. +/* +/* You should have received a copy of the GNU General Public License +/* along with Parity. If not, see . +*/ + +.overlay { + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + background: rgba(255, 255, 255, 0.75); + z-index: 20000; +} + +.body { + margin: 0 auto; + padding: 2em 4em; + text-align: center; + max-width: 30em; + min-height: 200px; + background: rgba(25, 25, 25, 0.75); + color: rgb(208, 208, 208); + box-shadow: rgba(0, 0, 0, 0.25) 0px 14px 45px, rgba(0, 0, 0, 0.22) 0px 10px 18px; +} + +.passcodeBoxes { + display: flex; + flex-flow: row wrap; + justify-content: center; + width: 100px; + padding: 20px 0; + margin: auto; +} + +.passcodeBox { + position: relative; + width: 25px; + height: 25px; + line-height: 25px; + margin: 2px; + background-color: rgba(0, 0, 0, 0.5); + transition: background-color 400ms; + cursor: pointer; + border: none; + outline: none; + + &:hover { + background-color: rgba(0, 0, 0, 0.25); + } +} + +.passcodeBall { + position: absolute; + width: 3px; + height: 3px; + border-radius: 100%; + background-color: rgba(208, 208, 208, 0.5); + left: 50%; + top: 50%; + transform: translate(-50%, -50%); +} + +.pin { + margin-left: 2px; + min-height: 20px; + position: relative; + letter-spacing: 2px; +} + +.clearThik { + color: rgba(0, 0, 0, 0.5); + font: 14px/100% arial, sans-serif; + position: absolute; + right: 150px; + text-decoration: none; + top: -5px; + border: solid 3px rgba(0, 0, 0, 0.5); + width: 18px; + height: 18px; + border-bottom-right-radius: 3px; + border-top-right-radius: 3px; + position: absolute; + line-height: 20px; + cursor: pointer; + + &:after { + right: 100%; + top: 50%; + border: solid transparent; + content: " "; + height: 0; + width: 0; + position: absolute; + pointer-events: none; + border-right-color: rgba(0, 0, 0, 0.5); + border-width: 12px; + margin-top: -12px; + margin-right: 3px; + } + + &:before { + content: '\2716'; + padding-left: 2px; + } +} + +.button { + padding: 7px; + background-color: rgba(0, 0, 0, 0.5); + border-radius: 3px; + cursor: pointer; + + &:hover { + background-color: rgba(0, 0, 0, 0.25); + } +} + +.cancel { + float: left; +} + +.submit { + float: right; +} + +.error { + color: rgba(218, 39, 39, 0.85); + padding-top: 7px; +} diff --git a/js/src/modals/PinMatrix/pinMatrix.js b/js/src/modals/PinMatrix/pinMatrix.js new file mode 100644 index 000000000..13c463ae9 --- /dev/null +++ b/js/src/modals/PinMatrix/pinMatrix.js @@ -0,0 +1,132 @@ +// Copyright 2015-2017 Parity Technologies (UK) Ltd. +// This file is part of Parity. + +// Parity is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity. If not, see . + +import React, { Component, PropTypes } from 'react'; +import { FormattedMessage } from 'react-intl'; + +import styles from './pinMatrix.css'; + +export default class PinMatrix extends Component { + static propTypes = { + store: PropTypes.object.isRequired, + device: PropTypes.object.isRequired + } + + state = { + passcode: '', + failureMessage: '' + } + + pinMatrix = [7, 8, 9, 4, 5, 6, 1, 2, 3] + + render () { + const { passcode, failureMessage } = this.state; + const { device } = this.props; + + return ( +
+
+ +
+ {this.renderPasscodeBox()} +
+ +
+ {passcode.replace(/./g, '*')} + { + passcode.length + ?
+ : null + } +
+ + Submit + +
+ { failureMessage } +
+
+
+ ); + } + + handleAddDigit = (ev) => { + const index = ev.currentTarget.getAttribute('data-index'); + const digit = this.pinMatrix[index]; + const { passcode } = this.state; + + if (passcode.length > 8) { + return; + } + + this.setState({ + passcode: passcode + digit + }); + } + + renderPasscodeBox () { + return Array.apply(null, Array(9)).map((box, index) => { + return ( + + ); + }); + } + + handleRemoveDigit = () => { + this.setState({ + passcode: this.state.passcode.slice(0, -1) + }); + } + + handleSubmit = () => { + const { device, store } = this.props; + const { passcode } = this.state; + + store.pinMatrixAck(device, passcode) + .then((status) => { + const passcode = ''; + const failureMessage = status ? '' : ( + + ); + + this.setState({ passcode, failureMessage }); + }) + .catch(err => { + this.setState({ + failureMessage: err.toString() + }); + }); + } +} diff --git a/js/src/modals/index.js b/js/src/modals/index.js index 7c313a2ef..fbfd4b6af 100644 --- a/js/src/modals/index.js +++ b/js/src/modals/index.js @@ -29,6 +29,7 @@ export Faucet from './Faucet'; export FirstRun from './FirstRun'; export LoadContract from './LoadContract'; export PasswordManager from './PasswordManager'; +export PinMatrix from './PinMatrix'; export SaveContract from './SaveContract'; export Shapeshift from './Shapeshift'; export Transfer from './Transfer'; diff --git a/js/src/views/Application/application.js b/js/src/views/Application/application.js index 73f0cdda8..9c251abb5 100644 --- a/js/src/views/Application/application.js +++ b/js/src/views/Application/application.js @@ -19,6 +19,8 @@ import React, { Component, PropTypes } from 'react'; import { connect } from 'react-redux'; import UpgradeStore from '~/modals/UpgradeParity/store'; +import { PinMatrix } from '~/modals'; +import HardwareStore from '~/mobx/hardwareStore'; import Connection from '../Connection'; import ParityBar from '../ParityBar'; @@ -52,12 +54,15 @@ class Application extends Component { pending: PropTypes.array } + hwstore = HardwareStore.get(this.context.api); + store = new Store(this.context.api); upgradeStore = UpgradeStore.get(this.context.api); render () { const [root] = (window.location.hash || '').replace('#/', '').split('/'); const isMinimized = root === 'app' || root === 'web'; + const { pinMatrixRequest } = this.hwstore; if (process.env.NODE_ENV !== 'production' && root === 'playground') { return ( @@ -86,6 +91,7 @@ class Application extends Component { : null } + { (pinMatrixRequest.length > 0) ? : null }
diff --git a/rpc/Cargo.toml b/rpc/Cargo.toml index 3d234d2d6..c5b20cf1e 100644 --- a/rpc/Cargo.toml +++ b/rpc/Cargo.toml @@ -58,6 +58,7 @@ rlp = { path = "../util/rlp" } stats = { path = "../util/stats" } vm = { path = "../ethcore/vm" } hash = { path = "../util/hash" } +hardware-wallet = { path = "../hw" } clippy = { version = "0.0.103", optional = true} pretty_assertions = "0.1" diff --git a/rpc/src/lib.rs b/rpc/src/lib.rs index 821b4cfd8..ba27bf290 100644 --- a/rpc/src/lib.rs +++ b/rpc/src/lib.rs @@ -64,6 +64,7 @@ extern crate parity_updater as updater; extern crate rlp; extern crate stats; extern crate hash; +extern crate hardware_wallet; #[macro_use] extern crate log; diff --git a/rpc/src/v1/helpers/dispatch.rs b/rpc/src/v1/helpers/dispatch.rs index 370c909d9..43386d5fa 100644 --- a/rpc/src/v1/helpers/dispatch.rs +++ b/rpc/src/v1/helpers/dispatch.rs @@ -562,7 +562,7 @@ fn hardware_signature(accounts: &AccountProvider, address: Address, t: Transacti let mut stream = rlp::RlpStream::new(); t.rlp_append_unsigned_transaction(&mut stream, chain_id); - let signature = accounts.sign_with_hardware(address, &stream.as_raw()) + let signature = accounts.sign_with_hardware(address, &t, chain_id, &stream.as_raw()) .map_err(|e| { debug!(target: "miner", "Error signing transaction with hardware wallet: {}", e); errors::account("Error signing transaction with hardware wallet", e) diff --git a/rpc/src/v1/impls/light/parity.rs b/rpc/src/v1/impls/light/parity.rs index 7cd540937..2f79f66b6 100644 --- a/rpc/src/v1/impls/light/parity.rs +++ b/rpc/src/v1/impls/light/parity.rs @@ -132,6 +132,11 @@ impl Parity for ParityClient { ) } + fn locked_hardware_accounts_info(&self) -> Result, Error> { + let store = &self.accounts; + Ok(store.locked_hardware_accounts().map_err(|e| errors::account("Error communicating with hardware wallet.", e))?) + } + fn default_account(&self, meta: Self::Metadata) -> BoxFuture { let dapp_id = meta.dapp_id(); future::ok(self.accounts diff --git a/rpc/src/v1/impls/parity.rs b/rpc/src/v1/impls/parity.rs index e66d3ac05..434227fcd 100644 --- a/rpc/src/v1/impls/parity.rs +++ b/rpc/src/v1/impls/parity.rs @@ -151,6 +151,11 @@ impl Parity for ParityClient where ) } + fn locked_hardware_accounts_info(&self) -> Result, Error> { + let store = self.account_provider()?; + Ok(store.locked_hardware_accounts().map_err(|e| errors::account("Error communicating with hardware wallet.", e))?) + } + fn default_account(&self, meta: Self::Metadata) -> BoxFuture { let dapp_id = meta.dapp_id(); future::ok( diff --git a/rpc/src/v1/impls/parity_accounts.rs b/rpc/src/v1/impls/parity_accounts.rs index 1a121699a..259e4802d 100644 --- a/rpc/src/v1/impls/parity_accounts.rs +++ b/rpc/src/v1/impls/parity_accounts.rs @@ -355,6 +355,11 @@ impl ParityAccounts for ParityAccountsClient { .map(Into::into) .map_err(|e| errors::account("Could not sign message.", e)) } + + fn hardware_pin_matrix_ack(&self, path: String, pin: String) -> Result { + let store = self.account_provider()?; + Ok(store.hardware_pin_matrix_ack(&path, &pin).map_err(|e| errors::account("Error communicating with hardware wallet.", e))?) + } } fn into_vec(a: Vec) -> Vec where diff --git a/rpc/src/v1/traits/parity.rs b/rpc/src/v1/traits/parity.rs index f1512b8ce..7a7f68cec 100644 --- a/rpc/src/v1/traits/parity.rs +++ b/rpc/src/v1/traits/parity.rs @@ -45,6 +45,10 @@ build_rpc_trait! { #[rpc(name = "parity_hardwareAccountsInfo")] fn hardware_accounts_info(&self) -> Result, Error>; + /// Get a list of paths to locked hardware wallets + #[rpc(name = "parity_lockedHardwareAccountsInfo")] + fn locked_hardware_accounts_info(&self) -> Result, Error>; + /// Returns default account for dapp. #[rpc(meta, name = "parity_defaultAccount")] fn default_account(&self, Self::Metadata) -> BoxFuture; diff --git a/rpc/src/v1/traits/parity_accounts.rs b/rpc/src/v1/traits/parity_accounts.rs index 73c40ffd4..f7bdc1172 100644 --- a/rpc/src/v1/traits/parity_accounts.rs +++ b/rpc/src/v1/traits/parity_accounts.rs @@ -184,5 +184,9 @@ build_rpc_trait! { /// Sign raw hash with the key corresponding to address and password. #[rpc(name = "parity_signMessage")] fn sign_message(&self, H160, String, H256) -> Result; + + /// Send a PinMatrixAck to a hardware wallet, unlocking it + #[rpc(name = "parity_hardwarePinMatrixAck")] + fn hardware_pin_matrix_ack(&self, String, String) -> Result; } } From e3fc3ccadaec4240753efe6a1c521122aca1410f Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Thu, 14 Sep 2017 20:29:01 +0300 Subject: [PATCH 2/9] SecretStore: use random key to encrypt channel + session-level nonce (#6470) * generate random channel encryption key on restart * session-level nonces * fixed warning after rebase * session_nonce -> nonce --- .../src/key_server_cluster/cluster.rs | 97 +++++++-- .../key_server_cluster/cluster_sessions.rs | 50 ++++- .../key_server_cluster/decryption_session.rs | 45 ++++- .../key_server_cluster/encryption_session.rs | 21 ++ .../key_server_cluster/generation_session.rs | 44 ++++ .../src/key_server_cluster/io/handshake.rs | 188 ++++++++++++------ .../src/key_server_cluster/io/message.rs | 63 ++++-- .../src/key_server_cluster/message.rs | 88 +++++++- secret_store/src/key_server_cluster/mod.rs | 6 + .../src/key_server_cluster/signing_session.rs | 57 +++++- 10 files changed, 556 insertions(+), 103 deletions(-) diff --git a/secret_store/src/key_server_cluster/cluster.rs b/secret_store/src/key_server_cluster/cluster.rs index c85ee9d93..4deeb1244 100644 --- a/secret_store/src/key_server_cluster/cluster.rs +++ b/secret_store/src/key_server_cluster/cluster.rs @@ -330,13 +330,13 @@ impl ClusterCore { finished(Ok(())).boxed() }, Ok((_, Err(err))) => { - warn!(target: "secretstore_net", "{}: protocol error {} when reading message from node {}", data.self_key_pair.public(), err, connection.node_id()); + warn!(target: "secretstore_net", "{}: protocol error '{}' when reading message from node {}", data.self_key_pair.public(), err, connection.node_id()); // continue serving connection data.spawn(ClusterCore::process_connection_messages(data.clone(), connection)); finished(Err(err)).boxed() }, Err(err) => { - warn!(target: "secretstore_net", "{}: network error {} when reading message from node {}", data.self_key_pair.public(), err, connection.node_id()); + warn!(target: "secretstore_net", "{}: network error '{}' when reading message from node {}", data.self_key_pair.public(), err, connection.node_id()); // close connection data.connections.remove(connection.node_id(), connection.is_inbound()); failed(err).boxed() @@ -381,7 +381,7 @@ impl ClusterCore { } }, Ok(DeadlineStatus::Meet(Err(err))) => { - warn!(target: "secretstore_net", "{}: protocol error {} when establishing {} connection{}", + warn!(target: "secretstore_net", "{}: protocol error '{}' when establishing {} connection{}", data.self_key_pair.public(), err, if outbound_addr.is_some() { "outbound" } else { "inbound" }, outbound_addr.map(|a| format!(" with {}", a)).unwrap_or_default()); finished(Ok(())).boxed() @@ -393,7 +393,7 @@ impl ClusterCore { finished(Ok(())).boxed() }, Err(err) => { - warn!(target: "secretstore_net", "{}: network error {} when establishing {} connection{}", + warn!(target: "secretstore_net", "{}: network error '{}' when establishing {} connection{}", data.self_key_pair.public(), err, if outbound_addr.is_some() { "outbound" } else { "inbound" }, outbound_addr.map(|a| format!(" with {}", a)).unwrap_or_default()); finished(Ok(())).boxed() @@ -417,6 +417,7 @@ impl ClusterCore { /// Process single generation message from the connection. fn process_generation_message(data: Arc, connection: Arc, mut message: GenerationMessage) { let session_id = message.session_id().clone(); + let session_nonce = message.session_nonce(); let mut sender = connection.node_id().clone(); let session = match message { GenerationMessage::InitializeSession(_) => { @@ -424,7 +425,19 @@ impl ClusterCore { connected_nodes.insert(data.self_key_pair.public().clone()); let cluster = Arc::new(ClusterView::new(data.clone(), connected_nodes)); - data.sessions.new_generation_session(sender.clone(), session_id.clone(), cluster) + match data.sessions.new_generation_session(sender.clone(), session_id.clone(), Some(session_nonce), cluster) { + Ok(session) => Ok(session), + Err(err) => { + // this is new session => it is not yet in container + warn!(target: "secretstore_net", "{}: generation session initialization error '{}' when requested for new session from node {}", data.self_key_pair.public(), err, sender); + data.spawn(connection.send_message(Message::Generation(GenerationMessage::SessionError(message::SessionError { + session: session_id.into(), + session_nonce: session_nonce, + error: format!("{:?}", err), + })))); + return; + }, + } }, _ => { data.sessions.generation_sessions.get(&session_id) @@ -462,9 +475,10 @@ impl ClusterCore { break; }, Err(err) => { - warn!(target: "secretstore_net", "{}: generation session error {} when processing message {} from node {}", data.self_key_pair.public(), err, message, sender); + warn!(target: "secretstore_net", "{}: generation session error '{}' when processing message {} from node {}", data.self_key_pair.public(), err, message, sender); data.sessions.respond_with_generation_error(&session_id, message::SessionError { session: session_id.clone().into(), + session_nonce: session_nonce, error: format!("{:?}", err), }); if err != Error::InvalidSessionId { @@ -479,6 +493,7 @@ impl ClusterCore { /// Process single encryption message from the connection. fn process_encryption_message(data: Arc, connection: Arc, mut message: EncryptionMessage) { let session_id = message.session_id().clone(); + let session_nonce = message.session_nonce(); let mut sender = connection.node_id().clone(); let session = match message { EncryptionMessage::InitializeEncryptionSession(_) => { @@ -486,7 +501,19 @@ impl ClusterCore { connected_nodes.insert(data.self_key_pair.public().clone()); let cluster = Arc::new(ClusterView::new(data.clone(), connected_nodes)); - data.sessions.new_encryption_session(sender.clone(), session_id.clone(), cluster) + match data.sessions.new_encryption_session(sender.clone(), session_id.clone(), Some(session_nonce), cluster) { + Ok(session) => Ok(session), + Err(err) => { + // this is new session => it is not yet in container + warn!(target: "secretstore_net", "{}: encryption session initialization error '{}' when requested for new session from node {}", data.self_key_pair.public(), err, sender); + data.spawn(connection.send_message(Message::Encryption(EncryptionMessage::EncryptionSessionError(message::EncryptionSessionError { + session: session_id.into(), + session_nonce: session_nonce, + error: format!("{:?}", err), + })))); + return; + }, + } }, _ => { data.sessions.encryption_sessions.get(&session_id) @@ -531,9 +558,10 @@ impl ClusterCore { break; }, Err(err) => { - warn!(target: "secretstore_net", "{}: encryption session error {} when processing message {} from node {}", data.self_key_pair.public(), err, message, sender); + warn!(target: "secretstore_net", "{}: encryption session error '{}' when processing message {} from node {}", data.self_key_pair.public(), err, message, sender); data.sessions.respond_with_encryption_error(&session_id, message::EncryptionSessionError { session: session_id.clone().into(), + session_nonce: session_nonce, error: format!("{:?}", err), }); if err != Error::InvalidSessionId { @@ -549,6 +577,7 @@ impl ClusterCore { fn process_decryption_message(data: Arc, connection: Arc, mut message: DecryptionMessage) { let session_id = message.session_id().clone(); let sub_session_id = message.sub_session_id().clone(); + let session_nonce = message.session_nonce(); let decryption_session_id = DecryptionSessionId::new(session_id.clone(), sub_session_id.clone()); let mut sender = connection.node_id().clone(); let session = match message { @@ -560,7 +589,20 @@ impl ClusterCore { connected_nodes.insert(data.self_key_pair.public().clone()); let cluster = Arc::new(ClusterView::new(data.clone(), connected_nodes)); - data.sessions.new_decryption_session(sender.clone(), session_id.clone(), sub_session_id.clone(), cluster, None) + match data.sessions.new_decryption_session(sender.clone(), session_id.clone(), sub_session_id.clone(), Some(session_nonce), cluster, None) { + Ok(session) => Ok(session), + Err(err) => { + // this is new session => it is not yet in container + warn!(target: "secretstore_net", "{}: decryption session initialization error '{}' when requested for new session from node {}", data.self_key_pair.public(), err, sender); + data.spawn(connection.send_message(Message::Decryption(DecryptionMessage::DecryptionSessionError(message::DecryptionSessionError { + session: session_id.into(), + sub_session: sub_session_id.clone().into(), + session_nonce: session_nonce, + error: format!("{:?}", err), + })))); + return; + }, + } }, _ => { data.sessions.decryption_sessions.get(&decryption_session_id) @@ -589,10 +631,11 @@ impl ClusterCore { } }, Err(err) => { - warn!(target: "secretstore_net", "{}: decryption session error {} when processing message {} from node {}", data.self_key_pair.public(), err, message, sender); + warn!(target: "secretstore_net", "{}: decryption session error '{}' when processing message {} from node {}", data.self_key_pair.public(), err, message, sender); data.sessions.respond_with_decryption_error(&session_id, &sub_session_id, &sender, message::DecryptionSessionError { session: session_id.clone().into(), sub_session: sub_session_id.clone().into(), + session_nonce: session_nonce, error: format!("{:?}", err), }); if err != Error::InvalidSessionId { @@ -608,6 +651,7 @@ impl ClusterCore { fn process_signing_message(data: Arc, connection: Arc, mut message: SigningMessage) { let session_id = message.session_id().clone(); let sub_session_id = message.sub_session_id().clone(); + let session_nonce = message.session_nonce(); let signing_session_id = SigningSessionId::new(session_id.clone(), sub_session_id.clone()); let mut sender = connection.node_id().clone(); let session = match message { @@ -619,7 +663,20 @@ impl ClusterCore { connected_nodes.insert(data.self_key_pair.public().clone()); let cluster = Arc::new(ClusterView::new(data.clone(), connected_nodes)); - data.sessions.new_signing_session(sender.clone(), session_id.clone(), sub_session_id.clone(), cluster, None) + match data.sessions.new_signing_session(sender.clone(), session_id.clone(), sub_session_id.clone(), Some(session_nonce), cluster, None) { + Ok(session) => Ok(session), + Err(err) => { + // this is new session => it is not yet in container + warn!(target: "secretstore_net", "{}: signing session initialization error '{}' when requested for new session from node {}", data.self_key_pair.public(), err, sender); + data.spawn(connection.send_message(Message::Signing(SigningMessage::SigningSessionError(message::SigningSessionError { + session: session_id.into(), + sub_session: sub_session_id.clone().into(), + session_nonce: session_nonce, + error: format!("{:?}", err), + })))); + return; + }, + } }, _ => { data.sessions.signing_sessions.get(&signing_session_id) @@ -654,10 +711,11 @@ impl ClusterCore { break; }, Err(err) => { - warn!(target: "secretstore_net", "{}: signing session error {} when processing message {} from node {}", data.self_key_pair.public(), err, message, sender); + warn!(target: "secretstore_net", "{}: signing session error '{}' when processing message {} from node {}", data.self_key_pair.public(), err, message, sender); data.sessions.respond_with_signing_error(&session_id, &sub_session_id, &sender, message::SigningSessionError { session: session_id.clone().into(), sub_session: sub_session_id.clone().into(), + session_nonce: session_nonce, error: format!("{:?}", err), }); if err != Error::InvalidSessionId { @@ -929,7 +987,7 @@ impl ClusterClient for ClusterClientImpl { connected_nodes.insert(self.data.self_key_pair.public().clone()); let cluster = Arc::new(ClusterView::new(self.data.clone(), connected_nodes.clone())); - let session = self.data.sessions.new_generation_session(self.data.self_key_pair.public().clone(), session_id, cluster)?; + let session = self.data.sessions.new_generation_session(self.data.self_key_pair.public().clone(), session_id, None, cluster)?; session.initialize(author, threshold, connected_nodes)?; Ok(GenerationSessionWrapper::new(Arc::downgrade(&self.data), session_id, session)) } @@ -939,7 +997,7 @@ impl ClusterClient for ClusterClientImpl { connected_nodes.insert(self.data.self_key_pair.public().clone()); let cluster = Arc::new(ClusterView::new(self.data.clone(), connected_nodes.clone())); - let session = self.data.sessions.new_encryption_session(self.data.self_key_pair.public().clone(), session_id, cluster)?; + let session = self.data.sessions.new_encryption_session(self.data.self_key_pair.public().clone(), session_id, None, cluster)?; session.initialize(requestor_signature, common_point, encrypted_point)?; Ok(EncryptionSessionWrapper::new(Arc::downgrade(&self.data), session_id, session)) } @@ -950,7 +1008,7 @@ impl ClusterClient for ClusterClientImpl { let access_key = Random.generate()?.secret().clone(); let cluster = Arc::new(ClusterView::new(self.data.clone(), connected_nodes.clone())); - let session = self.data.sessions.new_decryption_session(self.data.self_key_pair.public().clone(), session_id, access_key.clone(), cluster, Some(requestor_signature))?; + let session = self.data.sessions.new_decryption_session(self.data.self_key_pair.public().clone(), session_id, access_key.clone(), None, cluster, Some(requestor_signature))?; session.initialize(is_shadow_decryption)?; Ok(DecryptionSessionWrapper::new(Arc::downgrade(&self.data), DecryptionSessionId::new(session_id, access_key), session)) } @@ -961,7 +1019,7 @@ impl ClusterClient for ClusterClientImpl { let access_key = Random.generate()?.secret().clone(); let cluster = Arc::new(ClusterView::new(self.data.clone(), connected_nodes.clone())); - let session = self.data.sessions.new_signing_session(self.data.self_key_pair.public().clone(), session_id, access_key.clone(), cluster, Some(requestor_signature))?; + let session = self.data.sessions.new_signing_session(self.data.self_key_pair.public().clone(), session_id, access_key.clone(), None, cluster, Some(requestor_signature))?; session.initialize(message_hash)?; Ok(SigningSessionWrapper::new(Arc::downgrade(&self.data), SigningSessionId::new(session_id, access_key), session)) } @@ -1147,6 +1205,7 @@ pub mod tests { #[test] fn generation_session_is_removed_when_succeeded() { + //::logger::init_log(); let mut core = Core::new().unwrap(); let clusters = make_clusters(&core, 6019, 3); run_clusters(&clusters); @@ -1154,14 +1213,16 @@ pub mod tests { // start && wait for generation session to complete let session = clusters[0].client().new_generation_session(SessionId::default(), Public::default(), 1).unwrap(); - loop_until(&mut core, time::Duration::from_millis(300), || session.state() == GenerationSessionState::Finished); + loop_until(&mut core, time::Duration::from_millis(300), || session.state() == GenerationSessionState::Finished + || session.state() == GenerationSessionState::Failed); assert!(session.joint_public_and_secret().unwrap().is_ok()); // check that session is either removed from all nodes, or nonexistent (already removed) assert!(clusters[0].client().generation_session(&SessionId::default()).is_none()); for i in 1..3 { if let Some(session) = clusters[i].client().generation_session(&SessionId::default()) { - loop_until(&mut core, time::Duration::from_millis(300), || session.state() == GenerationSessionState::Finished); + loop_until(&mut core, time::Duration::from_millis(300), || session.state() == GenerationSessionState::Finished + || session.state() == GenerationSessionState::Failed); assert!(session.joint_public_and_secret().unwrap().is_err()); assert!(clusters[i].client().generation_session(&SessionId::default()).is_none()); } diff --git a/secret_store/src/key_server_cluster/cluster_sessions.rs b/secret_store/src/key_server_cluster/cluster_sessions.rs index f8e4974b1..1168dedc1 100644 --- a/secret_store/src/key_server_cluster/cluster_sessions.rs +++ b/secret_store/src/key_server_cluster/cluster_sessions.rs @@ -16,7 +16,7 @@ use std::time; use std::sync::{Arc, Weak}; -use std::sync::atomic::{AtomicBool, Ordering}; +use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering}; use std::collections::{VecDeque, BTreeSet, BTreeMap}; use parking_lot::RwLock; use ethkey::{Public, Secret, Signature}; @@ -68,6 +68,18 @@ pub struct ClusterSessions { acl_storage: Arc, /// Make faulty generation sessions. make_faulty_generation_sessions: AtomicBool, + /// Always-increasing sessions counter. Is used as session nonce to prevent replay attacks: + /// 1) during handshake, KeyServers generate new random key to encrypt messages + /// => there's no way to use messages from previous connections for replay attacks + /// 2) when session (of any type) is started, master node increases its own session counter and broadcasts it + /// 3) when slave KeyServer receives session initialization message, it checks that new nonce is larger than previous (from the same master) + /// => there's no way to use messages from previous sessions for replay attacks + /// 4) KeyServer checks that each session message contains the same nonce that initialization message + /// Given that: (A) handshake is secure and (B) session itself is initially replay-protected + /// => this guarantees that sessions are replay-protected. + session_counter: AtomicUsize, + /// Maximal session nonce, received from given connection. + max_nonce: RwLock>, } /// Active sessions container. @@ -143,6 +155,8 @@ impl ClusterSessions { decryption_sessions: ClusterSessionsContainer::new(), signing_sessions: ClusterSessionsContainer::new(), make_faulty_generation_sessions: AtomicBool::new(false), + session_counter: AtomicUsize::new(0), + max_nonce: RwLock::new(BTreeMap::new()), } } @@ -152,11 +166,12 @@ impl ClusterSessions { } /// Create new generation session. - pub fn new_generation_session(&self, master: NodeId, session_id: SessionId, cluster: Arc) -> Result, Error> { + pub fn new_generation_session(&self, master: NodeId, session_id: SessionId, nonce: Option, cluster: Arc) -> Result, Error> { // check that there's no finished encryption session with the same id if self.key_storage.contains(&session_id) { return Err(Error::DuplicateSessionId); } + // communicating to all other nodes is crucial for encryption session // => check that we have connections to all cluster nodes if self.nodes.iter().any(|n| !cluster.is_connected(n)) { @@ -164,12 +179,14 @@ impl ClusterSessions { } // check that there's no active encryption session with the same id + let nonce = self.check_session_nonce(&master, nonce)?; self.generation_sessions.insert(master, session_id, cluster.clone(), move || Ok(GenerationSessionImpl::new(GenerationSessionParams { id: session_id.clone(), self_node_id: self.self_node_id.clone(), key_storage: Some(self.key_storage.clone()), cluster: cluster, + nonce: Some(nonce), }))) .map(|session| { if self.make_faulty_generation_sessions.load(Ordering::Relaxed) { @@ -192,14 +209,17 @@ impl ClusterSessions { } /// Create new encryption session. - pub fn new_encryption_session(&self, master: NodeId, session_id: SessionId, cluster: Arc) -> Result, Error> { + pub fn new_encryption_session(&self, master: NodeId, session_id: SessionId, nonce: Option, cluster: Arc) -> Result, Error> { let encrypted_data = self.read_key_share(&session_id, &cluster)?; + let nonce = self.check_session_nonce(&master, nonce)?; + self.encryption_sessions.insert(master, session_id, cluster.clone(), move || EncryptionSessionImpl::new(EncryptionSessionParams { id: session_id.clone(), self_node_id: self.self_node_id.clone(), encrypted_data: encrypted_data, key_storage: self.key_storage.clone(), cluster: cluster, + nonce: nonce, })) } @@ -216,9 +236,10 @@ impl ClusterSessions { } /// Create new decryption session. - pub fn new_decryption_session(&self, master: NodeId, session_id: SessionId, sub_session_id: Secret, cluster: Arc, requester_signature: Option) -> Result, Error> { + pub fn new_decryption_session(&self, master: NodeId, session_id: SessionId, sub_session_id: Secret, nonce: Option, cluster: Arc, requester_signature: Option) -> Result, Error> { let session_id = DecryptionSessionId::new(session_id, sub_session_id); let encrypted_data = self.read_key_share(&session_id.id, &cluster)?; + let nonce = self.check_session_nonce(&master, nonce)?; self.decryption_sessions.insert(master, session_id.clone(), cluster.clone(), move || DecryptionSessionImpl::new(DecryptionSessionParams { meta: SessionMeta { @@ -231,6 +252,7 @@ impl ClusterSessions { key_share: encrypted_data, acl_storage: self.acl_storage.clone(), cluster: cluster, + nonce: nonce, }, requester_signature)) } @@ -253,9 +275,10 @@ impl ClusterSessions { } /// Create new signing session. - pub fn new_signing_session(&self, master: NodeId, session_id: SessionId, sub_session_id: Secret, cluster: Arc, requester_signature: Option) -> Result, Error> { + pub fn new_signing_session(&self, master: NodeId, session_id: SessionId, sub_session_id: Secret, nonce: Option, cluster: Arc, requester_signature: Option) -> Result, Error> { let session_id = SigningSessionId::new(session_id, sub_session_id); let encrypted_data = self.read_key_share(&session_id.id, &cluster)?; + let nonce = self.check_session_nonce(&master, nonce)?; self.signing_sessions.insert(master, session_id.clone(), cluster.clone(), move || SigningSessionImpl::new(SigningSessionParams { meta: SessionMeta { @@ -268,6 +291,7 @@ impl ClusterSessions { key_share: encrypted_data, acl_storage: self.acl_storage.clone(), cluster: cluster, + nonce: nonce, }, requester_signature)) } @@ -303,6 +327,7 @@ impl ClusterSessions { self.encryption_sessions.on_connection_timeout(node_id); self.decryption_sessions.on_connection_timeout(node_id); self.signing_sessions.on_connection_timeout(node_id); + self.max_nonce.write().remove(node_id); } /// Read key share && remove disconnected nodes. @@ -317,6 +342,21 @@ impl ClusterSessions { } Ok(encrypted_data) } + + /// Check or generate new session nonce. + fn check_session_nonce(&self, master: &NodeId, nonce: Option) -> Result { + // if we're master node of the session, then nonce should be generated + // if we're slave node of the session, then nonce should be passed from outside + debug_assert!((master == &self.self_node_id) == nonce.is_none()); + + match nonce { + Some(nonce) => match nonce > *self.max_nonce.write().entry(master.clone()).or_insert(0) { + true => Ok(nonce), + false => Err(Error::ReplayProtection), + }, + None => Ok(self.session_counter.fetch_add(1, Ordering::Relaxed) as u64 + 1), + } + } } impl ClusterSessionsContainer where K: Clone + Ord, V: ClusterSession { diff --git a/secret_store/src/key_server_cluster/decryption_session.rs b/secret_store/src/key_server_cluster/decryption_session.rs index cc19fa0c5..3f7bdba04 100644 --- a/secret_store/src/key_server_cluster/decryption_session.rs +++ b/secret_store/src/key_server_cluster/decryption_session.rs @@ -59,6 +59,8 @@ struct SessionCore { pub key_share: DocumentKeyShare, /// Cluster which allows this node to send messages to other nodes in the cluster. pub cluster: Arc, + /// Session-level nonce. + pub nonce: u64, /// SessionImpl completion condvar. pub completed: Condvar, } @@ -95,8 +97,10 @@ pub struct SessionParams { pub key_share: DocumentKeyShare, /// ACL storage. pub acl_storage: Arc, - /// Cluster + /// Cluster. pub cluster: Arc, + /// Session nonce. + pub nonce: u64, } /// Decryption consensus transport. @@ -105,6 +109,8 @@ struct DecryptionConsensusTransport { id: SessionId, /// Session access key. access_key: Secret, + /// Session-level nonce. + nonce: u64, /// Cluster. cluster: Arc, } @@ -115,6 +121,8 @@ struct DecryptionJobTransport { id: SessionId, //// Session access key. access_key: Secret, + /// Session-level nonce. + nonce: u64, /// Cluster. cluster: Arc, } @@ -140,6 +148,7 @@ impl SessionImpl { let consensus_transport = DecryptionConsensusTransport { id: params.meta.id.clone(), access_key: params.access_key.clone(), + nonce: params.nonce, cluster: params.cluster.clone(), }; @@ -149,6 +158,7 @@ impl SessionImpl { access_key: params.access_key, key_share: params.key_share, cluster: params.cluster, + nonce: params.nonce, completed: Condvar::new(), }, data: Mutex::new(SessionData { @@ -213,6 +223,10 @@ impl SessionImpl { /// Process decryption message. pub fn process_message(&self, sender: &NodeId, message: &DecryptionMessage) -> Result<(), Error> { + if self.core.nonce != message.session_nonce() { + return Err(Error::ReplayProtection); + } + match message { &DecryptionMessage::DecryptionConsensusMessage(ref message) => self.on_consensus_message(sender, message), @@ -286,6 +300,7 @@ impl SessionImpl { self.core.cluster.send(&node, Message::Decryption(DecryptionMessage::DecryptionSessionCompleted(DecryptionSessionCompleted { session: self.core.meta.id.clone().into(), sub_session: self.core.access_key.clone().into(), + session_nonce: self.core.nonce, })))?; } @@ -380,6 +395,7 @@ impl SessionCore { DecryptionJobTransport { id: self.meta.id.clone(), access_key: self.access_key.clone(), + nonce: self.nonce, cluster: self.cluster.clone() } } @@ -399,6 +415,7 @@ impl JobTransport for DecryptionConsensusTransport { self.cluster.send(node, Message::Decryption(DecryptionMessage::DecryptionConsensusMessage(DecryptionConsensusMessage { session: self.id.clone().into(), sub_session: self.access_key.clone().into(), + session_nonce: self.nonce, message: ConsensusMessage::InitializeConsensusSession(InitializeConsensusSession { requestor_signature: request.into(), }) @@ -409,6 +426,7 @@ impl JobTransport for DecryptionConsensusTransport { self.cluster.send(node, Message::Decryption(DecryptionMessage::DecryptionConsensusMessage(DecryptionConsensusMessage { session: self.id.clone().into(), sub_session: self.access_key.clone().into(), + session_nonce: self.nonce, message: ConsensusMessage::ConfirmConsensusInitialization(ConfirmConsensusInitialization { is_confirmed: response, }) @@ -424,6 +442,7 @@ impl JobTransport for DecryptionJobTransport { self.cluster.send(node, Message::Decryption(DecryptionMessage::RequestPartialDecryption(RequestPartialDecryption { session: self.id.clone().into(), sub_session: self.access_key.clone().into(), + session_nonce: self.nonce, request_id: request.id.into(), is_shadow_decryption: request.is_shadow_decryption, nodes: request.other_nodes_ids.into_iter().map(Into::into).collect(), @@ -434,6 +453,7 @@ impl JobTransport for DecryptionJobTransport { self.cluster.send(node, Message::Decryption(DecryptionMessage::PartialDecryption(PartialDecryption { session: self.id.clone().into(), sub_session: self.access_key.clone().into(), + session_nonce: self.nonce, request_id: response.request_id.into(), shadow_point: response.shadow_point.into(), decrypt_shadow: response.decrypt_shadow, @@ -535,7 +555,8 @@ mod tests { access_key: access_key.clone(), key_share: encrypted_datas[i].clone(), acl_storage: acl_storages[i].clone(), - cluster: clusters[i].clone() + cluster: clusters[i].clone(), + nonce: 0, }, if i == 0 { signature.clone() } else { None }).unwrap()).collect(); (requester, clusters, acl_storages, sessions) @@ -584,6 +605,7 @@ mod tests { }, acl_storage: Arc::new(DummyAclStorage::default()), cluster: Arc::new(DummyCluster::new(self_node_id.clone())), + nonce: 0, }, Some(ethkey::sign(Random.generate().unwrap().secret(), &SessionId::default()).unwrap())) { Ok(_) => (), _ => panic!("unexpected"), @@ -614,6 +636,7 @@ mod tests { }, acl_storage: Arc::new(DummyAclStorage::default()), cluster: Arc::new(DummyCluster::new(self_node_id.clone())), + nonce: 0, }, Some(ethkey::sign(Random.generate().unwrap().secret(), &SessionId::default()).unwrap())) { Err(Error::InvalidNodesConfiguration) => (), _ => panic!("unexpected"), @@ -644,6 +667,7 @@ mod tests { }, acl_storage: Arc::new(DummyAclStorage::default()), cluster: Arc::new(DummyCluster::new(self_node_id.clone())), + nonce: 0, }, Some(ethkey::sign(Random.generate().unwrap().secret(), &SessionId::default()).unwrap())) { Err(Error::InvalidThreshold) => (), _ => panic!("unexpected"), @@ -664,6 +688,7 @@ mod tests { assert_eq!(sessions[0].on_consensus_message(sessions[1].node(), &message::DecryptionConsensusMessage { session: SessionId::default().into(), sub_session: sessions[0].access_key().clone().into(), + session_nonce: 0, message: message::ConsensusMessage::InitializeConsensusSession(message::InitializeConsensusSession { requestor_signature: ethkey::sign(Random.generate().unwrap().secret(), &SessionId::default()).unwrap().into(), }), @@ -676,6 +701,7 @@ mod tests { assert_eq!(sessions[1].on_consensus_message(sessions[0].node(), &message::DecryptionConsensusMessage { session: SessionId::default().into(), sub_session: sessions[0].access_key().clone().into(), + session_nonce: 0, message: message::ConsensusMessage::InitializeConsensusSession(message::InitializeConsensusSession { requestor_signature: ethkey::sign(Random.generate().unwrap().secret(), &SessionId::default()).unwrap().into(), }), @@ -683,6 +709,7 @@ mod tests { assert_eq!(sessions[1].on_partial_decryption_requested(sessions[2].node(), &message::RequestPartialDecryption { session: SessionId::default().into(), sub_session: sessions[0].access_key().clone().into(), + session_nonce: 0, request_id: Random.generate().unwrap().secret().clone().into(), is_shadow_decryption: false, nodes: sessions.iter().map(|s| s.node().clone().into()).take(4).collect(), @@ -695,6 +722,7 @@ mod tests { assert_eq!(sessions[1].on_consensus_message(sessions[0].node(), &message::DecryptionConsensusMessage { session: SessionId::default().into(), sub_session: sessions[0].access_key().clone().into(), + session_nonce: 0, message: message::ConsensusMessage::InitializeConsensusSession(message::InitializeConsensusSession { requestor_signature: ethkey::sign(Random.generate().unwrap().secret(), &SessionId::default()).unwrap().into(), }), @@ -702,6 +730,7 @@ mod tests { assert_eq!(sessions[1].on_partial_decryption_requested(sessions[0].node(), &message::RequestPartialDecryption { session: SessionId::default().into(), sub_session: sessions[0].access_key().clone().into(), + session_nonce: 0, request_id: Random.generate().unwrap().secret().clone().into(), is_shadow_decryption: false, nodes: sessions.iter().map(|s| s.node().clone().into()).take(2).collect(), @@ -714,6 +743,7 @@ mod tests { assert_eq!(sessions[0].on_partial_decryption(sessions[1].node(), &message::PartialDecryption { session: SessionId::default().into(), sub_session: sessions[0].access_key().clone().into(), + session_nonce: 0, request_id: Random.generate().unwrap().secret().clone().into(), shadow_point: Random.generate().unwrap().public().clone().into(), decrypt_shadow: None, @@ -937,7 +967,14 @@ mod tests { } #[test] - fn decryption_session_works_over_network() { - // TODO + fn decryption_message_fails_when_nonce_is_wrong() { + let (_, _, _, sessions) = prepare_decryption_sessions(); + assert_eq!(sessions[1].process_message(sessions[0].node(), &message::DecryptionMessage::DecryptionSessionCompleted( + message::DecryptionSessionCompleted { + session: SessionId::default().into(), + sub_session: sessions[0].access_key().clone().into(), + session_nonce: 10, + } + )), Err(Error::ReplayProtection)); } } diff --git a/secret_store/src/key_server_cluster/encryption_session.rs b/secret_store/src/key_server_cluster/encryption_session.rs index 9a1b9e330..1a1304a53 100644 --- a/secret_store/src/key_server_cluster/encryption_session.rs +++ b/secret_store/src/key_server_cluster/encryption_session.rs @@ -53,6 +53,8 @@ pub struct SessionImpl { key_storage: Arc, /// Cluster which allows this node to send messages to other nodes in the cluster. cluster: Arc, + /// Session nonce. + nonce: u64, /// SessionImpl completion condvar. completed: Condvar, /// Mutable session data. @@ -71,6 +73,8 @@ pub struct SessionParams { pub key_storage: Arc, /// Cluster pub cluster: Arc, + /// Session nonce. + pub nonce: u64, } /// Mutable data of encryption (distributed key generation) session. @@ -119,6 +123,7 @@ impl SessionImpl { encrypted_data: params.encrypted_data, key_storage: params.key_storage, cluster: params.cluster, + nonce: params.nonce, completed: Condvar::new(), data: Mutex::new(SessionData { state: SessionState::WaitingForInitialization, @@ -169,6 +174,7 @@ impl SessionImpl { if self.encrypted_data.id_numbers.len() > 1 { self.cluster.broadcast(Message::Encryption(EncryptionMessage::InitializeEncryptionSession(InitializeEncryptionSession { session: self.id.clone().into(), + session_nonce: self.nonce, requestor_signature: requestor_signature.into(), common_point: common_point.into(), encrypted_point: encrypted_point.into(), @@ -187,6 +193,8 @@ impl SessionImpl { debug_assert!(self.id == *message.session); debug_assert!(&sender != self.node()); + self.check_nonce(message.session_nonce)?; + let mut data = self.data.lock(); // check state @@ -213,6 +221,7 @@ impl SessionImpl { // send confirmation back to master node self.cluster.send(&sender, Message::Encryption(EncryptionMessage::ConfirmEncryptionInitialization(ConfirmEncryptionInitialization { session: self.id.clone().into(), + session_nonce: self.nonce, }))) } @@ -221,6 +230,8 @@ impl SessionImpl { debug_assert!(self.id == *message.session); debug_assert!(&sender != self.node()); + self.check_nonce(message.session_nonce)?; + let mut data = self.data.lock(); debug_assert!(data.nodes.contains_key(&sender)); @@ -242,6 +253,8 @@ impl SessionImpl { /// When error has occured on another node. pub fn on_session_error(&self, sender: NodeId, message: &EncryptionSessionError) -> Result<(), Error> { + self.check_nonce(message.session_nonce)?; + let mut data = self.data.lock(); warn!("{}: encryption session failed with error: {} from {}", self.node(), message.error, sender); @@ -252,6 +265,14 @@ impl SessionImpl { Ok(()) } + + /// Check session nonce. + fn check_nonce(&self, message_session_nonce: u64) -> Result<(), Error> { + match self.nonce == message_session_nonce { + true => Ok(()), + false => Err(Error::ReplayProtection), + } + } } impl ClusterSession for SessionImpl { diff --git a/secret_store/src/key_server_cluster/generation_session.rs b/secret_store/src/key_server_cluster/generation_session.rs index dfc441bdb..68ecb3519 100644 --- a/secret_store/src/key_server_cluster/generation_session.rs +++ b/secret_store/src/key_server_cluster/generation_session.rs @@ -54,6 +54,8 @@ pub struct SessionImpl { key_storage: Option>, /// Cluster which allows this node to send messages to other nodes in the cluster. cluster: Arc, + /// Session-level nonce. + nonce: u64, /// SessionImpl completion condvar. completed: Condvar, /// Mutable session data. @@ -70,6 +72,8 @@ pub struct SessionParams { pub key_storage: Option>, /// Cluster pub cluster: Arc, + /// Session nonce. + pub nonce: Option, } /// Mutable data of distributed key generation session. @@ -187,6 +191,9 @@ impl SessionImpl { self_node_id: params.self_node_id, key_storage: params.key_storage, cluster: params.cluster, + // when nonce.is_nonce(), generation session is wrapped + // => nonce is checked somewhere else && we can pass any value + nonce: params.nonce.unwrap_or_default(), completed: Condvar::new(), data: Mutex::new(SessionData { state: SessionState::WaitingForInitialization, @@ -251,6 +258,7 @@ impl SessionImpl { // start initialization self.cluster.send(&next_node, Message::Generation(GenerationMessage::InitializeSession(InitializeSession { session: self.id.clone().into(), + session_nonce: self.nonce, author: author.into(), nodes: data.nodes.iter().map(|(k, v)| (k.clone().into(), v.id_number.clone().into())).collect(), threshold: data.threshold.expect("threshold is filled in initialization phase; KD phase follows initialization phase; qed"), @@ -269,6 +277,10 @@ impl SessionImpl { /// Process single message. pub fn process_message(&self, sender: &NodeId, message: &GenerationMessage) -> Result<(), Error> { + if self.nonce != message.session_nonce() { + return Err(Error::ReplayProtection); + } + match message { &GenerationMessage::InitializeSession(ref message) => self.on_initialize_session(sender.clone(), message), @@ -311,6 +323,7 @@ impl SessionImpl { // send confirmation back to master node self.cluster.send(&sender, Message::Generation(GenerationMessage::ConfirmInitialization(ConfirmInitialization { session: self.id.clone().into(), + session_nonce: self.nonce, derived_point: derived_point.into(), })))?; @@ -348,6 +361,7 @@ impl SessionImpl { if let Some(next_receiver) = next_receiver { return self.cluster.send(&next_receiver, Message::Generation(GenerationMessage::InitializeSession(InitializeSession { session: self.id.clone().into(), + session_nonce: self.nonce, author: data.author.as_ref().expect("author is filled on initialization step; confrm initialization follows initialization; qed").clone().into(), nodes: data.nodes.iter().map(|(k, v)| (k.clone().into(), v.id_number.clone().into())).collect(), threshold: data.threshold.expect("threshold is filled in initialization phase; KD phase follows initialization phase; qed"), @@ -506,6 +520,7 @@ impl SessionImpl { data.state = SessionState::Finished; return self.cluster.send(&sender, Message::Generation(GenerationMessage::SessionCompleted(SessionCompleted { session: self.id.clone().into(), + session_nonce: self.nonce, }))); } @@ -557,6 +572,7 @@ impl SessionImpl { // broadcast derived point && other session paraeters to every other node self.cluster.broadcast(Message::Generation(GenerationMessage::CompleteInitialization(CompleteInitialization { session: self.id.clone().into(), + session_nonce: self.nonce, derived_point: derived_point.into(), }))) } @@ -589,6 +605,7 @@ impl SessionImpl { self.cluster.send(&node, Message::Generation(GenerationMessage::KeysDissemination(KeysDissemination { session: self.id.clone().into(), + session_nonce: self.nonce, secret1: secret1.into(), secret2: secret2.into(), publics: publics.iter().cloned().map(Into::into).collect(), @@ -649,6 +666,7 @@ impl SessionImpl { // broadcast self public key share self.cluster.broadcast(Message::Generation(GenerationMessage::PublicKeyShare(PublicKeyShare { session: self.id.clone().into(), + session_nonce: self.nonce, public_share: self_public_share.into(), }))) } @@ -691,6 +709,7 @@ impl SessionImpl { // then distribute encrypted data to every other node self.cluster.broadcast(Message::Generation(GenerationMessage::SessionCompleted(SessionCompleted { session: self.id.clone().into(), + session_nonce: self.nonce, })))?; // then wait for confirmation from all other nodes @@ -871,6 +890,7 @@ pub mod tests { self_node_id: node_id.clone(), key_storage: Some(key_storage.clone()), cluster: cluster.clone(), + nonce: Some(0), }); nodes.insert(node_id, Node { cluster: cluster, key_storage: key_storage, session: session }); } @@ -960,6 +980,7 @@ pub mod tests { self_node_id: node_id.clone(), key_storage: Some(Arc::new(DummyKeyStorage::default())), cluster: cluster, + nonce: Some(0), }); let cluster_nodes: BTreeSet<_> = (0..2).map(|_| math::generate_random_point().unwrap()).collect(); assert_eq!(session.initialize(Public::default(), 0, cluster_nodes).unwrap_err(), Error::InvalidNodesConfiguration); @@ -1013,6 +1034,7 @@ pub mod tests { l.take_and_process_message().unwrap(); assert_eq!(l.master().on_confirm_initialization(s, &message::ConfirmInitialization { session: sid.into(), + session_nonce: 0, derived_point: math::generate_random_point().unwrap().into(), }).unwrap_err(), Error::InvalidStateForRequest); } @@ -1024,6 +1046,7 @@ pub mod tests { l.take_and_process_message().unwrap(); assert_eq!(l.master().on_confirm_initialization(s, &message::ConfirmInitialization { session: sid.into(), + session_nonce: 0, derived_point: math::generate_random_point().unwrap().into(), }).unwrap_err(), Error::InvalidStateForRequest); } @@ -1052,6 +1075,7 @@ pub mod tests { nodes.insert(math::generate_random_point().unwrap(), math::generate_random_scalar().unwrap()); assert_eq!(l.first_slave().on_initialize_session(m, &message::InitializeSession { session: sid.into(), + session_nonce: 0, author: Public::default().into(), nodes: nodes.into_iter().map(|(k, v)| (k.into(), v.into())).collect(), threshold: 0, @@ -1067,6 +1091,7 @@ pub mod tests { nodes.insert(s, math::generate_random_scalar().unwrap()); assert_eq!(l.first_slave().on_initialize_session(m, &message::InitializeSession { session: sid.into(), + session_nonce: 0, author: Public::default().into(), nodes: nodes.into_iter().map(|(k, v)| (k.into(), v.into())).collect(), threshold: 2, @@ -1079,6 +1104,7 @@ pub mod tests { let (sid, m, _, l) = make_simple_cluster(0, 2).unwrap(); assert_eq!(l.first_slave().on_complete_initialization(m, &message::CompleteInitialization { session: sid.into(), + session_nonce: 0, derived_point: math::generate_random_point().unwrap().into(), }).unwrap_err(), Error::InvalidStateForRequest); } @@ -1092,6 +1118,7 @@ pub mod tests { l.take_and_process_message().unwrap(); assert_eq!(l.first_slave().on_complete_initialization(l.second_slave().node().clone(), &message::CompleteInitialization { session: sid.into(), + session_nonce: 0, derived_point: math::generate_random_point().unwrap().into(), }).unwrap_err(), Error::InvalidMessage); } @@ -1101,6 +1128,7 @@ pub mod tests { let (sid, _, s, l) = make_simple_cluster(0, 2).unwrap(); assert_eq!(l.master().on_keys_dissemination(s, &message::KeysDissemination { session: sid.into(), + session_nonce: 0, secret1: math::generate_random_scalar().unwrap().into(), secret2: math::generate_random_scalar().unwrap().into(), publics: vec![math::generate_random_point().unwrap().into()], @@ -1119,6 +1147,7 @@ pub mod tests { l.take_and_process_message().unwrap(); // m -> s1: KeysDissemination assert_eq!(l.first_slave().on_keys_dissemination(m, &message::KeysDissemination { session: sid.into(), + session_nonce: 0, secret1: math::generate_random_scalar().unwrap().into(), secret2: math::generate_random_scalar().unwrap().into(), publics: vec![math::generate_random_point().unwrap().into(), math::generate_random_point().unwrap().into()], @@ -1137,6 +1166,7 @@ pub mod tests { l.take_and_process_message().unwrap(); // m -> s1: KeysDissemination assert_eq!(l.first_slave().on_keys_dissemination(m, &message::KeysDissemination { session: sid.into(), + session_nonce: 0, secret1: math::generate_random_scalar().unwrap().into(), secret2: math::generate_random_scalar().unwrap().into(), publics: vec![math::generate_random_point().unwrap().into()], @@ -1148,6 +1178,7 @@ pub mod tests { let (sid, _, s, l) = make_simple_cluster(1, 3).unwrap(); assert_eq!(l.master().on_public_key_share(s, &message::PublicKeyShare { session: sid.into(), + session_nonce: 0, public_share: math::generate_random_point().unwrap().into(), }).unwrap_err(), Error::InvalidStateForRequest); } @@ -1176,6 +1207,7 @@ pub mod tests { l.process_message((f, t, Message::Generation(GenerationMessage::PublicKeyShare(msg.clone())))).unwrap(); assert_eq!(l.second_slave().on_public_key_share(m, &message::PublicKeyShare { session: sid.into(), + session_nonce: 0, public_share: math::generate_random_point().unwrap().into(), }).unwrap_err(), Error::InvalidMessage); } @@ -1253,4 +1285,16 @@ pub mod tests { loop_until(&mut core, time::Duration::from_millis(1000), || session.joint_public_and_secret().is_some()); } } + + #[test] + fn generation_message_fails_when_nonce_is_wrong() { + let (sid, m, _, l) = make_simple_cluster(0, 2).unwrap(); + assert_eq!(l.first_slave().process_message(&m, &message::GenerationMessage::KeysDissemination(message::KeysDissemination { + session: sid.into(), + session_nonce: 10, + secret1: math::generate_random_scalar().unwrap().into(), + secret2: math::generate_random_scalar().unwrap().into(), + publics: vec![math::generate_random_point().unwrap().into()], + })).unwrap_err(), Error::ReplayProtection); + } } diff --git a/secret_store/src/key_server_cluster/io/handshake.rs b/secret_store/src/key_server_cluster/io/handshake.rs index 0aedcc624..22f841a15 100644 --- a/secret_store/src/key_server_cluster/io/handshake.rs +++ b/secret_store/src/key_server_cluster/io/handshake.rs @@ -14,12 +14,31 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . +///! Given: two nodes each holding its own `self_key_pair`. +///! +///! Handshake process: +///! 1) both nodes are generating random `KeyPair` (`session_key_pair`), which will be used for channel encryption +///! 2) both nodes are generating random H256 (`confirmation_plain`) +///! 3) both nodes are signing `confirmation_plain` using `session_key_pair` to receive `confirmation_signed_session` +///! 4) nodes exchange with `NodePublicKey` messages, containing: `self_key_pair.public`, `confirmation_plain`, `confirmation_signed_session` +///! 5) both nodes are checking that they're configured to communicate to server with received `message.self_key_pair.public`. Connection is closed otherwise +///! 6) both nodes are recovering peer' `session_key_pair.public` from `message.confirmation_plain` and `message.confirmation_signed_session` +///! 7) both nodes are computing shared session key pair using self' `session_key_pair.secret` && peer' `session_key_pair.public`. All following messages are encrypted using this key_pair. +///! 8) both nodes are signing `message.confirmation_plain` with their own `self_key_pair.private` to receive `confirmation_signed` +///! 9) nodes exchange with `NodePrivateKeySignature` messages, containing `confirmation_signed` +///! 10) both nodes are checking that `confirmation_signed` is actually signed with the owner of peer' `self_key_pair.secret` +///! +///! Result of handshake is: +///! 1) belief, that we are connected to the KS from our KS-set +///! 2) session key pair, which is used to enrypt all connection messages + use std::io; use std::sync::Arc; use std::collections::BTreeSet; use futures::{Future, Poll, Async}; use tokio_io::{AsyncRead, AsyncWrite}; -use ethkey::{Random, Generator, KeyPair, verify_public}; +use ethcrypto::ecdh::agree; +use ethkey::{Random, Generator, KeyPair, Public, Signature, verify_public, sign, recover}; use bigint::hash::H256; use key_server_cluster::{NodeId, Error, NodeKeyPair}; use key_server_cluster::message::{Message, ClusterMessage, NodePublicKey, NodePrivateKeySignature}; @@ -28,16 +47,20 @@ use key_server_cluster::io::{write_message, write_encrypted_message, WriteMessag /// Start handshake procedure with another node from the cluster. pub fn handshake(a: A, self_key_pair: Arc, trusted_nodes: BTreeSet) -> Handshake where A: AsyncWrite + AsyncRead { - let self_confirmation_plain = Random.generate().map(|kp| *kp.secret().clone()).map_err(Into::into); - handshake_with_plain_confirmation(a, self_confirmation_plain, self_key_pair, trusted_nodes) + let init_data = Random.generate().map(|kp| *kp.secret().clone()).map_err(Into::into) + .and_then(|cp| Random.generate().map(|kp| (cp, kp)).map_err(Into::into)); + handshake_with_init_data(a, init_data, self_key_pair, trusted_nodes) } -/// Start handshake procedure with another node from the cluster and given plain confirmation. -pub fn handshake_with_plain_confirmation(a: A, self_confirmation_plain: Result, self_key_pair: Arc, trusted_nodes: BTreeSet) -> Handshake where A: AsyncWrite + AsyncRead { - let (error, state) = match self_confirmation_plain.clone() - .and_then(|c| Handshake::::make_public_key_message(self_key_pair.public().clone(), c)) { - Ok(message) => (None, HandshakeState::SendPublicKey(write_message(a, message))), - Err(err) => (Some((a, Err(err))), HandshakeState::Finished), +/// Start handshake procedure with another node from the cluster and given plain confirmation + session key pair. +pub fn handshake_with_init_data(a: A, init_data: Result<(H256, KeyPair), Error>, self_key_pair: Arc, trusted_nodes: BTreeSet) -> Handshake where A: AsyncWrite + AsyncRead { + let handshake_input_data = init_data + .and_then(|(cp, kp)| sign(kp.secret(), &cp).map(|sp| (cp, kp, sp)).map_err(Into::into)) + .and_then(|(cp, kp, sp)| Handshake::::make_public_key_message(self_key_pair.public().clone(), cp.clone(), sp).map(|msg| (cp, kp, msg))); + + let (error, cp, kp, state) = match handshake_input_data { + Ok((cp, kp, msg)) => (None, cp, Some(kp), HandshakeState::SendPublicKey(write_message(a, msg))), + Err(err) => (Some((a, Err(err))), Default::default(), None, HandshakeState::Finished), }; Handshake { @@ -45,10 +68,12 @@ pub fn handshake_with_plain_confirmation(a: A, self_confirmation_plain: Resul error: error, state: state, self_key_pair: self_key_pair, - self_confirmation_plain: self_confirmation_plain.unwrap_or(Default::default()), + self_session_key_pair: kp, + self_confirmation_plain: cp, trusted_nodes: Some(trusted_nodes), - other_node_id: None, - other_confirmation_plain: None, + peer_node_id: None, + peer_session_public: None, + peer_confirmation_plain: None, shared_key: None, } } @@ -56,9 +81,12 @@ pub fn handshake_with_plain_confirmation(a: A, self_confirmation_plain: Resul /// Wait for handshake procedure to be started by another node from the cluster. pub fn accept_handshake(a: A, self_key_pair: Arc) -> Handshake where A: AsyncWrite + AsyncRead { let self_confirmation_plain = Random.generate().map(|kp| *kp.secret().clone()).map_err(Into::into); - let (error, state) = match self_confirmation_plain.clone() { - Ok(_) => (None, HandshakeState::ReceivePublicKey(read_message(a))), - Err(err) => (Some((a, Err(err))), HandshakeState::Finished), + let handshake_input_data = self_confirmation_plain + .and_then(|cp| Random.generate().map(|kp| (cp, kp)).map_err(Into::into)); + + let (error, cp, kp, state) = match handshake_input_data { + Ok((cp, kp)) => (None, cp, Some(kp), HandshakeState::ReceivePublicKey(read_message(a))), + Err(err) => (Some((a, Err(err))), Default::default(), None, HandshakeState::Finished), }; Handshake { @@ -66,10 +94,12 @@ pub fn accept_handshake(a: A, self_key_pair: Arc) -> Handshake { error: Option<(A, Result)>, state: HandshakeState, self_key_pair: Arc, + self_session_key_pair: Option, self_confirmation_plain: H256, trusted_nodes: Option>, - other_node_id: Option, - other_confirmation_plain: Option, + peer_node_id: Option, + peer_session_public: Option, + peer_confirmation_plain: Option, shared_key: Option, } @@ -111,10 +143,16 @@ impl Handshake where A: AsyncRead + AsyncWrite { self.self_confirmation_plain = self_confirmation_plain; } - pub fn make_public_key_message(self_node_id: NodeId, confirmation_plain: H256) -> Result { + #[cfg(test)] + pub fn set_self_session_key_pair(&mut self, self_session_key_pair: KeyPair) { + self.self_session_key_pair = Some(self_session_key_pair); + } + + pub fn make_public_key_message(self_node_id: NodeId, confirmation_plain: H256, confirmation_signed_session: Signature) -> Result { Ok(Message::Cluster(ClusterMessage::NodePublicKey(NodePublicKey { node_id: self_node_id.into(), confirmation_plain: confirmation_plain.into(), + confirmation_signed_session: confirmation_signed_session.into(), }))) } @@ -123,6 +161,12 @@ impl Handshake where A: AsyncRead + AsyncWrite { confirmation_signed: self_key_pair.sign(confirmation_plain)?.into(), }))) } + + fn compute_shared_key(self_session_key_pair: &KeyPair, peer_session_public: &Public) -> Result { + agree(self_session_key_pair.secret(), peer_session_public) + .map_err(Into::into) + .and_then(|s| fix_shared_key(&s)) + } } impl Future for Handshake where A: AsyncRead + AsyncWrite { @@ -143,20 +187,25 @@ impl Future for Handshake where A: AsyncRead + AsyncWrite { read_message(stream) ), Async::NotReady) } else { - self.shared_key = match self.self_key_pair.compute_shared_key( - self.other_node_id.as_ref().expect("we are in passive mode; in passive mode SendPublicKey follows ReceivePublicKey; other_node_id is filled in ReceivePublicKey; qed") - ).map_err(Into::into).and_then(|sk| fix_shared_key(sk.secret())) { + let shared_key = Self::compute_shared_key( + self.self_session_key_pair.as_ref().expect( + "self_session_key_pair is not filled only when initialization has failed; if initialization has failed, self.error.is_some(); qed"), + self.peer_session_public.as_ref().expect( + "we are in passive mode; in passive mode SendPublicKey follows ReceivePublicKey; peer_session_public is filled in ReceivePublicKey; qed"), + ); + + self.shared_key = match shared_key { Ok(shared_key) => Some(shared_key), - Err(err) => return Ok((stream, Err(err.into())).into()), + Err(err) => return Ok((stream, Err(err)).into()), }; - let message = match Handshake::::make_private_key_signature_message( - &*self.self_key_pair, - self.other_confirmation_plain.as_ref().expect("we are in passive mode; in passive mode SendPublicKey follows ReceivePublicKey; other_confirmation_plain is filled in ReceivePublicKey; qed") - ) { + let peer_confirmation_plain = self.peer_confirmation_plain.as_ref() + .expect("we are in passive mode; in passive mode SendPublicKey follows ReceivePublicKey; peer_confirmation_plain is filled in ReceivePublicKey; qed"); + let message = match Handshake::::make_private_key_signature_message(&*self.self_key_pair, peer_confirmation_plain) { Ok(message) => message, Err(err) => return Ok((stream, Err(err)).into()), }; + (HandshakeState::SendPrivateKeySignature(write_encrypted_message(stream, self.shared_key.as_ref().expect("filled couple of lines above; qed"), message)), Async::NotReady) @@ -177,28 +226,44 @@ impl Future for Handshake where A: AsyncRead + AsyncWrite { return Ok((stream, Err(Error::InvalidNodeId)).into()); } - self.other_node_id = Some(message.node_id.into()); - self.other_confirmation_plain = Some(message.confirmation_plain.into()); + self.peer_node_id = Some(message.node_id.into()); + self.peer_session_public = Some(match recover(&message.confirmation_signed_session, &message.confirmation_plain) { + Ok(peer_session_public) => peer_session_public, + Err(err) => return Ok((stream, Err(err.into())).into()), + }); + self.peer_confirmation_plain = Some(message.confirmation_plain.into()); if self.is_active { - self.shared_key = match self.self_key_pair.compute_shared_key( - self.other_node_id.as_ref().expect("filled couple of lines above; qed") - ).map_err(Into::into).and_then(|sk| fix_shared_key(sk.secret())) { + let shared_key = Self::compute_shared_key( + self.self_session_key_pair.as_ref().expect( + "self_session_key_pair is not filled only when initialization has failed; if initialization has failed, self.error.is_some(); qed"), + self.peer_session_public.as_ref().expect( + "we are in passive mode; in passive mode SendPublicKey follows ReceivePublicKey; peer_session_public is filled in ReceivePublicKey; qed"), + ); + + self.shared_key = match shared_key { Ok(shared_key) => Some(shared_key), - Err(err) => return Ok((stream, Err(err.into())).into()), + Err(err) => return Ok((stream, Err(err)).into()), }; - let message = match Handshake::::make_private_key_signature_message( - &*self.self_key_pair, - self.other_confirmation_plain.as_ref().expect("filled couple of lines above; qed") - ) { + let peer_confirmation_plain = self.peer_confirmation_plain.as_ref() + .expect("filled couple of lines above; qed"); + let message = match Handshake::::make_private_key_signature_message(&*self.self_key_pair, peer_confirmation_plain) { Ok(message) => message, Err(err) => return Ok((stream, Err(err)).into()), }; + (HandshakeState::SendPrivateKeySignature(write_encrypted_message(stream, self.shared_key.as_ref().expect("filled couple of lines above; qed"), message)), Async::NotReady) } else { - let message = match Handshake::::make_public_key_message(self.self_key_pair.public().clone(), self.self_confirmation_plain.clone()) { + let self_session_key_pair = self.self_session_key_pair.as_ref() + .expect("self_session_key_pair is not filled only when initialization has failed; if initialization has failed, self.error.is_some(); qed"); + let confirmation_signed_session = match sign(self_session_key_pair.secret(), &self.self_confirmation_plain).map_err(Into::into) { + Ok(confirmation_signed_session) => confirmation_signed_session, + Err(err) => return Ok((stream, Err(err)).into()), + }; + + let message = match Handshake::::make_public_key_message(self.self_key_pair.public().clone(), self.self_confirmation_plain.clone(), confirmation_signed_session) { Ok(message) => message, Err(err) => return Ok((stream, Err(err)).into()), }; @@ -225,13 +290,13 @@ impl Future for Handshake where A: AsyncRead + AsyncWrite { Err(err) => return Ok((stream, Err(err.into())).into()), }; - let other_node_public = self.other_node_id.as_ref().expect("other_node_id is filled in ReceivePublicKey; ReceivePrivateKeySignature follows ReceivePublicKey; qed"); - if !verify_public(other_node_public, &*message.confirmation_signed, &self.self_confirmation_plain).unwrap_or(false) { + let peer_public = self.peer_node_id.as_ref().expect("peer_node_id is filled in ReceivePublicKey; ReceivePrivateKeySignature follows ReceivePublicKey; qed"); + if !verify_public(peer_public, &*message.confirmation_signed, &self.self_confirmation_plain).unwrap_or(false) { return Ok((stream, Err(Error::InvalidMessage)).into()); } (HandshakeState::Finished, Async::Ready((stream, Ok(HandshakeResult { - node_id: self.other_node_id.expect("other_node_id is filled in ReceivePublicKey; ReceivePrivateKeySignature follows ReceivePublicKey; qed"), + node_id: self.peer_node_id.expect("peer_node_id is filled in ReceivePublicKey; ReceivePrivateKeySignature follows ReceivePublicKey; qed"), shared_key: self.shared_key.clone().expect("shared_key is filled in Send/ReceivePublicKey; ReceivePrivateKeySignature follows Send/ReceivePublicKey; qed"), })))) }, @@ -253,27 +318,26 @@ mod tests { use std::collections::BTreeSet; use futures::Future; use ethkey::{Random, Generator, sign}; - use ethcrypto::ecdh::agree; use bigint::hash::H256; use key_server_cluster::PlainNodeKeyPair; - use key_server_cluster::io::message::fix_shared_key; use key_server_cluster::io::message::tests::TestIo; use key_server_cluster::message::{Message, ClusterMessage, NodePublicKey, NodePrivateKeySignature}; - use super::{handshake_with_plain_confirmation, accept_handshake, HandshakeResult}; + use super::{handshake_with_init_data, accept_handshake, HandshakeResult}; fn prepare_test_io() -> (H256, TestIo) { - let self_key_pair = Random.generate().unwrap(); - let peer_key_pair = Random.generate().unwrap(); - let mut io = TestIo::new(self_key_pair.clone(), peer_key_pair.public().clone()); + let mut io = TestIo::new(); let self_confirmation_plain = *Random.generate().unwrap().secret().clone(); let peer_confirmation_plain = *Random.generate().unwrap().secret().clone(); - let self_confirmation_signed = sign(peer_key_pair.secret(), &self_confirmation_plain).unwrap(); + let self_confirmation_signed = sign(io.peer_key_pair().secret(), &self_confirmation_plain).unwrap(); + let peer_confirmation_signed = sign(io.peer_session_key_pair().secret(), &peer_confirmation_plain).unwrap(); + let peer_public = io.peer_key_pair().public().clone(); io.add_input_message(Message::Cluster(ClusterMessage::NodePublicKey(NodePublicKey { - node_id: peer_key_pair.public().clone().into(), + node_id: peer_public.into(), confirmation_plain: peer_confirmation_plain.into(), + confirmation_signed_session: peer_confirmation_signed.into(), }))); io.add_encrypted_input_message(Message::Cluster(ClusterMessage::NodePrivateKeySignature(NodePrivateKeySignature { confirmation_signed: self_confirmation_signed.into(), @@ -285,14 +349,15 @@ mod tests { #[test] fn active_handshake_works() { let (self_confirmation_plain, io) = prepare_test_io(); - let self_key_pair = io.self_key_pair().clone(); - let trusted_nodes: BTreeSet<_> = vec![io.peer_public().clone()].into_iter().collect(); - let shared_key = fix_shared_key(&agree(self_key_pair.secret(), trusted_nodes.iter().nth(0).unwrap()).unwrap()).unwrap(); + let trusted_nodes: BTreeSet<_> = vec![io.peer_key_pair().public().clone()].into_iter().collect(); + let self_session_key_pair = io.self_session_key_pair().clone(); + let self_key_pair = Arc::new(PlainNodeKeyPair::new(io.self_key_pair().clone())); + let shared_key = io.shared_key_pair().clone(); - let handshake = handshake_with_plain_confirmation(io, Ok(self_confirmation_plain), Arc::new(PlainNodeKeyPair::new(self_key_pair)), trusted_nodes); + let handshake = handshake_with_init_data(io, Ok((self_confirmation_plain, self_session_key_pair)), self_key_pair, trusted_nodes); let handshake_result = handshake.wait().unwrap(); assert_eq!(handshake_result.1, Ok(HandshakeResult { - node_id: handshake_result.0.peer_public().clone(), + node_id: handshake_result.0.peer_key_pair().public().clone(), shared_key: shared_key, })); } @@ -300,16 +365,17 @@ mod tests { #[test] fn passive_handshake_works() { let (self_confirmation_plain, io) = prepare_test_io(); - let self_key_pair = io.self_key_pair().clone(); - let trusted_nodes: BTreeSet<_> = vec![io.peer_public().clone()].into_iter().collect(); - let shared_key = fix_shared_key(&agree(self_key_pair.secret(), trusted_nodes.iter().nth(0).unwrap()).unwrap()).unwrap(); + let self_key_pair = Arc::new(PlainNodeKeyPair::new(io.self_key_pair().clone())); + let self_session_key_pair = io.self_session_key_pair().clone(); + let shared_key = io.shared_key_pair().clone(); - let mut handshake = accept_handshake(io, Arc::new(PlainNodeKeyPair::new(self_key_pair))); + let mut handshake = accept_handshake(io, self_key_pair); handshake.set_self_confirmation_plain(self_confirmation_plain); + handshake.set_self_session_key_pair(self_session_key_pair); let handshake_result = handshake.wait().unwrap(); assert_eq!(handshake_result.1, Ok(HandshakeResult { - node_id: handshake_result.0.peer_public().clone(), + node_id: handshake_result.0.peer_key_pair().public().clone(), shared_key: shared_key, })); } diff --git a/secret_store/src/key_server_cluster/io/message.rs b/secret_store/src/key_server_cluster/io/message.rs index e25e96836..2e549f1d9 100644 --- a/secret_store/src/key_server_cluster/io/message.rs +++ b/secret_store/src/key_server_cluster/io/message.rs @@ -30,6 +30,8 @@ use key_server_cluster::message::{Message, ClusterMessage, GenerationMessage, En /// Size of serialized header. pub const MESSAGE_HEADER_SIZE: usize = 4; +/// Current header version. +pub const CURRENT_HEADER_VERSION: u8 = 1; /// Message header. #[derive(Debug, PartialEq)] @@ -97,7 +99,7 @@ pub fn serialize_message(message: Message) -> Result { let payload = payload.map_err(|err| Error::Serde(err.to_string()))?; build_serialized_message(MessageHeader { kind: message_kind, - version: 1, + version: CURRENT_HEADER_VERSION, size: 0, }, payload) } @@ -177,8 +179,13 @@ fn serialize_header(header: &MessageHeader) -> Result, Error> { /// Deserialize message header. pub fn deserialize_header(data: &[u8]) -> Result { let mut reader = Cursor::new(data); + let version = reader.read_u8()?; + if version != CURRENT_HEADER_VERSION { + return Err(Error::InvalidMessageVersion); + } + Ok(MessageHeader { - version: reader.read_u8()?, + version: version, kind: reader.read_u8()?, size: reader.read_u16::()?, }) @@ -202,25 +209,34 @@ pub mod tests { use std::io; use futures::Poll; use tokio_io::{AsyncRead, AsyncWrite}; - use ethkey::{KeyPair, Public}; + use ethkey::{Random, Generator, KeyPair}; use ethcrypto::ecdh::agree; + use key_server_cluster::Error; use key_server_cluster::message::Message; - use super::{MESSAGE_HEADER_SIZE, MessageHeader, fix_shared_key, encrypt_message, serialize_message, - serialize_header, deserialize_header}; + use super::{MESSAGE_HEADER_SIZE, CURRENT_HEADER_VERSION, MessageHeader, fix_shared_key, encrypt_message, + serialize_message, serialize_header, deserialize_header}; pub struct TestIo { self_key_pair: KeyPair, - peer_public: Public, + self_session_key_pair: KeyPair, + peer_key_pair: KeyPair, + peer_session_key_pair: KeyPair, shared_key_pair: KeyPair, input_buffer: io::Cursor>, } impl TestIo { - pub fn new(self_key_pair: KeyPair, peer_public: Public) -> Self { - let shared_key_pair = fix_shared_key(&agree(self_key_pair.secret(), &peer_public).unwrap()).unwrap(); + pub fn new() -> Self { + let self_session_key_pair = Random.generate().unwrap(); + let peer_session_key_pair = Random.generate().unwrap(); + let self_key_pair = Random.generate().unwrap(); + let peer_key_pair = Random.generate().unwrap(); + let shared_key_pair = fix_shared_key(&agree(self_session_key_pair.secret(), peer_session_key_pair.public()).unwrap()).unwrap(); TestIo { self_key_pair: self_key_pair, - peer_public: peer_public, + self_session_key_pair: self_session_key_pair, + peer_key_pair: peer_key_pair, + peer_session_key_pair: peer_session_key_pair, shared_key_pair: shared_key_pair, input_buffer: io::Cursor::new(Vec::new()), } @@ -230,8 +246,20 @@ pub mod tests { &self.self_key_pair } - pub fn peer_public(&self) -> &Public { - &self.peer_public + pub fn self_session_key_pair(&self) -> &KeyPair { + &self.self_session_key_pair + } + + pub fn peer_key_pair(&self) -> &KeyPair { + &self.peer_key_pair + } + + pub fn peer_session_key_pair(&self) -> &KeyPair { + &self.peer_session_key_pair + } + + pub fn shared_key_pair(&self) -> &KeyPair { + &self.shared_key_pair } pub fn add_input_message(&mut self, message: Message) { @@ -281,7 +309,7 @@ pub mod tests { fn header_serialization_works() { let header = MessageHeader { kind: 1, - version: 2, + version: CURRENT_HEADER_VERSION, size: 3, }; @@ -291,4 +319,15 @@ pub mod tests { let deserialized_header = deserialize_header(&serialized_header).unwrap(); assert_eq!(deserialized_header, header); } + + #[test] + fn deserializing_header_of_wrong_version_fails() { + let header = MessageHeader { + kind: 1, + version: CURRENT_HEADER_VERSION + 1, + size: 3, + }; + + assert_eq!(deserialize_header(&serialize_header(&header).unwrap()).unwrap_err(), Error::InvalidMessageVersion); + } } diff --git a/secret_store/src/key_server_cluster/message.rs b/secret_store/src/key_server_cluster/message.rs index c0f5729c0..e5adc39d3 100644 --- a/secret_store/src/key_server_cluster/message.rs +++ b/secret_store/src/key_server_cluster/message.rs @@ -127,8 +127,10 @@ pub enum SigningMessage { pub struct NodePublicKey { /// Node identifier (aka node public key). pub node_id: MessageNodeId, - /// Data, which must be signed by peer to prove that he owns the corresponding private key. + /// Random data, which must be signed by peer to prove that he owns the corresponding private key. pub confirmation_plain: SerializableH256, + /// The same random `confirmation_plain`, signed with one-time session key. + pub confirmation_signed_session: SerializableSignature, } /// Confirm that node owns the private key of previously passed public key (aka node id). @@ -138,7 +140,6 @@ pub struct NodePrivateKeySignature { pub confirmation_signed: SerializableSignature, } - /// Ask if the node is still alive. #[derive(Clone, Debug, Serialize, Deserialize)] pub struct KeepAlive { @@ -154,6 +155,8 @@ pub struct KeepAliveResponse { pub struct InitializeSession { /// Session Id. pub session: MessageSessionId, + /// Session-level nonce. + pub session_nonce: u64, /// Session author. pub author: SerializablePublic, /// All session participants along with their identification numbers. @@ -173,6 +176,8 @@ pub struct InitializeSession { pub struct ConfirmInitialization { /// Session Id. pub session: MessageSessionId, + /// Session-level nonce. + pub session_nonce: u64, /// Derived generation point. pub derived_point: SerializablePublic, } @@ -182,6 +187,8 @@ pub struct ConfirmInitialization { pub struct CompleteInitialization { /// Session Id. pub session: MessageSessionId, + /// Session-level nonce. + pub session_nonce: u64, /// Derived generation point. pub derived_point: SerializablePublic, } @@ -191,6 +198,8 @@ pub struct CompleteInitialization { pub struct KeysDissemination { /// Session Id. pub session: MessageSessionId, + /// Session-level nonce. + pub session_nonce: u64, /// Secret 1. pub secret1: SerializableSecret, /// Secret 2. @@ -204,6 +213,8 @@ pub struct KeysDissemination { pub struct PublicKeyShare { /// Session Id. pub session: MessageSessionId, + /// Session-level nonce. + pub session_nonce: u64, /// Public key share. pub public_share: SerializablePublic, } @@ -213,6 +224,8 @@ pub struct PublicKeyShare { pub struct SessionError { /// Session Id. pub session: MessageSessionId, + /// Session-level nonce. + pub session_nonce: u64, /// Public key share. pub error: String, } @@ -222,6 +235,8 @@ pub struct SessionError { pub struct SessionCompleted { /// Session Id. pub session: MessageSessionId, + /// Session-level nonce. + pub session_nonce: u64, } /// Node is requested to prepare for saving encrypted data. @@ -229,6 +244,8 @@ pub struct SessionCompleted { pub struct InitializeEncryptionSession { /// Encryption session Id. pub session: MessageSessionId, + /// Session-level nonce. + pub session_nonce: u64, /// Requestor signature. pub requestor_signature: SerializableSignature, /// Common point. @@ -242,6 +259,8 @@ pub struct InitializeEncryptionSession { pub struct ConfirmEncryptionInitialization { /// Encryption session Id. pub session: MessageSessionId, + /// Session-level nonce. + pub session_nonce: u64, } /// When encryption session error has occured. @@ -249,6 +268,8 @@ pub struct ConfirmEncryptionInitialization { pub struct EncryptionSessionError { /// Encryption session Id. pub session: MessageSessionId, + /// Session-level nonce. + pub session_nonce: u64, /// Error message. pub error: String, } @@ -274,6 +295,8 @@ pub struct SigningConsensusMessage { pub session: MessageSessionId, /// Signing session Id. pub sub_session: SerializableSecret, + /// Session-level nonce. + pub session_nonce: u64, /// Consensus message. pub message: ConsensusMessage, } @@ -285,6 +308,8 @@ pub struct SigningGenerationMessage { pub session: MessageSessionId, /// Signing session Id. pub sub_session: SerializableSecret, + /// Session-level nonce. + pub session_nonce: u64, /// Generation message. pub message: GenerationMessage, } @@ -296,6 +321,8 @@ pub struct RequestPartialSignature { pub session: MessageSessionId, /// Signing session Id. pub sub_session: SerializableSecret, + /// Session-level nonce. + pub session_nonce: u64, /// Request id. pub request_id: SerializableSecret, /// Message hash. @@ -311,6 +338,8 @@ pub struct PartialSignature { pub session: MessageSessionId, /// Signing session Id. pub sub_session: SerializableSecret, + /// Session-level nonce. + pub session_nonce: u64, /// Request id. pub request_id: SerializableSecret, /// S part of signature. @@ -324,6 +353,8 @@ pub struct SigningSessionError { pub session: MessageSessionId, /// Signing session Id. pub sub_session: SerializableSecret, + /// Session-level nonce. + pub session_nonce: u64, /// Error description. pub error: String, } @@ -335,6 +366,8 @@ pub struct SigningSessionCompleted { pub session: MessageSessionId, /// Signing session Id. pub sub_session: SerializableSecret, + /// Session-level nonce. + pub session_nonce: u64, } /// Consensus-related decryption message. @@ -344,6 +377,8 @@ pub struct DecryptionConsensusMessage { pub session: MessageSessionId, /// Signing session Id. pub sub_session: SerializableSecret, + /// Session-level nonce. + pub session_nonce: u64, /// Consensus message. pub message: ConsensusMessage, } @@ -355,6 +390,8 @@ pub struct RequestPartialDecryption { pub session: MessageSessionId, /// Decryption session Id. pub sub_session: SerializableSecret, + /// Session-level nonce. + pub session_nonce: u64, /// Request id. pub request_id: SerializableSecret, /// Is shadow decryption requested? When true, decryption result @@ -371,6 +408,8 @@ pub struct PartialDecryption { pub session: MessageSessionId, /// Decryption session Id. pub sub_session: SerializableSecret, + /// Session-level nonce. + pub session_nonce: u64, /// Request id. pub request_id: SerializableSecret, /// Partially decrypted secret. @@ -386,6 +425,8 @@ pub struct DecryptionSessionError { pub session: MessageSessionId, /// Decryption session Id. pub sub_session: SerializableSecret, + /// Session-level nonce. + pub session_nonce: u64, /// Public key share. pub error: String, } @@ -397,6 +438,8 @@ pub struct DecryptionSessionCompleted { pub session: MessageSessionId, /// Decryption session Id. pub sub_session: SerializableSecret, + /// Session-level nonce. + pub session_nonce: u64, } impl GenerationMessage { @@ -411,6 +454,18 @@ impl GenerationMessage { GenerationMessage::SessionCompleted(ref msg) => &msg.session, } } + + pub fn session_nonce(&self) -> u64 { + match *self { + GenerationMessage::InitializeSession(ref msg) => msg.session_nonce, + GenerationMessage::ConfirmInitialization(ref msg) => msg.session_nonce, + GenerationMessage::CompleteInitialization(ref msg) => msg.session_nonce, + GenerationMessage::KeysDissemination(ref msg) => msg.session_nonce, + GenerationMessage::PublicKeyShare(ref msg) => msg.session_nonce, + GenerationMessage::SessionError(ref msg) => msg.session_nonce, + GenerationMessage::SessionCompleted(ref msg) => msg.session_nonce, + } + } } impl EncryptionMessage { @@ -421,6 +476,14 @@ impl EncryptionMessage { EncryptionMessage::EncryptionSessionError(ref msg) => &msg.session, } } + + pub fn session_nonce(&self) -> u64 { + match *self { + EncryptionMessage::InitializeEncryptionSession(ref msg) => msg.session_nonce, + EncryptionMessage::ConfirmEncryptionInitialization(ref msg) => msg.session_nonce, + EncryptionMessage::EncryptionSessionError(ref msg) => msg.session_nonce, + } + } } impl DecryptionMessage { @@ -443,6 +506,16 @@ impl DecryptionMessage { DecryptionMessage::DecryptionSessionCompleted(ref msg) => &msg.sub_session, } } + + pub fn session_nonce(&self) -> u64 { + match *self { + DecryptionMessage::DecryptionConsensusMessage(ref msg) => msg.session_nonce, + DecryptionMessage::RequestPartialDecryption(ref msg) => msg.session_nonce, + DecryptionMessage::PartialDecryption(ref msg) => msg.session_nonce, + DecryptionMessage::DecryptionSessionError(ref msg) => msg.session_nonce, + DecryptionMessage::DecryptionSessionCompleted(ref msg) => msg.session_nonce, + } + } } impl SigningMessage { @@ -467,6 +540,17 @@ impl SigningMessage { SigningMessage::SigningSessionCompleted(ref msg) => &msg.sub_session, } } + + pub fn session_nonce(&self) -> u64 { + match *self { + SigningMessage::SigningConsensusMessage(ref msg) => msg.session_nonce, + SigningMessage::SigningGenerationMessage(ref msg) => msg.session_nonce, + SigningMessage::RequestPartialSignature(ref msg) => msg.session_nonce, + SigningMessage::PartialSignature(ref msg) => msg.session_nonce, + SigningMessage::SigningSessionError(ref msg) => msg.session_nonce, + SigningMessage::SigningSessionCompleted(ref msg) => msg.session_nonce, + } + } } impl fmt::Display for Message { diff --git a/secret_store/src/key_server_cluster/mod.rs b/secret_store/src/key_server_cluster/mod.rs index 1ec04e2e0..a71c356ae 100644 --- a/secret_store/src/key_server_cluster/mod.rs +++ b/secret_store/src/key_server_cluster/mod.rs @@ -90,6 +90,10 @@ pub enum Error { /// Message or some data in the message was recognized as invalid. /// This means that node is misbehaving/cheating. InvalidMessage, + /// Message version is not supported. + InvalidMessageVersion, + /// Message is invalid because of replay-attack protection. + ReplayProtection, /// Connection to node, required for this session is not established. NodeDisconnected, /// Cryptographic error. @@ -140,6 +144,8 @@ impl fmt::Display for Error { Error::InvalidStateForRequest => write!(f, "session is in invalid state for processing this request"), Error::InvalidNodeForRequest => write!(f, "invalid node for this request"), Error::InvalidMessage => write!(f, "invalid message is received"), + Error::InvalidMessageVersion => write!(f, "unsupported message is received"), + Error::ReplayProtection => write!(f, "replay message is received"), Error::NodeDisconnected => write!(f, "node required for this operation is currently disconnected"), Error::EthKey(ref e) => write!(f, "cryptographic error {}", e), Error::Io(ref e) => write!(f, "i/o error {}", e), diff --git a/secret_store/src/key_server_cluster/signing_session.rs b/secret_store/src/key_server_cluster/signing_session.rs index 73d65f749..822d8228b 100644 --- a/secret_store/src/key_server_cluster/signing_session.rs +++ b/secret_store/src/key_server_cluster/signing_session.rs @@ -63,6 +63,8 @@ struct SessionCore { pub key_share: DocumentKeyShare, /// Cluster which allows this node to send messages to other nodes in the cluster. pub cluster: Arc, + /// Session-level nonce. + pub nonce: u64, /// SessionImpl completion condvar. pub completed: Condvar, } @@ -108,6 +110,8 @@ pub struct SessionParams { pub acl_storage: Arc, /// Cluster pub cluster: Arc, + /// Session nonce. + pub nonce: u64, } /// Signing consensus transport. @@ -116,6 +120,8 @@ struct SigningConsensusTransport { id: SessionId, /// Session access key. access_key: Secret, + /// Session-level nonce. + nonce: u64, /// Cluster. cluster: Arc, } @@ -126,6 +132,8 @@ struct SessionKeyGenerationTransport { access_key: Secret, /// Cluster. cluster: Arc, + /// Session-level nonce. + nonce: u64, /// Other nodes ids. other_nodes_ids: BTreeSet, } @@ -134,8 +142,10 @@ struct SessionKeyGenerationTransport { struct SigningJobTransport { /// Session id. id: SessionId, - //// Session access key. + /// Session access key. access_key: Secret, + /// Session-level nonce. + nonce: u64, /// Cluster. cluster: Arc, } @@ -156,6 +166,7 @@ impl SessionImpl { let consensus_transport = SigningConsensusTransport { id: params.meta.id.clone(), access_key: params.access_key.clone(), + nonce: params.nonce, cluster: params.cluster.clone(), }; @@ -165,6 +176,7 @@ impl SessionImpl { access_key: params.access_key, key_share: params.key_share, cluster: params.cluster, + nonce: params.nonce, completed: Condvar::new(), }, data: Mutex::new(SessionData { @@ -208,8 +220,10 @@ impl SessionImpl { cluster: Arc::new(SessionKeyGenerationTransport { access_key: self.core.access_key.clone(), cluster: self.core.cluster.clone(), + nonce: self.core.nonce, other_nodes_ids: BTreeSet::new() }), + nonce: None, }); generation_session.initialize(Public::default(), 0, vec![self.core.meta.self_node_id.clone()].into_iter().collect())?; @@ -232,6 +246,10 @@ impl SessionImpl { /// Process signing message. pub fn process_message(&self, sender: &NodeId, message: &SigningMessage) -> Result<(), Error> { + if self.core.nonce != message.session_nonce() { + return Err(Error::ReplayProtection); + } + match message { &SigningMessage::SigningConsensusMessage(ref message) => self.on_consensus_message(sender, message), @@ -274,8 +292,10 @@ impl SessionImpl { cluster: Arc::new(SessionKeyGenerationTransport { access_key: self.core.access_key.clone(), cluster: self.core.cluster.clone(), + nonce: self.core.nonce, other_nodes_ids: other_consensus_group_nodes, }), + nonce: None, }); generation_session.initialize(Public::default(), self.core.key_share.threshold, consensus_group)?; data.generation_session = Some(generation_session); @@ -308,8 +328,10 @@ impl SessionImpl { cluster: Arc::new(SessionKeyGenerationTransport { access_key: self.core.access_key.clone(), cluster: self.core.cluster.clone(), + nonce: self.core.nonce, other_nodes_ids: other_consensus_group_nodes }), + nonce: None, }); data.generation_session = Some(generation_session); data.state = SessionState::SessionKeyGeneration; @@ -390,6 +412,7 @@ impl SessionImpl { self.core.cluster.send(&node, Message::Signing(SigningMessage::SigningSessionCompleted(SigningSessionCompleted { session: self.core.meta.id.clone().into(), sub_session: self.core.access_key.clone().into(), + session_nonce: self.core.nonce, })))?; } @@ -490,6 +513,7 @@ impl SessionKeyGenerationTransport { Message::Generation(message) => Ok(Message::Signing(SigningMessage::SigningGenerationMessage(SigningGenerationMessage { session: message.session_id().clone().into(), sub_session: self.access_key.clone().into(), + session_nonce: self.nonce, message: message, }))), _ => Err(Error::InvalidMessage), @@ -517,6 +541,7 @@ impl SessionCore { SigningJobTransport { id: self.meta.id.clone(), access_key: self.access_key.clone(), + nonce: self.nonce, cluster: self.cluster.clone() } } @@ -535,6 +560,7 @@ impl JobTransport for SigningConsensusTransport { self.cluster.send(node, Message::Signing(SigningMessage::SigningConsensusMessage(SigningConsensusMessage { session: self.id.clone().into(), sub_session: self.access_key.clone().into(), + session_nonce: self.nonce, message: ConsensusMessage::InitializeConsensusSession(InitializeConsensusSession { requestor_signature: request.into(), }) @@ -545,6 +571,7 @@ impl JobTransport for SigningConsensusTransport { self.cluster.send(node, Message::Signing(SigningMessage::SigningConsensusMessage(SigningConsensusMessage { session: self.id.clone().into(), sub_session: self.access_key.clone().into(), + session_nonce: self.nonce, message: ConsensusMessage::ConfirmConsensusInitialization(ConfirmConsensusInitialization { is_confirmed: response, }) @@ -560,6 +587,7 @@ impl JobTransport for SigningJobTransport { self.cluster.send(node, Message::Signing(SigningMessage::RequestPartialSignature(RequestPartialSignature { session: self.id.clone().into(), sub_session: self.access_key.clone().into(), + session_nonce: self.nonce, request_id: request.id.into(), message_hash: request.message_hash.into(), nodes: request.other_nodes_ids.into_iter().map(Into::into).collect(), @@ -570,6 +598,7 @@ impl JobTransport for SigningJobTransport { self.cluster.send(node, Message::Signing(SigningMessage::PartialSignature(PartialSignature { session: self.id.clone().into(), sub_session: self.access_key.clone().into(), + session_nonce: self.nonce, request_id: response.request_id.into(), partial_signature: response.partial_signature.into(), }))) @@ -630,6 +659,7 @@ mod tests { key_share: gl_node.key_storage.get(&session_id).unwrap(), acl_storage: acl_storage, cluster: cluster.clone(), + nonce: 0, }, if i == 0 { signature.clone() } else { None }).unwrap(); nodes.insert(gl_node_id.clone(), Node { node_id: gl_node_id.clone(), cluster: cluster, session: session }); } @@ -764,6 +794,7 @@ mod tests { }, acl_storage: Arc::new(DummyAclStorage::default()), cluster: Arc::new(DummyCluster::new(self_node_id.clone())), + nonce: 0, }, Some(ethkey::sign(Random.generate().unwrap().secret(), &SessionId::default()).unwrap())) { Ok(_) => (), _ => panic!("unexpected"), @@ -794,6 +825,7 @@ mod tests { }, acl_storage: Arc::new(DummyAclStorage::default()), cluster: Arc::new(DummyCluster::new(self_node_id.clone())), + nonce: 0, }, Some(ethkey::sign(Random.generate().unwrap().secret(), &SessionId::default()).unwrap())) { Err(Error::InvalidNodesConfiguration) => (), _ => panic!("unexpected"), @@ -824,6 +856,7 @@ mod tests { }, acl_storage: Arc::new(DummyAclStorage::default()), cluster: Arc::new(DummyCluster::new(self_node_id.clone())), + nonce: 0, }, Some(ethkey::sign(Random.generate().unwrap().secret(), &SessionId::default()).unwrap())) { Err(Error::InvalidThreshold) => (), _ => panic!("unexpected"), @@ -862,6 +895,7 @@ mod tests { assert_eq!(sl.master().on_consensus_message(sl.nodes.keys().nth(1).unwrap(), &SigningConsensusMessage { session: SessionId::default().into(), sub_session: sl.master().core.access_key.clone().into(), + session_nonce: 0, message: ConsensusMessage::ConfirmConsensusInitialization(ConfirmConsensusInitialization { is_confirmed: true, }), @@ -874,8 +908,10 @@ mod tests { assert_eq!(sl.master().on_generation_message(sl.nodes.keys().nth(1).unwrap(), &SigningGenerationMessage { session: SessionId::default().into(), sub_session: sl.master().core.access_key.clone().into(), + session_nonce: 0, message: GenerationMessage::ConfirmInitialization(ConfirmInitialization { session: SessionId::default().into(), + session_nonce: 0, derived_point: Public::default().into(), }), }), Err(Error::InvalidStateForRequest)); @@ -893,8 +929,10 @@ mod tests { assert_eq!(slave1.on_generation_message(&slave2_id, &SigningGenerationMessage { session: SessionId::default().into(), sub_session: sl.master().core.access_key.clone().into(), + session_nonce: 0, message: GenerationMessage::InitializeSession(InitializeSession { session: SessionId::default().into(), + session_nonce: 0, author: Public::default().into(), nodes: BTreeMap::new(), threshold: 1, @@ -910,6 +948,7 @@ mod tests { assert_eq!(slave1.on_partial_signature_requested(sl.nodes.keys().nth(0).unwrap(), &RequestPartialSignature { session: SessionId::default().into(), sub_session: sl.master().core.access_key.clone().into(), + session_nonce: 0, request_id: Secret::from_str("0000000000000000000000000000000000000000000000000000000000000001").unwrap().into(), message_hash: H256::default().into(), nodes: Default::default(), @@ -922,6 +961,7 @@ mod tests { assert_eq!(sl.master().on_partial_signature_requested(sl.nodes.keys().nth(1).unwrap(), &RequestPartialSignature { session: SessionId::default().into(), sub_session: sl.master().core.access_key.clone().into(), + session_nonce: 0, request_id: Secret::from_str("0000000000000000000000000000000000000000000000000000000000000001").unwrap().into(), message_hash: H256::default().into(), nodes: Default::default(), @@ -983,4 +1023,19 @@ mod tests { _ => unreachable!(), } } + + #[test] + fn signing_message_fails_when_nonce_is_wrong() { + let (_, sl) = prepare_signing_sessions(1, 3); + assert_eq!(sl.master().process_message(sl.nodes.keys().nth(1).unwrap(), &SigningMessage::SigningGenerationMessage(SigningGenerationMessage { + session: SessionId::default().into(), + sub_session: sl.master().core.access_key.clone().into(), + session_nonce: 10, + message: GenerationMessage::ConfirmInitialization(ConfirmInitialization { + session: SessionId::default().into(), + session_nonce: 0, + derived_point: Public::default().into(), + }), + })), Err(Error::ReplayProtection)); + } } From 06ff866e9d415eb9ce85394036f30aab5f619cf6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Thu, 14 Sep 2017 19:32:06 +0200 Subject: [PATCH 3/9] Fix broken JavaScript tests (#6498) * Fixing/removing failing JS tests. * Fix javascript tests. --- js/src/api/subscriptions/manager.spec.js | 3 ++- js/src/api/subscriptions/personal.spec.js | 3 ++- js/src/mobx/hardwareStore.spec.js | 22 +++++-------------- .../redux/providers/signerMiddleware.spec.js | 6 +++++ js/src/views/Account/account.spec.js | 11 +++++++++- js/src/views/Accounts/accounts.spec.js | 6 ++++- js/src/views/ParityBar/accountStore.spec.js | 12 +--------- .../SignRequest/signRequest.spec.js | 2 +- 8 files changed, 33 insertions(+), 32 deletions(-) diff --git a/js/src/api/subscriptions/manager.spec.js b/js/src/api/subscriptions/manager.spec.js index df708a36d..05d645e6b 100644 --- a/js/src/api/subscriptions/manager.spec.js +++ b/js/src/api/subscriptions/manager.spec.js @@ -23,7 +23,8 @@ function newStub () { const manager = new Manager({ transport: { - isConnected: true + isConnected: true, + on: sinon.stub() } }); diff --git a/js/src/api/subscriptions/personal.spec.js b/js/src/api/subscriptions/personal.spec.js index ac046d250..3e950579c 100644 --- a/js/src/api/subscriptions/personal.spec.js +++ b/js/src/api/subscriptions/personal.spec.js @@ -37,7 +37,8 @@ function stubApi (accounts, info) { return { _calls, transport: { - isConnected: true + isConnected: true, + on: sinon.stub() }, parity: { accountsInfo: () => { diff --git a/js/src/mobx/hardwareStore.spec.js b/js/src/mobx/hardwareStore.spec.js index 784fc3f10..c620294f8 100644 --- a/js/src/mobx/hardwareStore.spec.js +++ b/js/src/mobx/hardwareStore.spec.js @@ -31,6 +31,12 @@ let store; function createApi () { api = { + transport: { + on: sinon.stub() + }, + pubsub: { + subscribeAndGetResult: sinon.stub().returns(Promise.reject(new Error('not connected'))) + }, parity: { hardwareAccountsInfo: sinon.stub().resolves({ ADDRESS: WALLET }), setAccountMeta: sinon.stub().resolves(true), @@ -195,22 +201,11 @@ describe('mobx/HardwareStore', () => { }); }); - describe('scanParity', () => { - beforeEach(() => { - return store.scanParity(); - }); - - it('calls parity_hardwareAccountsInfo', () => { - expect(api.parity.hardwareAccountsInfo).to.have.been.called; - }); - }); - describe('scan', () => { beforeEach(() => { sinon.spy(store, 'setScanning'); sinon.spy(store, 'setWallets'); sinon.spy(store, 'scanLedger'); - sinon.spy(store, 'scanParity'); return store.scan(); }); @@ -219,17 +214,12 @@ describe('mobx/HardwareStore', () => { store.setScanning.restore(); store.setWallets.restore(); store.scanLedger.restore(); - store.scanParity.restore(); }); it('calls scanLedger', () => { expect(store.scanLedger).to.have.been.called; }); - it('calls scanParity', () => { - expect(store.scanParity).to.have.been.called; - }); - it('sets and resets the scanning state', () => { expect(store.setScanning).to.have.been.calledWith(true); expect(store.setScanning).to.have.been.calledWith(false); diff --git a/js/src/redux/providers/signerMiddleware.spec.js b/js/src/redux/providers/signerMiddleware.spec.js index 1dcc19d75..4ee1123c1 100644 --- a/js/src/redux/providers/signerMiddleware.spec.js +++ b/js/src/redux/providers/signerMiddleware.spec.js @@ -48,6 +48,12 @@ let store; function createApi () { api = { + transport: { + on: sinon.stub() + }, + pubsub: { + subscribeAndGetResult: sinon.stub().returns(Promise.reject(new Error('not connected'))) + }, net: { version: sinon.stub().resolves('2') }, diff --git a/js/src/views/Account/account.spec.js b/js/src/views/Account/account.spec.js index 6a96d6300..d80376029 100644 --- a/js/src/views/Account/account.spec.js +++ b/js/src/views/Account/account.spec.js @@ -14,6 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . +import sinon from 'sinon'; import { shallow } from 'enzyme'; import React from 'react'; @@ -34,7 +35,15 @@ function render (props) { />, { context: { - store: createRedux() + store: createRedux(), + api: { + transport: { + on: sinon.stub() + }, + pubsub: { + subscribeAndGetResult: sinon.stub() + } + } } } ).find('Account').shallow(); diff --git a/js/src/views/Accounts/accounts.spec.js b/js/src/views/Accounts/accounts.spec.js index 3c6ab9439..3fad02643 100644 --- a/js/src/views/Accounts/accounts.spec.js +++ b/js/src/views/Accounts/accounts.spec.js @@ -27,7 +27,11 @@ let instance; let redux; function createApi () { - api = {}; + api = { + pubsub: { + subscribeAndGetResult: sinon.stub().returns(Promise.reject(new Error('uninitialized'))) + } + }; return api; } diff --git a/js/src/views/ParityBar/accountStore.spec.js b/js/src/views/ParityBar/accountStore.spec.js index 16cebf9e1..6935645d1 100644 --- a/js/src/views/ParityBar/accountStore.spec.js +++ b/js/src/views/ParityBar/accountStore.spec.js @@ -18,7 +18,7 @@ import sinon from 'sinon'; import AccountStore from './accountStore'; -import { ACCOUNT_DEFAULT, ACCOUNT_NEW, createApi } from './parityBar.test.js'; +import { ACCOUNT_NEW, createApi } from './parityBar.test.js'; let api; let store; @@ -89,16 +89,6 @@ describe('views/ParityBar/AccountStore', () => { }); }); - describe('loadDefaultAccount', () => { - beforeEach(() => { - return store.loadDefaultAccount(); - }); - - it('load and set the default account', () => { - expect(store.defaultAccount).to.equal(ACCOUNT_DEFAULT); - }); - }); - describe('makeDefaultAccount', () => { beforeEach(() => { return store.makeDefaultAccount(ACCOUNT_NEW); diff --git a/js/src/views/Signer/components/SignRequest/signRequest.spec.js b/js/src/views/Signer/components/SignRequest/signRequest.spec.js index ea5e274ed..ae197489b 100644 --- a/js/src/views/Signer/components/SignRequest/signRequest.spec.js +++ b/js/src/views/Signer/components/SignRequest/signRequest.spec.js @@ -73,7 +73,7 @@ function render () { return component; } -describe.only('views/Signer/components/SignRequest', () => { +describe('views/Signer/components/SignRequest', () => { beforeEach(() => { render(); }); From 79659bdc76cbd5d61c06e8c875682e58c625798a Mon Sep 17 00:00:00 2001 From: Alexey Date: Thu, 14 Sep 2017 20:32:29 +0300 Subject: [PATCH 4/9] WASM sha3 test (#6512) * sha3 test for empty input implemented * rename sha3-> keccak * update keccak test. Now it expects input to hash * fix gas_left in tests --- ethcore/res/wasm-tests | 2 +- ethcore/wasm/src/tests.rs | 59 ++++++++++++++++++++++++++++----------- 2 files changed, 44 insertions(+), 17 deletions(-) diff --git a/ethcore/res/wasm-tests b/ethcore/res/wasm-tests index 5fd27564f..fcac936bf 160000 --- a/ethcore/res/wasm-tests +++ b/ethcore/res/wasm-tests @@ -1 +1 @@ -Subproject commit 5fd27564f1ab49b25bb419bfc0cc68137e1f12f2 +Subproject commit fcac936bf68cc271a6a6ac088efb458f3a08f38a diff --git a/ethcore/wasm/src/tests.rs b/ethcore/wasm/src/tests.rs index b8643e625..22eeb23f5 100644 --- a/ethcore/wasm/src/tests.rs +++ b/ethcore/wasm/src/tests.rs @@ -88,7 +88,7 @@ fn logger() { }; println!("ext.store: {:?}", ext.store); - assert_eq!(gas_left, U256::from(99529)); + assert_eq!(gas_left, U256::from(98417)); let address_val: H256 = address.into(); assert_eq!( ext.store.get(&"0100000000000000000000000000000000000000000000000000000000000000".parse().unwrap()).expect("storage key to exist"), @@ -139,7 +139,7 @@ fn identity() { } }; - assert_eq!(gas_left, U256::from(99_762)); + assert_eq!(gas_left, U256::from(99_732)); assert_eq!( Address::from_slice(&result), @@ -173,7 +173,7 @@ fn dispersion() { } }; - assert_eq!(gas_left, U256::from(99_360)); + assert_eq!(gas_left, U256::from(99_421)); assert_eq!( result, @@ -202,7 +202,7 @@ fn suicide_not() { } }; - assert_eq!(gas_left, U256::from(99_668)); + assert_eq!(gas_left, U256::from(99_664)); assert_eq!( result, @@ -236,7 +236,7 @@ fn suicide() { } }; - assert_eq!(gas_left, U256::from(99_699)); + assert_eq!(gas_left, U256::from(99_420)); assert!(ext.suicides.contains(&refund)); } @@ -267,7 +267,7 @@ fn create() { assert!(ext.calls.contains( &FakeCall { call_type: FakeCallType::Create, - gas: U256::from(99_734), + gas: U256::from(98_908), sender_address: None, receive_address: None, value: Some(1_000_000_000.into()), @@ -275,7 +275,7 @@ fn create() { code_address: None, } )); - assert_eq!(gas_left, U256::from(99_686)); + assert_eq!(gas_left, U256::from(98_860)); } @@ -309,7 +309,7 @@ fn call_code() { assert!(ext.calls.contains( &FakeCall { call_type: FakeCallType::Call, - gas: U256::from(99_129), + gas: U256::from(99_108), sender_address: Some(sender), receive_address: Some(receiver), value: None, @@ -317,7 +317,7 @@ fn call_code() { code_address: Some("0d13710000000000000000000000000000000000".parse().unwrap()), } )); - assert_eq!(gas_left, U256::from(94262)); + assert_eq!(gas_left, U256::from(94_241)); // siphash result let res = LittleEndian::read_u32(&result[..]); @@ -354,7 +354,7 @@ fn call_static() { assert!(ext.calls.contains( &FakeCall { call_type: FakeCallType::Call, - gas: U256::from(99_129), + gas: U256::from(99_108), sender_address: Some(sender), receive_address: Some(receiver), value: None, @@ -362,7 +362,7 @@ fn call_static() { code_address: Some("13077bfb00000000000000000000000000000000".parse().unwrap()), } )); - assert_eq!(gas_left, U256::from(94262)); + assert_eq!(gas_left, U256::from(94_241)); // siphash result let res = LittleEndian::read_u32(&result[..]); @@ -388,7 +388,7 @@ fn realloc() { GasLeft::NeedsReturn { gas_left: gas, data: result, apply_state: _apply } => (gas, result.to_vec()), } }; - assert_eq!(gas_left, U256::from(99522)); + assert_eq!(gas_left, U256::from(99_562)); assert_eq!(result, vec![0u8; 2]); } @@ -414,10 +414,37 @@ fn storage_read() { } }; - assert_eq!(gas_left, U256::from(99800)); + assert_eq!(gas_left, U256::from(99_673)); assert_eq!(Address::from(&result[12..32]), address); } +// Tests keccak calculation +// keccak.wasm runs wasm-std::keccak function on data param and returns hash +#[test] +fn keccak() { + ::ethcore_logger::init_log(); + let code = load_sample!("keccak.wasm"); + + let mut params = ActionParams::default(); + params.gas = U256::from(100_000); + params.code = Some(Arc::new(code)); + params.data = Some(b"something".to_vec()); + let mut ext = FakeExt::new(); + + let (gas_left, result) = { + let mut interpreter = wasm_interpreter(); + let result = interpreter.exec(params, &mut ext).expect("Interpreter to execute without any errors"); + match result { + GasLeft::Known(_) => { panic!("keccak should return payload"); }, + GasLeft::NeedsReturn { gas_left: gas, data: result, apply_state: _apply } => (gas, result.to_vec()), + } + }; + + assert_eq!(H256::from_slice(&result), H256::from("68371d7e884c168ae2022c82bd837d51837718a7f7dfb7aa3f753074a35e1d87")); + assert_eq!(gas_left, U256::from(84003)); +} + + macro_rules! reqrep_test { ($name: expr, $input: expr) => { reqrep_test!($name, $input, vm::EnvInfo::default(), HashMap::new()) @@ -551,7 +578,7 @@ fn math_div() { } ).expect("Interpreter to execute without any errors"); - assert_eq!(gas_left, U256::from(91510)); + assert_eq!(gas_left, U256::from(91_562)); assert_eq!( U256::from_dec_str("1125000").unwrap(), (&result[..]).into() @@ -643,5 +670,5 @@ fn externs() { "Gas limit requested and returned does not match" ); - assert_eq!(gas_left, U256::from(97588)); -} \ No newline at end of file + assert_eq!(gas_left, U256::from(95_999)); +} From ade37be25b57d2140b02a1b1368ca2979f3309e7 Mon Sep 17 00:00:00 2001 From: Hawstein Date: Thu, 7 Sep 2017 02:47:45 +0800 Subject: [PATCH 5/9] separate trie from util and make its dependencies into libs: * bytes * hashdb * memorydb * nibbleslice * nibblevec --- Cargo.lock | 87 +++++++++++++++++++ Cargo.toml | 1 + dapps/Cargo.toml | 1 + dapps/src/apps/fetcher/mod.rs | 2 +- dapps/src/lib.rs | 1 + dapps/src/tests/helpers/registrar.rs | 3 +- ethcore/Cargo.toml | 4 + ethcore/light/Cargo.toml | 3 + ethcore/light/src/cht.rs | 5 +- ethcore/light/src/lib.rs | 3 + ethcore/light/src/on_demand/request.rs | 11 +-- ethcore/light/src/types/request/mod.rs | 11 +-- ethcore/node_filter/Cargo.toml | 1 + ethcore/node_filter/src/lib.rs | 4 +- ethcore/res/wasm-tests | 2 +- ethcore/src/block.rs | 3 +- ethcore/src/blockchain/best_block.rs | 2 +- ethcore/src/blockchain/blockchain.rs | 1 + ethcore/src/blockchain/generator/block.rs | 2 +- ethcore/src/blockchain/generator/complete.rs | 2 +- ethcore/src/blockchain/generator/generator.rs | 2 +- ethcore/src/builtin.rs | 4 +- ethcore/src/client/chain_notify.rs | 2 +- ethcore/src/client/client.rs | 9 +- ethcore/src/client/error.rs | 2 +- ethcore/src/client/evm_test_client.rs | 8 +- ethcore/src/client/test_client.rs | 1 + ethcore/src/client/traits.rs | 5 +- ethcore/src/engines/authority_round/mod.rs | 1 + ethcore/src/engines/mod.rs | 2 + ethcore/src/engines/tendermint/message.rs | 1 + ethcore/src/engines/tendermint/mod.rs | 2 + ethcore/src/engines/validator_set/contract.rs | 2 + ethcore/src/engines/validator_set/mod.rs | 3 +- ethcore/src/engines/validator_set/multi.rs | 3 +- .../engines/validator_set/safe_contract.rs | 1 + ethcore/src/engines/validator_set/test.rs | 3 +- ethcore/src/engines/vote_collector.rs | 1 + ethcore/src/error.rs | 1 + ethcore/src/executed.rs | 4 +- ethcore/src/executive.rs | 3 +- ethcore/src/externalities.rs | 1 + ethcore/src/factory.rs | 4 +- ethcore/src/header.rs | 1 + ethcore/src/json_tests/executive.rs | 2 + ethcore/src/json_tests/trie.rs | 8 +- ethcore/src/lib.rs | 4 + ethcore/src/migrations/state/v7.rs | 3 +- ethcore/src/migrations/v10.rs | 4 +- ethcore/src/miner/miner.rs | 1 + ethcore/src/miner/mod.rs | 3 +- ethcore/src/pod_account.rs | 2 + ethcore/src/service.rs | 1 + ethcore/src/snapshot/account.rs | 7 +- ethcore/src/snapshot/block.rs | 5 +- ethcore/src/snapshot/consensus/authority.rs | 3 +- ethcore/src/snapshot/consensus/work.rs | 3 +- ethcore/src/snapshot/error.rs | 2 +- ethcore/src/snapshot/io.rs | 2 +- ethcore/src/snapshot/mod.rs | 5 +- ethcore/src/snapshot/service.rs | 5 +- .../src/snapshot/snapshot_service_trait.rs | 2 +- ethcore/src/snapshot/tests/helpers.rs | 6 +- ethcore/src/snapshot/tests/state.rs | 4 +- ethcore/src/snapshot/watcher.rs | 2 +- ethcore/src/spec/spec.rs | 1 + ethcore/src/state/account.rs | 8 +- ethcore/src/state/backend.rs | 2 +- ethcore/src/state/mod.rs | 7 +- ethcore/src/state_db.rs | 2 +- ethcore/src/tests/evm.rs | 1 + ethcore/src/tests/helpers.rs | 1 + ethcore/src/trace/executive_tracer.rs | 3 +- ethcore/src/trace/mod.rs | 3 +- ethcore/src/trace/noop_tracer.rs | 3 +- ethcore/src/trace/types/trace.rs | 3 +- ethcore/src/transaction.rs | 3 +- ethcore/src/tx_filter.rs | 3 +- ethcore/src/verification/queue/kind.rs | 2 +- ethcore/src/verification/verification.rs | 4 +- ethcore/src/views/block.rs | 2 +- ethcore/src/views/body.rs | 2 +- ethcore/src/views/header.rs | 3 +- ethcore/src/views/transaction.rs | 2 +- ethcore/types/Cargo.toml | 1 + ethcore/types/src/account_diff.rs | 4 +- ethcore/types/src/lib.rs | 1 + ethcore/types/src/log_entry.rs | 3 +- ethcore/types/src/snapshot_manifest.rs | 2 +- ethcore/vm/Cargo.toml | 2 + ethcore/vm/src/action_params.rs | 3 +- ethcore/vm/src/error.rs | 2 +- ethcore/vm/src/ext.rs | 1 + ethcore/vm/src/lib.rs | 2 + ethcore/vm/src/tests.rs | 3 +- evmbin/Cargo.toml | 1 + evmbin/src/display/json.rs | 2 +- evmbin/src/display/simple.rs | 2 +- evmbin/src/main.rs | 4 +- hash-fetch/Cargo.toml | 1 + hash-fetch/src/lib.rs | 1 + hash-fetch/src/urlhint.rs | 6 +- ipc/tests/Cargo.toml | 1 + ipc/tests/binary.rs.in | 2 +- ipc/tests/run.rs | 1 + ipfs/Cargo.toml | 1 + ipfs/src/lib.rs | 1 + ipfs/src/route.rs | 2 +- parity/blockchain.rs | 3 +- parity/configuration.rs | 3 +- parity/dapps.rs | 3 +- parity/informant.rs | 2 +- parity/main.rs | 1 + rpc/Cargo.toml | 1 + rpc/src/lib.rs | 1 + rpc/src/v1/helpers/dispatch.rs | 3 +- rpc/src/v1/helpers/requests.rs | 3 +- rpc/src/v1/helpers/secretstore.rs | 4 +- rpc/src/v1/impls/eth_pubsub.rs | 2 +- rpc/src/v1/impls/personal.rs | 3 +- rpc/src/v1/tests/helpers/miner_service.rs | 3 +- rpc/src/v1/tests/helpers/snapshot_service.rs | 2 +- rpc/src/v1/tests/mocked/parity.rs | 2 +- rpc/src/v1/tests/mocked/signer.rs | 3 +- rpc/src/v1/tests/mocked/signing.rs | 3 +- rpc/src/v1/types/confirmations.rs | 2 +- secret_store/Cargo.toml | 1 + secret_store/src/acl_storage.rs | 3 +- secret_store/src/key_server_set.rs | 3 +- secret_store/src/lib.rs | 1 + secret_store/src/serialization.rs | 2 +- secret_store/src/types/all.rs | 6 +- sync/Cargo.toml | 1 + sync/src/api.rs | 2 +- sync/src/blocks.rs | 1 + sync/src/chain.rs | 4 +- sync/src/lib.rs | 1 + sync/src/snapshot.rs | 2 +- sync/src/sync_io.rs | 2 +- sync/src/tests/helpers.rs | 2 +- sync/src/tests/snapshot.rs | 2 +- updater/Cargo.toml | 1 + updater/src/lib.rs | 1 + updater/src/updater.rs | 3 +- util/Cargo.toml | 6 ++ util/benches/trie.rs | 9 +- util/bytes/Cargo.toml | 6 ++ util/{src/bytes.rs => bytes/src/lib.rs} | 0 util/hashdb/Cargo.toml | 8 ++ util/{src/hashdb.rs => hashdb/src/lib.rs} | 72 +-------------- util/memorydb/Cargo.toml | 13 +++ util/{src/memorydb.rs => memorydb/src/lib.rs} | 19 ++-- util/network/Cargo.toml | 1 + util/network/src/connection.rs | 4 +- util/network/src/discovery.rs | 2 +- util/network/src/handshake.rs | 2 +- util/network/src/lib.rs | 1 + util/network/src/tests.rs | 2 +- util/nibbleslice/Cargo.toml | 7 ++ .../nibbleslice.rs => nibbleslice/src/lib.rs} | 6 +- util/nibblevec/Cargo.toml | 8 ++ .../nibblevec.rs => nibblevec/src/lib.rs} | 2 + util/src/journaldb/archivedb.rs | 4 +- util/src/journaldb/earlymergedb.rs | 2 +- util/src/journaldb/overlayrecentdb.rs | 2 +- util/src/journaldb/refcounteddb.rs | 3 +- util/src/journaldb/traits.rs | 3 +- util/src/kvdb.rs | 3 +- util/src/lib.rs | 12 +-- util/src/misc.rs | 2 +- util/trie/Cargo.toml | 21 +++++ util/{src/trie => trie/src}/fatdb.rs | 3 +- util/{src/trie => trie/src}/fatdbmut.rs | 0 util/{src/trie/mod.rs => trie/src/lib.rs} | 14 +++ util/{src/trie => trie/src}/lookup.rs | 0 util/{src/trie => trie/src}/node.rs | 0 util/{src/trie => trie/src}/recorder.rs | 4 +- util/{src/trie => trie/src}/sectriedb.rs | 2 +- util/{src/trie => trie/src}/sectriedbmut.rs | 0 util/{src/trie => trie/src}/standardmap.rs | 0 util/{src/trie => trie/src}/triedb.rs | 12 +-- util/{src/trie => trie/src}/triedbmut.rs | 18 ++-- 182 files changed, 497 insertions(+), 251 deletions(-) create mode 100644 util/bytes/Cargo.toml rename util/{src/bytes.rs => bytes/src/lib.rs} (100%) create mode 100644 util/hashdb/Cargo.toml rename util/{src/hashdb.rs => hashdb/src/lib.rs} (57%) create mode 100644 util/memorydb/Cargo.toml rename util/{src/memorydb.rs => memorydb/src/lib.rs} (96%) create mode 100644 util/nibbleslice/Cargo.toml rename util/{src/nibbleslice.rs => nibbleslice/src/lib.rs} (99%) create mode 100644 util/nibblevec/Cargo.toml rename util/{src/nibblevec.rs => nibblevec/src/lib.rs} (98%) create mode 100644 util/trie/Cargo.toml rename util/{src/trie => trie/src}/fatdb.rs (98%) rename util/{src/trie => trie/src}/fatdbmut.rs (100%) rename util/{src/trie/mod.rs => trie/src/lib.rs} (96%) rename util/{src/trie => trie/src}/lookup.rs (100%) rename util/{src/trie => trie/src}/node.rs (100%) rename util/{src/trie => trie/src}/recorder.rs (98%) rename util/{src/trie => trie/src}/sectriedb.rs (98%) rename util/{src/trie => trie/src}/sectriedbmut.rs (100%) rename util/{src/trie => trie/src}/standardmap.rs (100%) rename util/{src/trie => trie/src}/triedb.rs (98%) rename util/{src/trie => trie/src}/triedbmut.rs (99%) diff --git a/Cargo.lock b/Cargo.lock index a29e516dc..e3fd78eb9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -352,6 +352,7 @@ version = "0.1.0" dependencies = [ "bloomable 0.1.0", "ethcore-bigint 0.1.3", + "ethcore-bytes 0.1.0", "ethcore-util 1.8.0", "ethjson 0.1.0", "hash 0.1.0", @@ -559,6 +560,7 @@ dependencies = [ "ethash 1.8.0", "ethcore-bigint 0.1.3", "ethcore-bloom-journal 0.1.0", + "ethcore-bytes 0.1.0", "ethcore-devtools 1.8.0", "ethcore-io 1.8.0", "ethcore-ipc 1.8.0", @@ -575,12 +577,14 @@ dependencies = [ "hardware-wallet 1.8.0", "hash 0.1.0", "heapsize 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "hashdb 0.1.0", "hyper 0.10.0-a.0 (git+https://github.com/paritytech/hyper)", "itertools 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "linked-hash-map 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "lru-cache 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "memorydb 0.1.0", "native-contracts 0.1.0", "num 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.6.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -598,6 +602,7 @@ dependencies = [ "table 0.1.0", "time 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)", "transient-hashmap 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "trie 0.1.0", "triehash 0.1.0", "unexpected 0.1.0", "using_queue 0.1.0", @@ -624,6 +629,10 @@ dependencies = [ "siphasher 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "ethcore-bytes" +version = "0.1.0" + [[package]] name = "ethcore-devtools" version = "1.8.0" @@ -693,6 +702,7 @@ dependencies = [ name = "ethcore-ipc-tests" version = "0.1.0" dependencies = [ + "ethcore-bytes 0.1.0", "ethcore-devtools 1.8.0", "ethcore-ipc 1.8.0", "ethcore-ipc-codegen 1.8.0", @@ -710,6 +720,7 @@ dependencies = [ "bincode 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "ethcore 1.8.0", "ethcore-bigint 0.1.3", + "ethcore-bytes 0.1.0", "ethcore-devtools 1.8.0", "ethcore-io 1.8.0", "ethcore-ipc 1.8.0", @@ -724,6 +735,7 @@ dependencies = [ "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)", + "memorydb 0.1.0", "rlp 0.2.0", "rlp_derive 0.1.0", "serde 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)", @@ -731,6 +743,7 @@ dependencies = [ "smallvec 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", "stats 0.1.0", "time 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)", + "trie 0.1.0", "triehash 0.1.0", "vm 0.1.0", ] @@ -758,6 +771,7 @@ dependencies = [ "bytes 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", "clippy 0.0.103 (registry+https://github.com/rust-lang/crates.io-index)", "ethcore-bigint 0.1.3", + "ethcore-bytes 0.1.0", "ethcore-devtools 1.8.0", "ethcore-io 1.8.0", "ethcore-logger 1.8.0", @@ -790,6 +804,7 @@ dependencies = [ "ethabi 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "ethcore 1.8.0", "ethcore-bigint 0.1.3", + "ethcore-bytes 0.1.0", "ethcore-devtools 1.8.0", "ethcore-ipc 1.8.0", "ethcore-ipc-codegen 1.8.0", @@ -852,6 +867,7 @@ dependencies = [ "eth-secp256k1 0.5.6 (git+https://github.com/paritytech/rust-secp256k1)", "ethcore-bigint 0.1.3", "ethcore-bloom-journal 0.1.0", + "ethcore-bytes 0.1.0", "ethcore-devtools 1.8.0", "ethcore-logger 1.8.0", "hash 0.1.0", @@ -861,12 +877,17 @@ dependencies = [ "lru-cache 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", "regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "hashdb 0.1.0", + "memorydb 0.1.0", + "nibbleslice 0.1.0", + "nibblevec 0.1.0", "rlp 0.2.0", "rocksdb 0.4.5 (git+https://github.com/paritytech/rust-rocksdb)", "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "target_info 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "tiny-keccak 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "trie 0.1.0", "triehash 0.1.0", "vergen 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -965,6 +986,7 @@ dependencies = [ "env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", "ethcore 1.8.0", "ethcore-bigint 0.1.3", + "ethcore-bytes 0.1.0", "ethcore-devtools 1.8.0", "ethcore-io 1.8.0", "ethcore-ipc 1.8.0", @@ -1017,6 +1039,7 @@ dependencies = [ "docopt 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", "ethcore 1.8.0", "ethcore-bigint 0.1.3", + "ethcore-bytes 0.1.0", "ethcore-util 1.8.0", "ethjson 0.1.0", "evm 0.1.0", @@ -1147,6 +1170,14 @@ dependencies = [ "tiny-keccak 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "hashdb" +version = "0.1.0" +dependencies = [ + "elastic-array 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ethcore-bigint 0.1.3", +] + [[package]] name = "heapsize" version = "0.4.1" @@ -1545,6 +1576,19 @@ dependencies = [ "libc 0.2.30 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "memorydb" +version = "0.1.0" +dependencies = [ + "bigint 4.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "elastic-array 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ethcore-bigint 0.1.3", + "hash 0.1.0", + "hashdb 0.1.0", + "heapsize 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rlp 0.2.0", +] + [[package]] name = "mime" version = "0.2.6" @@ -1711,12 +1755,28 @@ dependencies = [ "ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "nibbleslice" +version = "0.1.0" +dependencies = [ + "elastic-array 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "nibblevec" +version = "0.1.0" +dependencies = [ + "elastic-array 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "nibbleslice 0.1.0", +] + [[package]] name = "node-filter" version = "1.8.0" dependencies = [ "ethcore 1.8.0", "ethcore-bigint 0.1.3", + "ethcore-bytes 0.1.0", "ethcore-io 1.8.0", "ethcore-network 1.8.0", "ethcore-util 1.8.0", @@ -1929,6 +1989,7 @@ dependencies = [ "env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", "ethcore 1.8.0", "ethcore-bigint 0.1.3", + "ethcore-bytes 0.1.0", "ethcore-devtools 1.8.0", "ethcore-io 1.8.0", "ethcore-ipc 1.8.0", @@ -1992,6 +2053,7 @@ dependencies = [ "clippy 0.0.103 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", "ethcore-bigint 0.1.3", + "ethcore-bytes 0.1.0", "ethcore-devtools 1.8.0", "ethcore-util 1.8.0", "fetch 0.1.0", @@ -2041,6 +2103,7 @@ version = "1.8.0" dependencies = [ "ethabi 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "ethcore-bigint 0.1.3", + "ethcore-bytes 0.1.0", "ethcore-util 1.8.0", "fetch 0.1.0", "futures 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2062,6 +2125,7 @@ dependencies = [ "cid 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "ethcore 1.8.0", "ethcore-bigint 0.1.3", + "ethcore-bytes 0.1.0", "ethcore-util 1.8.0", "jsonrpc-http-server 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)", "mime 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2102,6 +2166,7 @@ dependencies = [ "ethash 1.8.0", "ethcore 1.8.0", "ethcore-bigint 0.1.3", + "ethcore-bytes 0.1.0", "ethcore-devtools 1.8.0", "ethcore-io 1.8.0", "ethcore-ipc 1.8.0", @@ -2218,6 +2283,7 @@ dependencies = [ "ethabi 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "ethcore 1.8.0", "ethcore-bigint 0.1.3", + "ethcore-bytes 0.1.0", "ethcore-ipc 1.8.0", "ethcore-ipc-codegen 1.8.0", "ethcore-util 1.8.0", @@ -3238,6 +3304,25 @@ dependencies = [ "protobuf 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "trie" +version = "0.1.0" +dependencies = [ + "elastic-array 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ethcore-bigint 0.1.3", + "ethcore-bytes 0.1.0", + "ethcore-logger 1.8.0", + "hash 0.1.0", + "hashdb 0.1.0", + "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "memorydb 0.1.0", + "nibbleslice 0.1.0", + "nibblevec 0.1.0", + "rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", + "rlp 0.2.0", + "triehash 0.1.0", +] + [[package]] name = "triehash" version = "0.1.0" @@ -3372,6 +3457,7 @@ dependencies = [ "byteorder 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "common-types 0.1.0", "ethcore-bigint 0.1.3", + "ethcore-bytes 0.1.0", "ethcore-util 1.8.0", "ethjson 0.1.0", "evmjit 1.8.0", @@ -3379,6 +3465,7 @@ dependencies = [ "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "rlp 0.2.0", + "trie 0.1.0", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 5f3a6ad73..68a288072 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -35,6 +35,7 @@ jsonrpc-core = { git = "https://github.com/paritytech/jsonrpc.git", branch = "pa ethsync = { path = "sync" } ethcore = { path = "ethcore" } ethcore-util = { path = "util" } +ethcore-bytes = { path = "util/bytes" } ethcore-bigint = { path = "util/bigint" } ethcore-io = { path = "util/io" } ethcore-devtools = { path = "devtools" } diff --git a/dapps/Cargo.toml b/dapps/Cargo.toml index 2c55b79cb..cb384d011 100644 --- a/dapps/Cargo.toml +++ b/dapps/Cargo.toml @@ -32,6 +32,7 @@ jsonrpc-http-server = { git = "https://github.com/paritytech/jsonrpc.git", branc ethcore-util = { path = "../util" } ethcore-bigint = { path = "../util/bigint" } +ethcore-bytes = { path = "../util/bytes" } fetch = { path = "../util/fetch" } node-health = { path = "./node-health" } parity-hash-fetch = { path = "../hash-fetch" } diff --git a/dapps/src/apps/fetcher/mod.rs b/dapps/src/apps/fetcher/mod.rs index fe529d772..8a11f7a9b 100644 --- a/dapps/src/apps/fetcher/mod.rs +++ b/dapps/src/apps/fetcher/mod.rs @@ -261,7 +261,7 @@ impl Fetcher for ContentFetcher { mod tests { use std::env; use std::sync::Arc; - use util::Bytes; + use bytes::Bytes; use fetch::{Fetch, Client}; use futures::{future, Future, BoxFuture}; use hash_fetch::urlhint::{URLHint, URLHintResult}; diff --git a/dapps/src/lib.rs b/dapps/src/lib.rs index 0cb0833af..e579439d0 100644 --- a/dapps/src/lib.rs +++ b/dapps/src/lib.rs @@ -39,6 +39,7 @@ extern crate jsonrpc_http_server; extern crate ethcore_util as util; extern crate ethcore_bigint as bigint; +extern crate ethcore_bytes as bytes; extern crate fetch; extern crate node_health; extern crate parity_dapps_glue as parity_dapps; diff --git a/dapps/src/tests/helpers/registrar.rs b/dapps/src/tests/helpers/registrar.rs index 41f296f8d..4df7e31b6 100644 --- a/dapps/src/tests/helpers/registrar.rs +++ b/dapps/src/tests/helpers/registrar.rs @@ -21,7 +21,8 @@ use rustc_hex::FromHex; use hash_fetch::urlhint::ContractClient; use bigint::hash::H256; -use util::{Bytes, Address, ToPretty}; +use util::Address; +use bytes::{Bytes, ToPretty}; use parking_lot::Mutex; const REGISTRAR: &'static str = "8e4e9b13d4b45cb0befc93c3061b1408f67316b2"; diff --git a/ethcore/Cargo.toml b/ethcore/Cargo.toml index 5a2f7327a..638454aac 100644 --- a/ethcore/Cargo.toml +++ b/ethcore/Cargo.toml @@ -23,6 +23,10 @@ env_logger = "0.4" ethabi = "2.0" ethash = { path = "../ethash" } ethcore-bloom-journal = { path = "../util/bloom" } +ethcore-bytes = { path = "../util/bytes" } +hashdb = { path = "../util/hashdb" } +memorydb = { path = "../util/memorydb" } +trie = { path = "../util/trie" } ethcore-devtools = { path = "../devtools" } ethcore-io = { path = "../util/io" } ethcore-ipc = { path = "../ipc/rpc" } diff --git a/ethcore/light/Cargo.toml b/ethcore/light/Cargo.toml index a96a7fb76..e7cf959ad 100644 --- a/ethcore/light/Cargo.toml +++ b/ethcore/light/Cargo.toml @@ -15,6 +15,9 @@ log = "0.3" ethcore = { path = ".."} ethcore-util = { path = "../../util" } ethcore-bigint = { path = "../../util/bigint" } +ethcore-bytes = { path = "../../util/bytes" } +memorydb = { path = "../../util/memorydb" } +trie = { path = "../../util/trie" } ethcore-network = { path = "../../util/network" } ethcore-io = { path = "../../util/io" } ethcore-ipc = { path = "../../ipc/rpc", optional = true } diff --git a/ethcore/light/src/cht.rs b/ethcore/light/src/cht.rs index d4d1f2294..d8a07fab9 100644 --- a/ethcore/light/src/cht.rs +++ b/ethcore/light/src/cht.rs @@ -23,8 +23,9 @@ use ethcore::ids::BlockId; use bigint::prelude::U256; use bigint::hash::H256; -use util::{Bytes, HashDB, MemoryDB}; -use util::trie::{self, TrieMut, TrieDBMut, Trie, TrieDB, Recorder}; +use util::{HashDB, MemoryDB}; +use bytes::Bytes; +use trie::{self, TrieMut, TrieDBMut, Trie, TrieDB, Recorder}; use rlp::{RlpStream, UntrustedRlp}; // encode a key. diff --git a/ethcore/light/src/lib.rs b/ethcore/light/src/lib.rs index 07f862a1a..4cf0b3e58 100644 --- a/ethcore/light/src/lib.rs +++ b/ethcore/light/src/lib.rs @@ -71,11 +71,14 @@ extern crate ethcore_io as io; extern crate ethcore_network as network; extern crate ethcore_util as util; extern crate ethcore_bigint as bigint; +extern crate ethcore_bytes as bytes; extern crate ethcore; extern crate evm; extern crate heapsize; extern crate futures; extern crate itertools; +extern crate memorydb; +extern crate trie; extern crate rand; extern crate rlp; extern crate parking_lot; diff --git a/ethcore/light/src/on_demand/request.rs b/ethcore/light/src/on_demand/request.rs index d9afd5582..162e2bb3a 100644 --- a/ethcore/light/src/on_demand/request.rs +++ b/ethcore/light/src/on_demand/request.rs @@ -33,9 +33,10 @@ use rlp::{RlpStream, UntrustedRlp}; use bigint::prelude::U256; use bigint::hash::H256; use parking_lot::Mutex; -use util::{Address, Bytes, DBValue, HashDB}; -use util::memorydb::MemoryDB; -use util::trie::{Trie, TrieDB, TrieError}; +use util::{Address, DBValue, HashDB}; +use bytes::Bytes; +use memorydb::MemoryDB; +use trie::{Trie, TrieDB, TrieError}; const SUPPLIED_MATCHES: &'static str = "supplied responses always match produced requests; enforced by `check_response`; qed"; @@ -896,8 +897,8 @@ mod tests { use bigint::hash::H256; use util::{MemoryDB, Address}; use parking_lot::Mutex; - use util::trie::{Trie, TrieMut, SecTrieDB, SecTrieDBMut}; - use util::trie::recorder::Recorder; + use trie::{Trie, TrieMut, SecTrieDB, SecTrieDBMut}; + use trie::recorder::Recorder; use hash::keccak; use ethcore::client::{BlockChainClient, TestBlockChainClient, EachBlockWith}; diff --git a/ethcore/light/src/types/request/mod.rs b/ethcore/light/src/types/request/mod.rs index c623ca656..c33d8b4cc 100644 --- a/ethcore/light/src/types/request/mod.rs +++ b/ethcore/light/src/types/request/mod.rs @@ -789,7 +789,7 @@ pub mod header_proof { use rlp::{Encodable, Decodable, DecoderError, RlpStream, UntrustedRlp}; use bigint::prelude::U256; use bigint::hash::H256; - use util::Bytes; + use bytes::Bytes; /// Potentially incomplete header proof request. #[derive(Debug, Clone, PartialEq, Eq, RlpEncodable, RlpDecodable)] @@ -1120,7 +1120,7 @@ pub mod account { use super::{Field, NoSuchOutput, OutputKind, Output}; use bigint::prelude::U256; use bigint::hash::H256; - use util::Bytes; + use bytes::Bytes; /// Potentially incomplete request for an account proof. #[derive(Debug, Clone, PartialEq, Eq, RlpEncodable, RlpDecodable)] @@ -1220,7 +1220,7 @@ pub mod account { pub mod storage { use super::{Field, NoSuchOutput, OutputKind, Output}; use bigint::hash::H256; - use util::Bytes; + use bytes::Bytes; /// Potentially incomplete request for an storage proof. #[derive(Debug, Clone, PartialEq, Eq, RlpEncodable, RlpDecodable)] @@ -1329,7 +1329,7 @@ pub mod storage { pub mod contract_code { use super::{Field, NoSuchOutput, OutputKind, Output}; use bigint::hash::H256; - use util::Bytes; + use bytes::Bytes; /// Potentially incomplete contract code request. #[derive(Debug, Clone, PartialEq, Eq, RlpEncodable, RlpDecodable)] @@ -1417,7 +1417,8 @@ pub mod execution { use rlp::{Encodable, Decodable, DecoderError, RlpStream, UntrustedRlp}; use bigint::prelude::U256; use bigint::hash::H256; - use util::{Bytes, Address, DBValue}; + use util::{Address, DBValue}; + use bytes::Bytes; /// Potentially incomplete execution proof request. #[derive(Debug, Clone, PartialEq, Eq, RlpEncodable, RlpDecodable)] diff --git a/ethcore/node_filter/Cargo.toml b/ethcore/node_filter/Cargo.toml index 2d70c3461..6043c0e5d 100644 --- a/ethcore/node_filter/Cargo.toml +++ b/ethcore/node_filter/Cargo.toml @@ -10,6 +10,7 @@ authors = ["Parity Technologies "] ethcore = { path = ".."} ethcore-util = { path = "../../util" } ethcore-bigint = { path = "../../util/bigint" } +ethcore-bytes = { path = "../../util/bytes" } ethcore-io = { path = "../../util/io" } ethcore-network = { path = "../../util/network" } native-contracts = { path = "../native_contracts" } diff --git a/ethcore/node_filter/src/lib.rs b/ethcore/node_filter/src/lib.rs index 16a1bdd8f..276e6a5d7 100644 --- a/ethcore/node_filter/src/lib.rs +++ b/ethcore/node_filter/src/lib.rs @@ -19,6 +19,7 @@ extern crate ethcore; extern crate ethcore_util as util; extern crate ethcore_bigint as bigint; +extern crate ethcore_bytes as bytes; extern crate ethcore_network as network; extern crate native_contracts; extern crate futures; @@ -32,7 +33,8 @@ use native_contracts::PeerSet as Contract; use network::{NodeId, ConnectionFilter, ConnectionDirection}; use ethcore::client::{BlockChainClient, BlockId, ChainNotify}; use bigint::hash::H256; -use util::{Address, Bytes}; +use util::Address; +use bytes::Bytes; use parking_lot::Mutex; use futures::Future; diff --git a/ethcore/res/wasm-tests b/ethcore/res/wasm-tests index fcac936bf..5fd27564f 160000 --- a/ethcore/res/wasm-tests +++ b/ethcore/res/wasm-tests @@ -1 +1 @@ -Subproject commit fcac936bf68cc271a6a6ac088efb458f3a08f38a +Subproject commit 5fd27564f1ab49b25bb419bfc0cc68137e1f12f2 diff --git a/ethcore/src/block.rs b/ethcore/src/block.rs index d6fa65a41..63f79335d 100644 --- a/ethcore/src/block.rs +++ b/ethcore/src/block.rs @@ -25,7 +25,8 @@ use triehash::ordered_trie_root; use rlp::{UntrustedRlp, RlpStream, Encodable, Decodable, DecoderError}; use bigint::prelude::U256; use bigint::hash::H256; -use util::{Bytes, Address}; +use util::Address; +use bytes::Bytes; use unexpected::{Mismatch, OutOfBounds}; use basic_types::{LogBloom, Seal}; diff --git a/ethcore/src/blockchain/best_block.rs b/ethcore/src/blockchain/best_block.rs index fd41f71e8..baf8819c5 100644 --- a/ethcore/src/blockchain/best_block.rs +++ b/ethcore/src/blockchain/best_block.rs @@ -16,7 +16,7 @@ use bigint::prelude::U256; use bigint::hash::H256; -use util::Bytes; +use bytes::Bytes; use header::BlockNumber; /// Best block info. diff --git a/ethcore/src/blockchain/blockchain.rs b/ethcore/src/blockchain/blockchain.rs index d44d8ff9b..88bed91a3 100644 --- a/ethcore/src/blockchain/blockchain.rs +++ b/ethcore/src/blockchain/blockchain.rs @@ -25,6 +25,7 @@ use heapsize::HeapSizeOf; use bigint::prelude::U256; use bigint::hash::{H256, H2048}; use parking_lot::{Mutex, RwLock}; +use bytes::Bytes; use util::*; use rlp::*; use header::*; diff --git a/ethcore/src/blockchain/generator/block.rs b/ethcore/src/blockchain/generator/block.rs index d5243dc66..4aba039a3 100644 --- a/ethcore/src/blockchain/generator/block.rs +++ b/ethcore/src/blockchain/generator/block.rs @@ -16,7 +16,7 @@ use rlp::*; use bigint::hash::{H256, H2048}; -use util::bytes::Bytes; +use bytes::Bytes; use header::Header; use transaction::SignedTransaction; diff --git a/ethcore/src/blockchain/generator/complete.rs b/ethcore/src/blockchain/generator/complete.rs index be5695d36..7b9bc572a 100644 --- a/ethcore/src/blockchain/generator/complete.rs +++ b/ethcore/src/blockchain/generator/complete.rs @@ -15,7 +15,7 @@ // along with Parity. If not, see . use bigint::hash::H256; -use util::bytes::Bytes; +use bytes::Bytes; use views::BlockView; #[derive(Default, Clone)] diff --git a/ethcore/src/blockchain/generator/generator.rs b/ethcore/src/blockchain/generator/generator.rs index a32e37942..967fc37fd 100644 --- a/ethcore/src/blockchain/generator/generator.rs +++ b/ethcore/src/blockchain/generator/generator.rs @@ -16,7 +16,7 @@ use bigint::prelude::U256; use bigint::hash::H2048; -use util::Bytes; +use bytes::Bytes; use header::BlockNumber; use transaction::SignedTransaction; use super::fork::Fork; diff --git a/ethcore/src/builtin.rs b/ethcore/src/builtin.rs index ac2726354..191e04dc6 100644 --- a/ethcore/src/builtin.rs +++ b/ethcore/src/builtin.rs @@ -26,7 +26,7 @@ use num::{BigUint, Zero, One}; use hash::keccak; use bigint::prelude::U256; use bigint::hash::H256; -use util::BytesRef; +use bytes::BytesRef; use ethkey::{Signature, recover as ec_recover}; use ethjson; @@ -509,7 +509,7 @@ mod tests { use super::{Builtin, Linear, ethereum_builtin, Pricer, Modexp, modexp as me}; use ethjson; use bigint::prelude::U256; - use util::BytesRef; + use bytes::BytesRef; use rustc_hex::FromHex; use num::{BigUint, Zero, One}; diff --git a/ethcore/src/client/chain_notify.rs b/ethcore/src/client/chain_notify.rs index 977e7b435..00b744167 100644 --- a/ethcore/src/client/chain_notify.rs +++ b/ethcore/src/client/chain_notify.rs @@ -16,7 +16,7 @@ use ipc::IpcConfig; use bigint::hash::H256; -use util::Bytes; +use bytes::Bytes; /// Represents what has to be handled by actor listening to chain events #[ipc] diff --git a/ethcore/src/client/client.rs b/ethcore/src/client/client.rs index 38dce1ffe..9fe9a4573 100644 --- a/ethcore/src/client/client.rs +++ b/ethcore/src/client/client.rs @@ -25,11 +25,10 @@ use itertools::Itertools; // util use hash::keccak; use timer::PerfTimer; -use util::UtilError; -use util::Bytes; -use util::{journaldb, DBValue, TrieFactory, Trie}; -use util::Address; -use util::trie::TrieSpec; +use bytes::Bytes; +use util::{journaldb, DBValue}; +use util::{Address, UtilError}; +use trie::{TrieSpec, TrieFactory, Trie}; use util::kvdb::*; // other diff --git a/ethcore/src/client/error.rs b/ethcore/src/client/error.rs index ff8b6d2ce..2bb5b46d4 100644 --- a/ethcore/src/client/error.rs +++ b/ethcore/src/client/error.rs @@ -17,7 +17,7 @@ use util::UtilError; use std::fmt::{Display, Formatter, Error as FmtError}; -use util::trie::TrieError; +use trie::TrieError; /// Client configuration errors. #[derive(Debug)] diff --git a/ethcore/src/client/evm_test_client.rs b/ethcore/src/client/evm_test_client.rs index e6f5e4675..2c465a24b 100644 --- a/ethcore/src/client/evm_test_client.rs +++ b/ethcore/src/client/evm_test_client.rs @@ -20,7 +20,9 @@ use std::fmt; use std::sync::Arc; use bigint::prelude::U256; use bigint::hash::H256; -use util::{self, journaldb, trie}; +use util::journaldb; +use trie; +use bytes; use util::kvdb::{self, KeyValueDB}; use {state, state_db, client, executive, trace, transaction, db, spec, pod_state}; use factory::Factories; @@ -31,7 +33,7 @@ use vm::{self, ActionParams}; #[derive(Debug)] pub enum EvmTestError { /// Trie integrity error. - Trie(util::TrieError), + Trie(trie::TrieError), /// EVM error. Evm(vm::Error), /// Initialization error. @@ -179,7 +181,7 @@ impl<'a> EvmTestClient<'a> { let (gas_left, _) = executive.call( params, &mut substate, - util::BytesRef::Flexible(&mut output), + bytes::BytesRef::Flexible(&mut output), &mut tracer, vm_tracer, ).map_err(EvmTestError::Evm)?; diff --git a/ethcore/src/client/test_client.rs b/ethcore/src/client/test_client.rs index b7245b25c..eb3706e01 100644 --- a/ethcore/src/client/test_client.rs +++ b/ethcore/src/client/test_client.rs @@ -27,6 +27,7 @@ use bigint::prelude::U256; use bigint::hash::H256; use parking_lot::RwLock; use util::*; +use bytes::Bytes; use rlp::*; use ethkey::{Generator, Random}; use devtools::*; diff --git a/ethcore/src/client/traits.rs b/ethcore/src/client/traits.rs index b7616a478..b4fc60f14 100644 --- a/ethcore/src/client/traits.rs +++ b/ethcore/src/client/traits.rs @@ -36,8 +36,9 @@ use verification::queue::QueueInfo as BlockQueueInfo; use bigint::prelude::U256; use bigint::hash::H256; -use util::{Address, Bytes}; -use util::hashdb::DBValue; +use util::Address; +use bytes::Bytes; +use hashdb::DBValue; use types::ids::*; use types::basic_account::BasicAccount; diff --git a/ethcore/src/engines/authority_round/mod.rs b/ethcore/src/engines/authority_round/mod.rs index b50ebbc4f..4ea032411 100644 --- a/ethcore/src/engines/authority_round/mod.rs +++ b/ethcore/src/engines/authority_round/mod.rs @@ -48,6 +48,7 @@ use semantic_version::SemanticVersion; use parking_lot::{Mutex, RwLock}; use unexpected::{Mismatch, OutOfBounds}; use util::*; +use bytes::Bytes; mod finality; diff --git a/ethcore/src/engines/mod.rs b/ethcore/src/engines/mod.rs index fcf387f8b..b48ff2f3f 100644 --- a/ethcore/src/engines/mod.rs +++ b/ethcore/src/engines/mod.rs @@ -59,6 +59,7 @@ use bigint::hash::H256; use semantic_version::SemanticVersion; use util::*; use unexpected::{Mismatch, OutOfBounds}; +use bytes::Bytes; /// Default EIP-210 contrat code. /// As defined in https://github.com/ethereum/EIPs/pull/210/commits/9df24a3714af42e3bf350265bdc75b486c909d7f#diff-e02a92c2fb96c1a1bfb05e4c6e2ef5daR49 @@ -420,6 +421,7 @@ pub mod common { use bigint::prelude::U256; use bigint::hash::H256; use util::*; + use bytes::{Bytes, BytesRef}; use super::Engine; /// Execute a call as the system address. diff --git a/ethcore/src/engines/tendermint/message.rs b/ethcore/src/engines/tendermint/message.rs index baaf94601..5fec4f737 100644 --- a/ethcore/src/engines/tendermint/message.rs +++ b/ethcore/src/engines/tendermint/message.rs @@ -20,6 +20,7 @@ use std::cmp; use hash::keccak; use bigint::hash::{H256, H520}; use util::*; +use bytes::Bytes; use super::{Height, View, BlockHash, Step}; use error::Error; use header::Header; diff --git a/ethcore/src/engines/tendermint/mod.rs b/ethcore/src/engines/tendermint/mod.rs index ce0a0da24..6fe00aaab 100644 --- a/ethcore/src/engines/tendermint/mod.rs +++ b/ethcore/src/engines/tendermint/mod.rs @@ -36,6 +36,7 @@ use parking_lot::RwLock; use util::*; use unexpected::{OutOfBounds, Mismatch}; use client::EngineClient; +use bytes::Bytes; use error::{Error, BlockError}; use header::{Header, BlockNumber}; use builtin::Builtin; @@ -775,6 +776,7 @@ mod tests { use std::str::FromStr; use rustc_hex::FromHex; use util::*; + use bytes::Bytes; use block::*; use error::{Error, BlockError}; use header::Header; diff --git a/ethcore/src/engines/validator_set/contract.rs b/ethcore/src/engines/validator_set/contract.rs index 24e396c10..3f035d424 100644 --- a/ethcore/src/engines/validator_set/contract.rs +++ b/ethcore/src/engines/validator_set/contract.rs @@ -21,6 +21,7 @@ use std::sync::Weak; use bigint::hash::H256; use parking_lot::RwLock; use util::*; +use bytes::Bytes; use futures::Future; use native_contracts::ValidatorReport as Provider; @@ -139,6 +140,7 @@ mod tests { use hash::keccak; use bigint::hash::H520; use util::*; + use bytes::ToPretty; use rlp::encode; use spec::Spec; use header::Header; diff --git a/ethcore/src/engines/validator_set/mod.rs b/ethcore/src/engines/validator_set/mod.rs index 451abe6f2..32060f8bf 100644 --- a/ethcore/src/engines/validator_set/mod.rs +++ b/ethcore/src/engines/validator_set/mod.rs @@ -26,7 +26,8 @@ mod multi; use std::sync::Weak; use ids::BlockId; use bigint::hash::H256; -use util::{Bytes, Address}; +use util::Address; +use bytes::Bytes; use ethjson::spec::ValidatorSet as ValidatorSpec; use client::EngineClient; use header::{Header, BlockNumber}; diff --git a/ethcore/src/engines/validator_set/multi.rs b/ethcore/src/engines/validator_set/multi.rs index 043f8aab6..baf82b88d 100644 --- a/ethcore/src/engines/validator_set/multi.rs +++ b/ethcore/src/engines/validator_set/multi.rs @@ -21,7 +21,8 @@ use std::sync::Weak; use engines::{Call, Engine}; use bigint::hash::H256; use parking_lot::RwLock; -use util::{Bytes, Address}; +use util::Address; +use bytes::Bytes; use ids::BlockId; use header::{BlockNumber, Header}; use client::EngineClient; diff --git a/ethcore/src/engines/validator_set/safe_contract.rs b/ethcore/src/engines/validator_set/safe_contract.rs index c3f82e181..3e1279228 100644 --- a/ethcore/src/engines/validator_set/safe_contract.rs +++ b/ethcore/src/engines/validator_set/safe_contract.rs @@ -26,6 +26,7 @@ use bigint::hash::{H160, H256}; use parking_lot::{Mutex, RwLock}; use util::*; +use bytes::Bytes; use util::cache::MemoryLruCache; use unexpected::Mismatch; use rlp::{UntrustedRlp, RlpStream}; diff --git a/ethcore/src/engines/validator_set/test.rs b/ethcore/src/engines/validator_set/test.rs index da89880ca..e2a0c36c7 100644 --- a/ethcore/src/engines/validator_set/test.rs +++ b/ethcore/src/engines/validator_set/test.rs @@ -21,7 +21,8 @@ use std::sync::Arc; use std::sync::atomic::{AtomicUsize, Ordering as AtomicOrdering}; use heapsize::HeapSizeOf; use bigint::hash::H256; -use util::{Bytes, Address}; +use util::Address; +use bytes::Bytes; use engines::{Call, Engine}; use header::{Header, BlockNumber}; diff --git a/ethcore/src/engines/vote_collector.rs b/ethcore/src/engines/vote_collector.rs index f759cbaf8..413d75389 100644 --- a/ethcore/src/engines/vote_collector.rs +++ b/ethcore/src/engines/vote_collector.rs @@ -22,6 +22,7 @@ use std::hash::Hash; use bigint::hash::{H256, H520}; use parking_lot:: RwLock; use util::*; +use bytes::Bytes; use rlp::{Encodable, RlpStream}; pub trait Message: Clone + PartialEq + Eq + Hash + Encodable + Debug { diff --git a/ethcore/src/error.rs b/ethcore/src/error.rs index 8b0554e5a..9c7f7b4e2 100644 --- a/ethcore/src/error.rs +++ b/ethcore/src/error.rs @@ -21,6 +21,7 @@ use bigint::prelude::U256; use bigint::hash::H256; use util::*; use unexpected::{Mismatch, OutOfBounds}; +use trie::TrieError; use io::*; use header::BlockNumber; use basic_types::LogBloom; diff --git a/ethcore/src/executed.rs b/ethcore/src/executed.rs index 909e1b6cb..490681dfb 100644 --- a/ethcore/src/executed.rs +++ b/ethcore/src/executed.rs @@ -17,7 +17,9 @@ //! Transaction execution format module. use bigint::prelude::{U256, U512}; -use util::{Bytes, Address, trie}; +use util::Address; +use bytes::Bytes; +use trie; use vm; use trace::{VMTrace, FlatTrace}; use log_entry::LogEntry; diff --git a/ethcore/src/executive.rs b/ethcore/src/executive.rs index c00046e0e..98ead0b8e 100644 --- a/ethcore/src/executive.rs +++ b/ethcore/src/executive.rs @@ -21,6 +21,7 @@ use hash::keccak; use bigint::prelude::{U256, U512}; use bigint::hash::H256; use util::*; +use bytes::{Bytes, BytesRef}; use state::{Backend as StateBackend, State, Substate, CleanupMode}; use engines::Engine; use vm::EnvInfo; @@ -680,7 +681,7 @@ mod tests { use bigint::prelude::{U256, U512}; use bigint::hash::H256; use util::Address; - use util::bytes::BytesRef; + use bytes::BytesRef; use vm::{ActionParams, ActionValue, CallType, EnvInfo, CreateContractAddress}; use evm::{Factory, VMType}; use error::ExecutionError; diff --git a/ethcore/src/externalities.rs b/ethcore/src/externalities.rs index 5fc613844..b84fbfe5b 100644 --- a/ethcore/src/externalities.rs +++ b/ethcore/src/externalities.rs @@ -20,6 +20,7 @@ use std::sync::Arc; use bigint::prelude::U256; use bigint::hash::H256; use util::*; +use bytes::{Bytes, BytesRef}; use state::{Backend as StateBackend, State, Substate, CleanupMode}; use engines::Engine; use executive::*; diff --git a/ethcore/src/factory.rs b/ethcore/src/factory.rs index e283491e1..e9edfa3bd 100644 --- a/ethcore/src/factory.rs +++ b/ethcore/src/factory.rs @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -use util::trie::TrieFactory; +use trie::TrieFactory; use evm::Factory as EvmFactory; use account_db::Factory as AccountFactory; @@ -27,4 +27,4 @@ pub struct Factories { pub trie: TrieFactory, /// factory for account databases. pub accountdb: AccountFactory, -} \ No newline at end of file +} diff --git a/ethcore/src/header.rs b/ethcore/src/header.rs index 8dca493a7..5cbd0d22b 100644 --- a/ethcore/src/header.rs +++ b/ethcore/src/header.rs @@ -23,6 +23,7 @@ use heapsize::HeapSizeOf; use bigint::prelude::U256; use bigint::hash::H256; use util::*; +use bytes::Bytes; use basic_types::{LogBloom, ZERO_LOGBLOOM}; use time::get_time; use rlp::*; diff --git a/ethcore/src/json_tests/executive.rs b/ethcore/src/json_tests/executive.rs index f7b4bbe81..f6d3023c9 100644 --- a/ethcore/src/json_tests/executive.rs +++ b/ethcore/src/json_tests/executive.rs @@ -30,6 +30,8 @@ use tests::helpers::*; use ethjson; use trace::{Tracer, NoopTracer}; use trace::{VMTracer, NoopVMTracer}; +use bytes::{Bytes, BytesRef}; +use trie; #[derive(Debug, PartialEq, Clone)] struct CallCreate { diff --git a/ethcore/src/json_tests/trie.rs b/ethcore/src/json_tests/trie.rs index 5d2696893..f7989bc09 100644 --- a/ethcore/src/json_tests/trie.rs +++ b/ethcore/src/json_tests/trie.rs @@ -15,9 +15,9 @@ // along with Parity. If not, see . use ethjson; -use util::trie::{TrieFactory, TrieSpec}; +use trie::{TrieFactory, TrieSpec}; use bigint::hash::H256; -use util::memorydb::MemoryDB; +use memorydb::MemoryDB; fn test_trie(json: &[u8], trie: TrieSpec) -> Vec { let tests = ethjson::trie::Test::load(json).unwrap(); @@ -49,7 +49,7 @@ fn test_trie(json: &[u8], trie: TrieSpec) -> Vec { } mod generic { - use util::trie::TrieSpec; + use trie::TrieSpec; fn do_json_test(json: &[u8]) -> Vec { super::test_trie(json, TrieSpec::Generic) @@ -60,7 +60,7 @@ mod generic { } mod secure { - use util::trie::TrieSpec; + use trie::TrieSpec; fn do_json_test(json: &[u8]) -> Vec { super::test_trie(json, TrieSpec::Secure) diff --git a/ethcore/src/lib.rs b/ethcore/src/lib.rs index 82b3cfd96..6edd2261e 100644 --- a/ethcore/src/lib.rs +++ b/ethcore/src/lib.rs @@ -86,12 +86,14 @@ extern crate ethcore_devtools as devtools; extern crate ethcore_io as io; extern crate ethcore_ipc_nano as nanoipc; extern crate ethcore_bigint as bigint; +extern crate ethcore_bytes as bytes; extern crate ethcore_logger; extern crate ethcore_stratum; extern crate ethjson; extern crate ethkey; extern crate futures; extern crate hardware_wallet; +extern crate hashdb; extern crate hyper; extern crate itertools; extern crate linked_hash_map; @@ -106,6 +108,8 @@ extern crate rayon; extern crate rlp; extern crate hash; extern crate heapsize; +extern crate memorydb; +extern crate trie; extern crate triehash; extern crate ansi_term; extern crate semantic_version; diff --git a/ethcore/src/migrations/state/v7.rs b/ethcore/src/migrations/state/v7.rs index 64fa5b272..4a9d850ad 100644 --- a/ethcore/src/migrations/state/v7.rs +++ b/ethcore/src/migrations/state/v7.rs @@ -20,7 +20,8 @@ use std::collections::HashMap; use bigint::hash::H256; -use util::{Address, Bytes}; +use util::Address; +use bytes::Bytes; use util::kvdb::Database; use util::migration::{Batch, Config, Error, Migration, SimpleMigration, Progress}; use hash::keccak; diff --git a/ethcore/src/migrations/v10.rs b/ethcore/src/migrations/v10.rs index dd6968bbb..d2f6952d4 100644 --- a/ethcore/src/migrations/v10.rs +++ b/ethcore/src/migrations/v10.rs @@ -19,13 +19,13 @@ use std::sync::Arc; use db::{COL_EXTRA, COL_HEADERS, COL_STATE}; use state_db::{ACCOUNT_BLOOM_SPACE, DEFAULT_ACCOUNT_PRESET, StateDB}; -use util::trie::TrieDB; +use trie::TrieDB; use views::HeaderView; use bloom_journal::Bloom; use util::migration::{Error, Migration, Progress, Batch, Config}; use util::journaldb; use bigint::hash::H256; -use util::Trie; +use trie::Trie; use util::{Database, DBTransaction}; /// Account bloom upgrade routine. If bloom already present, does nothing. diff --git a/ethcore/src/miner/miner.rs b/ethcore/src/miner/miner.rs index b28288570..c088a18be 100644 --- a/ethcore/src/miner/miner.rs +++ b/ethcore/src/miner/miner.rs @@ -22,6 +22,7 @@ use bigint::prelude::U256; use bigint::hash::H256; use parking_lot::{Mutex, RwLock}; use util::*; +use bytes::Bytes; use timer::PerfTimer; use using_queue::{UsingQueue, GetAction}; use account_provider::{AccountProvider, SignError as AccountError}; diff --git a/ethcore/src/miner/mod.rs b/ethcore/src/miner/mod.rs index b9bf7859e..6e1504c21 100644 --- a/ethcore/src/miner/mod.rs +++ b/ethcore/src/miner/mod.rs @@ -63,7 +63,8 @@ pub use self::stratum::{Stratum, Error as StratumError, Options as StratumOption use std::collections::BTreeMap; use bigint::prelude::U256; use bigint::hash::H256; -use util::{Address, Bytes}; +use util::Address; +use bytes::Bytes; use client::{MiningBlockChainClient}; use block::ClosedBlock; use header::BlockNumber; diff --git a/ethcore/src/pod_account.rs b/ethcore/src/pod_account.rs index 8f21de298..7276c0541 100644 --- a/ethcore/src/pod_account.rs +++ b/ethcore/src/pod_account.rs @@ -22,6 +22,8 @@ use bigint::prelude::U256; use bigint::hash::H256; use triehash::sec_trie_root; use util::*; +use bytes::Bytes; +use trie::TrieFactory; use state::Account; use ethjson; use types::account_diff::*; diff --git a/ethcore/src/service.rs b/ethcore/src/service.rs index 4e7e04341..ca283b0aa 100644 --- a/ethcore/src/service.rs +++ b/ethcore/src/service.rs @@ -20,6 +20,7 @@ use std::sync::Arc; use std::path::Path; use bigint::hash::H256; use util::*; +use bytes::Bytes; use io::*; use spec::Spec; use error::*; diff --git a/ethcore/src/snapshot/account.rs b/ethcore/src/snapshot/account.rs index 47598c86e..8fb990ca9 100644 --- a/ethcore/src/snapshot/account.rs +++ b/ethcore/src/snapshot/account.rs @@ -23,8 +23,9 @@ use hash::{KECCAK_EMPTY, KECCAK_NULL_RLP}; use bigint::prelude::U256; use bigint::hash::H256; -use util::{Bytes, HashDB}; -use util::trie::{TrieDB, Trie}; +use util::HashDB; +use bytes::Bytes; +use trie::{TrieDB, Trie}; use rlp::{RlpStream, UntrustedRlp}; use std::collections::HashSet; @@ -151,7 +152,7 @@ pub fn from_fat_rlp( rlp: UntrustedRlp, mut storage_root: H256, ) -> Result<(BasicAccount, Option), Error> { - use util::{TrieDBMut, TrieMut}; + use trie::{TrieDBMut, TrieMut}; // check for special case of empty account. if rlp.is_empty() { diff --git a/ethcore/src/snapshot/block.rs b/ethcore/src/snapshot/block.rs index ed8c130d4..8143a4931 100644 --- a/ethcore/src/snapshot/block.rs +++ b/ethcore/src/snapshot/block.rs @@ -23,7 +23,7 @@ use hash::keccak; use views::BlockView; use rlp::{DecoderError, RlpStream, UntrustedRlp}; use bigint::hash::H256; -use util::Bytes; +use bytes::Bytes; use triehash::ordered_trie_root; const HEADER_FIELDS: usize = 8; @@ -140,7 +140,8 @@ mod tests { use bigint::prelude::U256; use bigint::hash::H256; - use util::{Address, Bytes}; + use util::Address; + use bytes::Bytes; fn encode_block(b: &Block) -> Bytes { b.rlp_bytes(::basic_types::Seal::With) diff --git a/ethcore/src/snapshot/consensus/authority.rs b/ethcore/src/snapshot/consensus/authority.rs index 28222bfb5..0c1d12808 100644 --- a/ethcore/src/snapshot/consensus/authority.rs +++ b/ethcore/src/snapshot/consensus/authority.rs @@ -34,7 +34,8 @@ use snapshot::{Error, ManifestData}; use itertools::{Position, Itertools}; use rlp::{RlpStream, UntrustedRlp}; use bigint::hash::H256; -use util::{Bytes, KeyValueDB}; +use util::KeyValueDB; +use bytes::Bytes; /// Snapshot creation and restoration for PoA chains. /// Chunk format: diff --git a/ethcore/src/snapshot/consensus/work.rs b/ethcore/src/snapshot/consensus/work.rs index 16b8a5c18..349cce685 100644 --- a/ethcore/src/snapshot/consensus/work.rs +++ b/ethcore/src/snapshot/consensus/work.rs @@ -31,7 +31,8 @@ use engines::Engine; use snapshot::{Error, ManifestData}; use snapshot::block::AbridgedBlock; use bigint::hash::H256; -use util::{Bytes, KeyValueDB}; +use util::KeyValueDB; +use bytes::Bytes; use rlp::{RlpStream, UntrustedRlp}; use rand::OsRng; diff --git a/ethcore/src/snapshot/error.rs b/ethcore/src/snapshot/error.rs index b7a310c0d..bd0cb227b 100644 --- a/ethcore/src/snapshot/error.rs +++ b/ethcore/src/snapshot/error.rs @@ -21,7 +21,7 @@ use std::fmt; use ids::BlockId; use bigint::hash::H256; -use util::trie::TrieError; +use trie::TrieError; use rlp::DecoderError; /// Snapshot-related errors. diff --git a/ethcore/src/snapshot/io.rs b/ethcore/src/snapshot/io.rs index dabb86283..3f2622296 100644 --- a/ethcore/src/snapshot/io.rs +++ b/ethcore/src/snapshot/io.rs @@ -25,7 +25,7 @@ use std::io::{self, Read, Seek, SeekFrom, Write}; use std::fs::{self, File}; use std::path::{Path, PathBuf}; -use util::Bytes; +use bytes::Bytes; use bigint::hash::H256; use rlp::{RlpStream, UntrustedRlp}; diff --git a/ethcore/src/snapshot/mod.rs b/ethcore/src/snapshot/mod.rs index bd9672caf..9b8cfb726 100644 --- a/ethcore/src/snapshot/mod.rs +++ b/ethcore/src/snapshot/mod.rs @@ -32,11 +32,12 @@ use ids::BlockId; use bigint::prelude::U256; use bigint::hash::H256; -use util::{Bytes, HashDB, DBValue, snappy}; +use util::{HashDB, DBValue, snappy}; +use bytes::Bytes; use parking_lot::Mutex; use util::journaldb::{self, Algorithm, JournalDB}; use util::kvdb::KeyValueDB; -use util::trie::{TrieDB, TrieDBMut, Trie, TrieMut}; +use trie::{TrieDB, TrieDBMut, Trie, TrieMut}; use rlp::{RlpStream, UntrustedRlp}; use bloom_journal::Bloom; diff --git a/ethcore/src/snapshot/service.rs b/ethcore/src/snapshot/service.rs index 72ef8ccc1..9cc841782 100644 --- a/ethcore/src/snapshot/service.rs +++ b/ethcore/src/snapshot/service.rs @@ -37,7 +37,8 @@ use io::IoChannel; use bigint::hash::H256; use parking_lot::{Mutex, RwLock, RwLockReadGuard}; -use util::{Bytes, UtilError}; +use util::UtilError; +use bytes::Bytes; use util::journaldb::Algorithm; use util::kvdb::{Database, DatabaseConfig}; use util::snappy; @@ -161,7 +162,7 @@ impl Restoration { // finish up restoration. fn finalize(mut self, engine: &Engine) -> Result<(), Error> { - use util::trie::TrieError; + use trie::TrieError; if !self.is_done() { return Ok(()) } diff --git a/ethcore/src/snapshot/snapshot_service_trait.rs b/ethcore/src/snapshot/snapshot_service_trait.rs index 9ef7706b4..8208400df 100644 --- a/ethcore/src/snapshot/snapshot_service_trait.rs +++ b/ethcore/src/snapshot/snapshot_service_trait.rs @@ -16,7 +16,7 @@ use super::{ManifestData, RestorationStatus}; use bigint::hash::H256; -use util::Bytes; +use bytes::Bytes; use ipc::IpcConfig; /// The interface for a snapshot network service. diff --git a/ethcore/src/snapshot/tests/helpers.rs b/ethcore/src/snapshot/tests/helpers.rs index c93409c51..e5e48bf58 100644 --- a/ethcore/src/snapshot/tests/helpers.rs +++ b/ethcore/src/snapshot/tests/helpers.rs @@ -33,10 +33,10 @@ use rand::Rng; use util::{DBValue, KeyValueDB}; use bigint::hash::H256; -use util::hashdb::HashDB; +use hashdb::HashDB; use util::journaldb; -use util::trie::{Alphabet, StandardMap, SecTrieDBMut, TrieMut, ValueMode}; -use util::trie::{TrieDB, TrieDBMut, Trie}; +use trie::{Alphabet, StandardMap, SecTrieDBMut, TrieMut, ValueMode}; +use trie::{TrieDB, TrieDBMut, Trie}; // the proportion of accounts we will alter each tick. const ACCOUNT_CHURN: f32 = 0.01; diff --git a/ethcore/src/snapshot/tests/state.rs b/ethcore/src/snapshot/tests/state.rs index d3bea08dc..460dd77b5 100644 --- a/ethcore/src/snapshot/tests/state.rs +++ b/ethcore/src/snapshot/tests/state.rs @@ -28,7 +28,7 @@ use rand::{XorShiftRng, SeedableRng}; use bigint::hash::H256; use util::journaldb::{self, Algorithm}; use util::kvdb::{Database, DatabaseConfig}; -use util::memorydb::MemoryDB; +use memorydb::MemoryDB; use parking_lot::Mutex; use devtools::RandomTempPath; @@ -99,7 +99,7 @@ fn get_code_from_prev_chunk() { use rlp::RlpStream; use bigint::prelude::U256; use bigint::hash::H256; - use util::HashDB; + use hashdb::HashDB; use account_db::{AccountDBMut, AccountDB}; diff --git a/ethcore/src/snapshot/watcher.rs b/ethcore/src/snapshot/watcher.rs index e4b236b88..6c34cf39d 100644 --- a/ethcore/src/snapshot/watcher.rs +++ b/ethcore/src/snapshot/watcher.rs @@ -23,7 +23,7 @@ use service::ClientIoMessage; use io::IoChannel; use bigint::hash::H256; -use util::Bytes; +use bytes::Bytes; use std::sync::Arc; diff --git a/ethcore/src/spec/spec.rs b/ethcore/src/spec/spec.rs index a807384be..0cf5e7eb5 100644 --- a/ethcore/src/spec/spec.rs +++ b/ethcore/src/spec/spec.rs @@ -43,6 +43,7 @@ use bigint::prelude::U256; use bigint::hash::{H256, H2048}; use parking_lot::RwLock; use util::*; +use bytes::Bytes; /// Parameters common to ethereum-like blockchains. /// NOTE: when adding bugfix hard-fork parameters, diff --git a/ethcore/src/state/account.rs b/ethcore/src/state/account.rs index b46b5ec4c..2d9a37e81 100644 --- a/ethcore/src/state/account.rs +++ b/ethcore/src/state/account.rs @@ -23,6 +23,9 @@ use hash::{KECCAK_EMPTY, KECCAK_NULL_RLP, keccak}; use bigint::prelude::U256; use bigint::hash::H256; use util::*; +use bytes::{Bytes, ToPretty}; +use trie; +use trie::{SecTrieDB, Trie, TrieFactory, TrieError}; use pod_account::*; use rlp::*; use lru_cache::LruCache; @@ -450,8 +453,8 @@ impl Account { /// `storage_key` is the hash of the desired storage key, meaning /// this will only work correctly under a secure trie. pub fn prove_storage(&self, db: &HashDB, storage_key: H256) -> Result<(Vec, H256), Box> { - use util::trie::{Trie, TrieDB}; - use util::trie::recorder::Recorder; + use trie::{Trie, TrieDB}; + use trie::recorder::Recorder; let mut recorder = Recorder::new(); @@ -475,6 +478,7 @@ impl fmt::Debug for Account { mod tests { use rlp::{UntrustedRlp, RlpType, Compressible}; use util::*; + use bytes::Bytes; use super::*; use account_db::*; diff --git a/ethcore/src/state/backend.rs b/ethcore/src/state/backend.rs index c0d0380e7..968d0cfd7 100644 --- a/ethcore/src/state/backend.rs +++ b/ethcore/src/state/backend.rs @@ -28,7 +28,7 @@ use state::Account; use bigint::hash::H256; use parking_lot::Mutex; use util::{Address, MemoryDB}; -use util::hashdb::{AsHashDB, HashDB, DBValue}; +use hashdb::{AsHashDB, HashDB, DBValue}; /// State backend. See module docs for more details. pub trait Backend: Send { diff --git a/ethcore/src/state/mod.rs b/ethcore/src/state/mod.rs index eb6deac23..8f7259c4b 100644 --- a/ethcore/src/state/mod.rs +++ b/ethcore/src/state/mod.rs @@ -45,9 +45,12 @@ use evm::{Factory as EvmFactory}; use bigint::prelude::U256; use bigint::hash::H256; use util::*; +use bytes::Bytes; + +use trie; +use trie::{Trie, TrieError, TrieDB}; +use trie::recorder::Recorder; -use util::trie; -use util::trie::recorder::Recorder; mod account; mod substate; diff --git a/ethcore/src/state_db.rs b/ethcore/src/state_db.rs index 346312c3b..34279a382 100644 --- a/ethcore/src/state_db.rs +++ b/ethcore/src/state_db.rs @@ -21,7 +21,7 @@ use util::cache::MemoryLruCache; use util::journaldb::JournalDB; use util::kvdb::KeyValueDB; use bigint::hash::H256; -use util::hashdb::HashDB; +use hashdb::HashDB; use state::{self, Account}; use header::BlockNumber; use hash::keccak; diff --git a/ethcore/src/tests/evm.rs b/ethcore/src/tests/evm.rs index 8b51c3487..f8eb178d5 100644 --- a/ethcore/src/tests/evm.rs +++ b/ethcore/src/tests/evm.rs @@ -14,6 +14,7 @@ use rustc_hex::FromHex; use bigint::hash::H256; use util::*; +use bytes::BytesRef; evm_test!{test_blockhash_eip210: test_blockhash_eip210_jit, test_blockhash_eip210_int} fn test_blockhash_eip210(factory: Factory) { diff --git a/ethcore/src/tests/helpers.rs b/ethcore/src/tests/helpers.rs index ac5669da7..80eadcfa5 100644 --- a/ethcore/src/tests/helpers.rs +++ b/ethcore/src/tests/helpers.rs @@ -23,6 +23,7 @@ use client::{BlockChainClient, Client, ClientConfig}; use bigint::prelude::U256; use bigint::hash::H256; use util::*; +use bytes::Bytes; use spec::*; use account_provider::AccountProvider; use state_db::StateDB; diff --git a/ethcore/src/trace/executive_tracer.rs b/ethcore/src/trace/executive_tracer.rs index fbc8eaee1..38c134e6b 100644 --- a/ethcore/src/trace/executive_tracer.rs +++ b/ethcore/src/trace/executive_tracer.rs @@ -17,7 +17,8 @@ //! Simple executive tracer. use bigint::prelude::U256; -use util::{Bytes, Address}; +use util::Address; +use bytes::Bytes; use vm::ActionParams; use trace::trace::{Call, Create, Action, Res, CreateResult, CallResult, VMTrace, VMOperation, VMExecutedOperation, MemoryDiff, StorageDiff, Suicide, Reward, RewardType}; use trace::{Tracer, VMTracer, FlatTrace, TraceError}; diff --git a/ethcore/src/trace/mod.rs b/ethcore/src/trace/mod.rs index 06f1afb0b..0a255b357 100644 --- a/ethcore/src/trace/mod.rs +++ b/ethcore/src/trace/mod.rs @@ -39,7 +39,8 @@ pub use self::types::filter::{Filter, AddressesFilter}; use bigint::prelude::U256; use bigint::hash::H256; -use util::{Bytes, Address, DBTransaction}; +use util::{Address, DBTransaction}; +use bytes::Bytes; use self::trace::{Call, Create}; use vm::ActionParams; use header::BlockNumber; diff --git a/ethcore/src/trace/noop_tracer.rs b/ethcore/src/trace/noop_tracer.rs index c39c805fb..6def53c6c 100644 --- a/ethcore/src/trace/noop_tracer.rs +++ b/ethcore/src/trace/noop_tracer.rs @@ -17,7 +17,8 @@ //! Nonoperative tracer. use bigint::prelude::U256; -use util::{Bytes, Address}; +use util::Address; +use bytes::Bytes; use vm::ActionParams; use trace::{Tracer, VMTracer, FlatTrace, TraceError}; use trace::trace::{Call, Create, VMTrace, RewardType}; diff --git a/ethcore/src/trace/types/trace.rs b/ethcore/src/trace/types/trace.rs index a4efcee0e..8c48e6a4a 100644 --- a/ethcore/src/trace/types/trace.rs +++ b/ethcore/src/trace/types/trace.rs @@ -17,7 +17,8 @@ //! Tracing datatypes. use bigint::prelude::U256; -use util::{Bytes, Address}; +use util::Address; +use bytes::Bytes; use hash::keccak; use bloomable::Bloomable; use rlp::*; diff --git a/ethcore/src/transaction.rs b/ethcore/src/transaction.rs index ce767cd0d..02f77d5f3 100644 --- a/ethcore/src/transaction.rs +++ b/ethcore/src/transaction.rs @@ -22,7 +22,8 @@ use hash::keccak; use heapsize::HeapSizeOf; use bigint::prelude::U256; use bigint::hash::H256; -use util::{Address, Bytes}; +use util::Address; +use bytes::Bytes; use ethkey::{Signature, Secret, Public, recover, public_to_address, Error as EthkeyError}; use error::*; use evm::Schedule; diff --git a/ethcore/src/tx_filter.rs b/ethcore/src/tx_filter.rs index b2b7828f1..e9863a154 100644 --- a/ethcore/src/tx_filter.rs +++ b/ethcore/src/tx_filter.rs @@ -22,7 +22,8 @@ use std::collections::hash_map::Entry; use bigint::hash::H256; use native_contracts::TransactAcl as Contract; use client::{EngineClient, BlockId, ChainNotify}; -use util::{Address, Bytes}; +use util::Address; +use bytes::Bytes; use parking_lot::{Mutex, RwLock}; use futures::{self, Future}; use spec::CommonParams; diff --git a/ethcore/src/verification/queue/kind.rs b/ethcore/src/verification/queue/kind.rs index 686311579..47946ef74 100644 --- a/ethcore/src/verification/queue/kind.rs +++ b/ethcore/src/verification/queue/kind.rs @@ -77,7 +77,7 @@ pub mod blocks { use heapsize::HeapSizeOf; use bigint::prelude::U256; use bigint::hash::H256; - use util::Bytes; + use bytes::Bytes; /// A mode for verifying blocks. pub struct Blocks; diff --git a/ethcore/src/verification/verification.rs b/ethcore/src/verification/verification.rs index 4ea0efe51..80d433950 100644 --- a/ethcore/src/verification/verification.rs +++ b/ethcore/src/verification/verification.rs @@ -26,8 +26,8 @@ use hash::keccak; use triehash::ordered_trie_root; use heapsize::HeapSizeOf; use bigint::hash::H256; -use util::*; use unexpected::{Mismatch, OutOfBounds}; +use bytes::Bytes; use engines::Engine; use error::{BlockError, Error}; use blockchain::*; @@ -276,7 +276,7 @@ mod tests { use bigint::hash::{H256, H2048}; use triehash::ordered_trie_root; use unexpected::{Mismatch, OutOfBounds}; - use util::*; + use bytes::Bytes; use ethkey::{Random, Generator}; use header::*; use verification::*; diff --git a/ethcore/src/views/block.rs b/ethcore/src/views/block.rs index 27906c6c5..450b8bafd 100644 --- a/ethcore/src/views/block.rs +++ b/ethcore/src/views/block.rs @@ -18,7 +18,7 @@ use hash::keccak; use bigint::hash::H256; -use util::*; +use bytes::Bytes; use header::*; use transaction::*; use super::{TransactionView, HeaderView}; diff --git a/ethcore/src/views/body.rs b/ethcore/src/views/body.rs index c9f78fc1c..092732d8a 100644 --- a/ethcore/src/views/body.rs +++ b/ethcore/src/views/body.rs @@ -18,7 +18,7 @@ use hash::keccak; use bigint::hash::H256; -use util::*; +use bytes::Bytes; use header::*; use transaction::*; use super::{TransactionView, HeaderView}; diff --git a/ethcore/src/views/header.rs b/ethcore/src/views/header.rs index c3c446e19..d308a042d 100644 --- a/ethcore/src/views/header.rs +++ b/ethcore/src/views/header.rs @@ -19,7 +19,8 @@ use hash::keccak; use bigint::prelude::U256; use bigint::hash::{H256, H2048}; -use util::{Bytes, Address}; +use util::Address; +use bytes::Bytes; use rlp::Rlp; use header::BlockNumber; diff --git a/ethcore/src/views/transaction.rs b/ethcore/src/views/transaction.rs index 25a6fde3a..60bcec90e 100644 --- a/ethcore/src/views/transaction.rs +++ b/ethcore/src/views/transaction.rs @@ -17,7 +17,7 @@ //! View onto transaction rlp use bigint::prelude::U256; use bigint::hash::H256; -use util::Bytes; +use bytes::Bytes; use hash::keccak; use rlp::Rlp; diff --git a/ethcore/types/Cargo.toml b/ethcore/types/Cargo.toml index 8e156f416..73d7b2932 100644 --- a/ethcore/types/Cargo.toml +++ b/ethcore/types/Cargo.toml @@ -7,6 +7,7 @@ authors = ["Parity Technologies "] [dependencies] rlp = { path = "../../util/rlp" } rlp_derive = { path = "../../util/rlp_derive" } +ethcore-bytes = { path = "../../util/bytes" } ethcore-util = { path = "../../util" } ethcore-bigint = { path = "../../util/bigint" } ethjson = { path = "../../json" } diff --git a/ethcore/types/src/account_diff.rs b/ethcore/types/src/account_diff.rs index b862fb220..c1eb89d92 100644 --- a/ethcore/types/src/account_diff.rs +++ b/ethcore/types/src/account_diff.rs @@ -21,7 +21,7 @@ use std::fmt; use std::collections::BTreeMap; use bigint::prelude::U256; use bigint::hash::H256; -use util::Bytes; +use bytes::Bytes; #[derive(Debug, PartialEq, Eq, Clone)] /// Diff type for specifying a change (or not). @@ -114,7 +114,7 @@ fn interpreted_hash(u: &H256) -> String { impl fmt::Display for AccountDiff { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - use util::bytes::ToPretty; + use bytes::ToPretty; match self.nonce { Diff::Born(ref x) => write!(f, " non {}", x)?, diff --git a/ethcore/types/src/lib.rs b/ethcore/types/src/lib.rs index a3af37a69..85d36b200 100644 --- a/ethcore/types/src/lib.rs +++ b/ethcore/types/src/lib.rs @@ -18,6 +18,7 @@ extern crate ethcore_util as util; extern crate ethcore_bigint as bigint; +extern crate ethcore_bytes as bytes; extern crate ethjson; extern crate rlp; #[macro_use] diff --git a/ethcore/types/src/log_entry.rs b/ethcore/types/src/log_entry.rs index 1878c66b9..ca56107b1 100644 --- a/ethcore/types/src/log_entry.rs +++ b/ethcore/types/src/log_entry.rs @@ -19,7 +19,8 @@ use std::ops::Deref; use hash::keccak; use heapsize::HeapSizeOf; -use util::{Address, Bytes}; +use util::Address; +use bytes::Bytes; use bigint::hash::H256; use bloomable::Bloomable; diff --git a/ethcore/types/src/snapshot_manifest.rs b/ethcore/types/src/snapshot_manifest.rs index 8b7503bef..9e5f9f646 100644 --- a/ethcore/types/src/snapshot_manifest.rs +++ b/ethcore/types/src/snapshot_manifest.rs @@ -18,7 +18,7 @@ use bigint::hash::H256; use rlp::*; -use util::Bytes; +use bytes::Bytes; /// Manifest data. #[derive(Debug, Clone, PartialEq, Eq)] diff --git a/ethcore/vm/Cargo.toml b/ethcore/vm/Cargo.toml index 6e5c7d3f2..957e6450d 100644 --- a/ethcore/vm/Cargo.toml +++ b/ethcore/vm/Cargo.toml @@ -6,7 +6,9 @@ authors = ["Parity Technologies "] [dependencies] byteorder = "1.0" ethcore-util = { path = "../../util" } +ethcore-bytes = { path = "../../util/bytes" } ethcore-bigint = { path = "../../util/bigint" } +trie = { path = "../../util/trie" } log = "0.3" common-types = { path = "../types" } evmjit = { path = "../../evmjit", optional = true } diff --git a/ethcore/vm/src/action_params.rs b/ethcore/vm/src/action_params.rs index 89e5da801..f87b1e558 100644 --- a/ethcore/vm/src/action_params.rs +++ b/ethcore/vm/src/action_params.rs @@ -17,7 +17,8 @@ //! Evm input params. use bigint::prelude::U256; use bigint::hash::{H256}; -use util::{Address, Bytes}; +use util::Address; +use bytes::Bytes; use hash::{keccak, KECCAK_EMPTY}; use ethjson; diff --git a/ethcore/vm/src/error.rs b/ethcore/vm/src/error.rs index e4b199438..2c2c9a38d 100644 --- a/ethcore/vm/src/error.rs +++ b/ethcore/vm/src/error.rs @@ -16,7 +16,7 @@ //! VM errors module -use util::trie; +use trie; use std::fmt; /// VM errors. diff --git a/ethcore/vm/src/ext.rs b/ethcore/vm/src/ext.rs index d292af8d8..a4610b672 100644 --- a/ethcore/vm/src/ext.rs +++ b/ethcore/vm/src/ext.rs @@ -20,6 +20,7 @@ use std::sync::Arc; use bigint::prelude::U256; use bigint::hash::H256; use util::*; +use bytes::Bytes; use call_type::CallType; use env_info::EnvInfo; use schedule::Schedule; diff --git a/ethcore/vm/src/lib.rs b/ethcore/vm/src/lib.rs index ee8873b01..0bbef3702 100644 --- a/ethcore/vm/src/lib.rs +++ b/ethcore/vm/src/lib.rs @@ -18,10 +18,12 @@ extern crate ethcore_util as util; extern crate ethcore_bigint as bigint; +extern crate ethcore_bytes as bytes; extern crate common_types as types; extern crate ethjson; extern crate rlp; extern crate hash; +extern crate trie; mod action_params; mod call_type; diff --git a/ethcore/vm/src/tests.rs b/ethcore/vm/src/tests.rs index 923216114..f56975a9e 100644 --- a/ethcore/vm/src/tests.rs +++ b/ethcore/vm/src/tests.rs @@ -19,7 +19,8 @@ use std::collections::{HashMap, HashSet}; use bigint::prelude::U256; use bigint::hash::H256; -use util::{Address, Bytes}; +use util::Address; +use bytes::Bytes; use { CallType, Schedule, EnvInfo, ReturnData, Ext, ContractCreateResult, MessageCallResult, diff --git a/evmbin/Cargo.toml b/evmbin/Cargo.toml index 310a2de25..efb6ba591 100644 --- a/evmbin/Cargo.toml +++ b/evmbin/Cargo.toml @@ -17,6 +17,7 @@ ethcore = { path = "../ethcore" } ethjson = { path = "../json" } ethcore-util = { path = "../util" } ethcore-bigint = { path = "../util/bigint" } +ethcore-bytes = { path = "../util/bytes" } evm = { path = "../ethcore/evm" } vm = { path = "../ethcore/vm" } panic_hook = { path = "../panic_hook" } diff --git a/evmbin/src/display/json.rs b/evmbin/src/display/json.rs index 47e9ccfe5..b36653c78 100644 --- a/evmbin/src/display/json.rs +++ b/evmbin/src/display/json.rs @@ -20,7 +20,7 @@ use ethcore::trace; use std::collections::HashMap; use bigint::prelude::U256; use bigint::hash::H256; -use util::ToPretty; +use bytes::ToPretty; use display; use info as vm; diff --git a/evmbin/src/display/simple.rs b/evmbin/src/display/simple.rs index bb4ecc127..9f6773734 100644 --- a/evmbin/src/display/simple.rs +++ b/evmbin/src/display/simple.rs @@ -17,7 +17,7 @@ //! Simple VM output. use ethcore::trace; -use util::ToPretty; +use bytes::ToPretty; use display; use info as vm; diff --git a/evmbin/src/main.rs b/evmbin/src/main.rs index bb6435ee0..695349db3 100644 --- a/evmbin/src/main.rs +++ b/evmbin/src/main.rs @@ -27,6 +27,7 @@ extern crate serde_derive; extern crate docopt; extern crate ethcore_util as util; extern crate ethcore_bigint as bigint; +extern crate ethcore_bytes as bytes; extern crate vm; extern crate evm; extern crate panic_hook; @@ -37,7 +38,8 @@ use std::path::PathBuf; use docopt::Docopt; use rustc_hex::FromHex; use bigint::prelude::U256; -use util::{Bytes, Address}; +use util::Address; +use bytes::Bytes; use ethcore::spec; use vm::{ActionParams, CallType}; diff --git a/hash-fetch/Cargo.toml b/hash-fetch/Cargo.toml index d5cec4d47..a063c65ff 100644 --- a/hash-fetch/Cargo.toml +++ b/hash-fetch/Cargo.toml @@ -18,6 +18,7 @@ parking_lot = "0.4" fetch = { path = "../util/fetch" } ethcore-util = { path = "../util" } ethcore-bigint = { path = "../util/bigint" } +ethcore-bytes = { path = "../util/bytes" } parity-reactor = { path = "../util/reactor" } native-contracts = { path = "../ethcore/native_contracts" } hash = { path = "../util/hash" } diff --git a/hash-fetch/src/lib.rs b/hash-fetch/src/lib.rs index ad048f3d9..3279f868f 100644 --- a/hash-fetch/src/lib.rs +++ b/hash-fetch/src/lib.rs @@ -26,6 +26,7 @@ extern crate mime; extern crate ethabi; extern crate ethcore_util as util; extern crate ethcore_bigint as bigint; +extern crate ethcore_bytes as bytes; extern crate futures; extern crate mime_guess; extern crate native_contracts; diff --git a/hash-fetch/src/urlhint.rs b/hash-fetch/src/urlhint.rs index c41b0b960..95a16511b 100644 --- a/hash-fetch/src/urlhint.rs +++ b/hash-fetch/src/urlhint.rs @@ -24,7 +24,8 @@ use hash::keccak; use futures::{future, BoxFuture, Future}; use native_contracts::{Registry, Urlhint}; -use util::{Address, Bytes}; +use util::Address; +use bytes::Bytes; const COMMIT_LEN: usize = 20; @@ -217,7 +218,8 @@ pub mod tests { use super::*; use super::guess_mime_type; use parking_lot::Mutex; - use util::{Bytes, Address, ToPretty}; + use util::Address; + use bytes::{Bytes, ToPretty}; pub struct FakeRegistrar { pub calls: Arc>>, diff --git a/ipc/tests/Cargo.toml b/ipc/tests/Cargo.toml index 89a4f98c5..3bf5dc316 100644 --- a/ipc/tests/Cargo.toml +++ b/ipc/tests/Cargo.toml @@ -14,6 +14,7 @@ semver = "0.6" nanomsg = { git = "https://github.com/paritytech/nanomsg.rs.git", branch = "parity-1.7" } ethcore-ipc-nano = { path = "../nano" } ethcore-util = { path = "../../util" } +ethcore-bytes = { path = "../../util/bytes" } log = "0.3" [build-dependencies] diff --git a/ipc/tests/binary.rs.in b/ipc/tests/binary.rs.in index dfc020c45..8b04f683b 100644 --- a/ipc/tests/binary.rs.in +++ b/ipc/tests/binary.rs.in @@ -15,7 +15,7 @@ // along with Parity. If not, see . -use util::Bytes; +use bytes::Bytes; #[binary] pub enum Root { diff --git a/ipc/tests/run.rs b/ipc/tests/run.rs index 607e20636..83e502aab 100644 --- a/ipc/tests/run.rs +++ b/ipc/tests/run.rs @@ -22,6 +22,7 @@ extern crate semver; extern crate nanomsg; extern crate ethcore_ipc_nano as nanoipc; extern crate ethcore_util as util; +extern crate ethcore_bytes as bytes; #[macro_use] extern crate log; pub mod service; diff --git a/ipfs/Cargo.toml b/ipfs/Cargo.toml index f56159399..89048081a 100644 --- a/ipfs/Cargo.toml +++ b/ipfs/Cargo.toml @@ -9,6 +9,7 @@ authors = ["Parity Technologies "] ethcore = { path = "../ethcore" } ethcore-util = { path = "../util" } ethcore-bigint = { path = "../util/bigint" } +ethcore-bytes = { path = "../util/bytes" } jsonrpc-http-server = { git = "https://github.com/paritytech/jsonrpc.git", branch = "parity-1.7" } rlp = { path = "../util/rlp" } mime = "0.2" diff --git a/ipfs/src/lib.rs b/ipfs/src/lib.rs index ec065fa48..6a5f93092 100644 --- a/ipfs/src/lib.rs +++ b/ipfs/src/lib.rs @@ -23,6 +23,7 @@ extern crate rlp; extern crate ethcore; extern crate ethcore_util as util; extern crate ethcore_bigint as bigint; +extern crate ethcore_bytes as bytes; extern crate jsonrpc_http_server as http; pub mod error; diff --git a/ipfs/src/route.rs b/ipfs/src/route.rs index e95552404..37e34f69e 100644 --- a/ipfs/src/route.rs +++ b/ipfs/src/route.rs @@ -20,7 +20,7 @@ use cid::{ToCid, Codec}; use multihash::Hash; use bigint::hash::H256; -use util::Bytes; +use bytes::Bytes; use ethcore::client::{BlockId, TransactionId}; type Reason = &'static str; diff --git a/parity/blockchain.rs b/parity/blockchain.rs index f21364214..b1bf8d4db 100644 --- a/parity/blockchain.rs +++ b/parity/blockchain.rs @@ -24,7 +24,8 @@ use rustc_hex::FromHex; use hash::{keccak, KECCAK_NULL_RLP}; use bigint::prelude::U256; use bigint::hash::H256; -use util::{ToPretty, Address}; +use util::Address; +use bytes::ToPretty; use rlp::PayloadInfo; use ethcore::service::ClientService; use ethcore::client::{Mode, DatabaseCompactionProfile, VMType, BlockImportError, BlockChainClient, BlockId}; diff --git a/parity/configuration.rs b/parity/configuration.rs index 88e5e8d02..856810d3c 100644 --- a/parity/configuration.rs +++ b/parity/configuration.rs @@ -25,7 +25,8 @@ use cli::{Args, ArgsError}; use hash::keccak; use bigint::prelude::U256; use bigint::hash::H256; -use util::{Bytes, version_data, Address}; +use util::{version_data, Address}; +use bytes::Bytes; use util::journaldb::Algorithm; use ansi_term::Colour; use ethsync::{NetworkConfiguration, is_valid_node_url}; diff --git a/parity/dapps.rs b/parity/dapps.rs index 98eca3459..b23b759d5 100644 --- a/parity/dapps.rs +++ b/parity/dapps.rs @@ -31,7 +31,8 @@ use node_health::{SyncStatus, NodeHealth}; use rpc; use rpc_apis::SignerService; use parity_reactor; -use util::{Bytes, Address}; +use util::Address; +use bytes::Bytes; #[derive(Debug, PartialEq, Clone)] pub struct Configuration { diff --git a/parity/informant.rs b/parity/informant.rs index deb2190d1..a9f7d3636 100644 --- a/parity/informant.rs +++ b/parity/informant.rs @@ -36,7 +36,7 @@ use number_prefix::{binary_prefix, Standalone, Prefixed}; use parity_rpc::{is_major_importing}; use parity_rpc::informant::RpcStats; use bigint::hash::H256; -use util::Bytes; +use bytes::Bytes; use parking_lot::{RwLock, Mutex}; /// Format byte counts to standard denominations. diff --git a/parity/main.rs b/parity/main.rs index 1f065d838..cd269b00b 100644 --- a/parity/main.rs +++ b/parity/main.rs @@ -59,6 +59,7 @@ extern crate ethcore_light as light; extern crate ethcore_logger; extern crate ethcore_util as util; extern crate ethcore_bigint as bigint; +extern crate ethcore_bytes as bytes; extern crate ethcore_network as network; extern crate ethkey; extern crate ethsync; diff --git a/rpc/Cargo.toml b/rpc/Cargo.toml index c5b20cf1e..377a75b21 100644 --- a/rpc/Cargo.toml +++ b/rpc/Cargo.toml @@ -40,6 +40,7 @@ ethcore-io = { path = "../util/io" } ethcore-ipc = { path = "../ipc/rpc" } ethcore-util = { path = "../util" } ethcore-bigint = { path = "../util/bigint" } +ethcore-bytes = { path = "../util/bytes" } ethcore = { path = "../ethcore" } ethcrypto = { path = "../ethcrypto" } ethkey = { path = "../ethkey" } diff --git a/rpc/src/lib.rs b/rpc/src/lib.rs index ba27bf290..caf998334 100644 --- a/rpc/src/lib.rs +++ b/rpc/src/lib.rs @@ -47,6 +47,7 @@ extern crate jsonrpc_pubsub; extern crate ethash; extern crate ethcore; extern crate ethcore_bigint as bigint; +extern crate ethcore_bytes as bytes; extern crate ethcore_devtools as devtools; extern crate ethcore_io as io; extern crate ethcore_ipc; diff --git a/rpc/src/v1/helpers/dispatch.rs b/rpc/src/v1/helpers/dispatch.rs index 43386d5fa..c616a70e1 100644 --- a/rpc/src/v1/helpers/dispatch.rs +++ b/rpc/src/v1/helpers/dispatch.rs @@ -29,7 +29,8 @@ use rlp; use hash::keccak; use bigint::prelude::U256; use bigint::hash::{H256, H520}; -use util::{Address, Bytes}; +use util::Address; +use bytes::Bytes; use parking_lot::{Mutex, RwLock}; use stats::Corpus; diff --git a/rpc/src/v1/helpers/requests.rs b/rpc/src/v1/helpers/requests.rs index 8c5307f5f..83abf9353 100644 --- a/rpc/src/v1/helpers/requests.rs +++ b/rpc/src/v1/helpers/requests.rs @@ -15,7 +15,8 @@ // along with Parity. If not, see . use bigint::prelude::U256; -use util::{Address, Bytes}; +use util::Address; +use bytes::Bytes; use v1::types::{Origin, TransactionCondition}; /// Transaction request coming from RPC diff --git a/rpc/src/v1/helpers/secretstore.rs b/rpc/src/v1/helpers/secretstore.rs index 246d0fa3f..b5528c778 100644 --- a/rpc/src/v1/helpers/secretstore.rs +++ b/rpc/src/v1/helpers/secretstore.rs @@ -18,7 +18,7 @@ use std::iter::repeat; use rand::{Rng, OsRng}; use ethkey::{Public, Secret, math}; use crypto; -use util::Bytes; +use bytes::Bytes; use jsonrpc_core::Error; use v1::helpers::errors; @@ -98,7 +98,7 @@ fn decrypt_with_shadow_coefficients(mut decrypted_shadow: Public, mut common_sha #[cfg(test)] mod tests { - use util::Bytes; + use bytes::Bytes; use rustc_hex::FromHex; use super::{encrypt_document, decrypt_document, decrypt_document_with_shadow}; diff --git a/rpc/src/v1/impls/eth_pubsub.rs b/rpc/src/v1/impls/eth_pubsub.rs index f279e2f81..a5770f0e5 100644 --- a/rpc/src/v1/impls/eth_pubsub.rs +++ b/rpc/src/v1/impls/eth_pubsub.rs @@ -40,7 +40,7 @@ use light::on_demand::OnDemand; use light::client::{LightChainClient, LightChainNotify}; use parity_reactor::Remote; use bigint::hash::H256; -use util::Bytes; +use bytes::Bytes; use parking_lot::{RwLock, Mutex}; type Client = Sink; diff --git a/rpc/src/v1/impls/personal.rs b/rpc/src/v1/impls/personal.rs index b606d3e58..4573b8d1a 100644 --- a/rpc/src/v1/impls/personal.rs +++ b/rpc/src/v1/impls/personal.rs @@ -21,7 +21,8 @@ use ethcore::account_provider::AccountProvider; use ethcore::transaction::PendingTransaction; use bigint::prelude::U128; -use util::{Address, ToPretty}; +use util::Address; +use bytes::ToPretty; use futures::{future, Future, BoxFuture}; use jsonrpc_core::Error; diff --git a/rpc/src/v1/tests/helpers/miner_service.rs b/rpc/src/v1/tests/helpers/miner_service.rs index 65a0c25b7..92d36cf15 100644 --- a/rpc/src/v1/tests/helpers/miner_service.rs +++ b/rpc/src/v1/tests/helpers/miner_service.rs @@ -20,7 +20,8 @@ use std::collections::{BTreeMap, HashMap}; use std::collections::hash_map::Entry; use bigint::prelude::U256; use bigint::hash::H256; -use util::{Address, Bytes}; +use util::Address; +use bytes::Bytes; use parking_lot::{RwLock, Mutex}; use ethcore::error::Error; use ethcore::client::MiningBlockChainClient; diff --git a/rpc/src/v1/tests/helpers/snapshot_service.rs b/rpc/src/v1/tests/helpers/snapshot_service.rs index b81e05e7e..84202c7f8 100644 --- a/rpc/src/v1/tests/helpers/snapshot_service.rs +++ b/rpc/src/v1/tests/helpers/snapshot_service.rs @@ -16,7 +16,7 @@ use ethcore::snapshot::{ManifestData, RestorationStatus, SnapshotService}; -use util::Bytes; +use bytes::Bytes; use bigint::hash::H256; use parking_lot::Mutex; diff --git a/rpc/src/v1/tests/mocked/parity.rs b/rpc/src/v1/tests/mocked/parity.rs index bb7765446..32280804f 100644 --- a/rpc/src/v1/tests/mocked/parity.rs +++ b/rpc/src/v1/tests/mocked/parity.rs @@ -223,7 +223,7 @@ fn rpc_parity_extra_data() { #[test] fn rpc_parity_default_extra_data() { use util::misc; - use util::ToPretty; + use bytes::ToPretty; let deps = Dependencies::new(); let io = deps.default_client(); diff --git a/rpc/src/v1/tests/mocked/signer.rs b/rpc/src/v1/tests/mocked/signer.rs index 55f2eae77..af84d336a 100644 --- a/rpc/src/v1/tests/mocked/signer.rs +++ b/rpc/src/v1/tests/mocked/signer.rs @@ -17,7 +17,8 @@ use std::sync::Arc; use std::str::FromStr; use bigint::prelude::U256; -use util::{Address, ToPretty}; +use util::Address; +use bytes::ToPretty; use ethcore::account_provider::AccountProvider; use ethcore::client::TestBlockChainClient; diff --git a/rpc/src/v1/tests/mocked/signing.rs b/rpc/src/v1/tests/mocked/signing.rs index ee8787915..02e6e13a7 100644 --- a/rpc/src/v1/tests/mocked/signing.rs +++ b/rpc/src/v1/tests/mocked/signing.rs @@ -29,7 +29,8 @@ use v1::tests::helpers::TestMinerService; use v1::tests::mocked::parity; use bigint::prelude::U256; -use util::{Address, ToPretty}; +use util::Address; +use bytes::ToPretty; use ethkey::Secret; use ethcore::account_provider::AccountProvider; use ethcore::client::TestBlockChainClient; diff --git a/rpc/src/v1/types/confirmations.rs b/rpc/src/v1/types/confirmations.rs index 39bf8d0a1..fc4a0e303 100644 --- a/rpc/src/v1/types/confirmations.rs +++ b/rpc/src/v1/types/confirmations.rs @@ -19,7 +19,7 @@ use std::fmt; use serde::{Serialize, Serializer}; use ansi_term::Colour; -use util::bytes::ToPretty; +use bytes::ToPretty; use v1::types::{U256, TransactionRequest, RichRawTransaction, H160, H256, H520, Bytes, TransactionCondition, Origin}; use v1::helpers; diff --git a/secret_store/Cargo.toml b/secret_store/Cargo.toml index 9143b289a..ab13b9caa 100644 --- a/secret_store/Cargo.toml +++ b/secret_store/Cargo.toml @@ -27,6 +27,7 @@ tokio-proto = "0.1" url = "1.0" ethabi = "2.0" ethcore = { path = "../ethcore" } +ethcore-bytes = { path = "../util/bytes" } ethcore-devtools = { path = "../devtools" } ethcore-util = { path = "../util" } ethcore-bigint = { path = "../util/bigint" } diff --git a/secret_store/src/acl_storage.rs b/secret_store/src/acl_storage.rs index 0a30a1a60..c06929e94 100644 --- a/secret_store/src/acl_storage.rs +++ b/secret_store/src/acl_storage.rs @@ -22,7 +22,8 @@ use ethkey::public_to_address; use ethcore::client::{Client, BlockChainClient, BlockId, ChainNotify}; use native_contracts::SecretStoreAclStorage; use bigint::hash::H256; -use util::{Address, Bytes}; +use util::Address; +use bytes::Bytes; use types::all::{Error, ServerKeyId, Public}; const ACL_CHECKER_CONTRACT_REGISTRY_NAME: &'static str = "secretstore_acl_checker"; diff --git a/secret_store/src/key_server_set.rs b/secret_store/src/key_server_set.rs index ee959d0ba..8a94e9f42 100644 --- a/secret_store/src/key_server_set.rs +++ b/secret_store/src/key_server_set.rs @@ -24,7 +24,8 @@ use ethcore::client::{Client, BlockChainClient, BlockId, ChainNotify}; use native_contracts::KeyServerSet as KeyServerSetContract; use hash::keccak; use bigint::hash::H256; -use util::{Address, Bytes}; +use util::Address; +use bytes::Bytes; use types::all::{Error, Public, NodeAddress}; const KEY_SERVER_SET_CONTRACT_REGISTRY_NAME: &'static str = "secretstore_server_set"; diff --git a/secret_store/src/lib.rs b/secret_store/src/lib.rs index cbad4ffe6..6c592ccc5 100644 --- a/secret_store/src/lib.rs +++ b/secret_store/src/lib.rs @@ -38,6 +38,7 @@ extern crate url; extern crate ethabi; extern crate ethcore; extern crate ethcore_devtools as devtools; +extern crate ethcore_bytes as bytes; extern crate ethcore_util as util; extern crate ethcore_bigint as bigint; extern crate ethcore_ipc as ipc; diff --git a/secret_store/src/serialization.rs b/secret_store/src/serialization.rs index caa74ec32..369e647ee 100644 --- a/secret_store/src/serialization.rs +++ b/secret_store/src/serialization.rs @@ -22,7 +22,7 @@ use serde::{Serialize, Deserialize, Serializer, Deserializer}; use serde::de::{Visitor, Error as SerdeError}; use ethkey::{Public, Secret, Signature}; use bigint::hash::H256; -use util::Bytes; +use bytes::Bytes; /// Serializable message hash. pub type SerializableMessageHash = SerializableH256; diff --git a/secret_store/src/types/all.rs b/secret_store/src/types/all.rs index 078d65649..1c4fb5946 100644 --- a/secret_store/src/types/all.rs +++ b/secret_store/src/types/all.rs @@ -19,7 +19,7 @@ use std::collections::BTreeMap; use serde_json; use ethkey; -use util; +use bytes; use bigint; use key_server_cluster; @@ -28,11 +28,11 @@ pub type NodeId = ethkey::Public; /// Server key id. When key is used to encrypt document, it could be document contents hash. pub type ServerKeyId = bigint::hash::H256; /// Encrypted document key type. -pub type EncryptedDocumentKey = util::Bytes; +pub type EncryptedDocumentKey = bytes::Bytes; /// Message hash. pub type MessageHash = bigint::hash::H256; /// Message signature. -pub type EncryptedMessageSignature = util::Bytes; +pub type EncryptedMessageSignature = bytes::Bytes; /// Request signature type. pub type RequestSignature = ethkey::Signature; /// Public key type. diff --git a/sync/Cargo.toml b/sync/Cargo.toml index f9edab512..d5ef8ed3c 100644 --- a/sync/Cargo.toml +++ b/sync/Cargo.toml @@ -13,6 +13,7 @@ ethcore-ipc-codegen = { path = "../ipc/codegen" } [dependencies] ethcore-util = { path = "../util" } +ethcore-bytes = { path = "../util/bytes" } ethcore-bigint = { path = "../util/bigint" } ethcore-network = { path = "../util/network" } ethcore-io = { path = "../util/io" } diff --git a/sync/src/api.rs b/sync/src/api.rs index 0dfe51efd..642b4472c 100644 --- a/sync/src/api.rs +++ b/sync/src/api.rs @@ -17,7 +17,7 @@ use std::sync::Arc; use std::collections::{HashMap, BTreeMap}; use std::io; -use util::Bytes; +use bytes::Bytes; use network::{NetworkProtocolHandler, NetworkService, NetworkContext, HostInfo, PeerId, ProtocolId, NetworkConfiguration as BasicNetworkConfiguration, NonReservedPeerMode, NetworkError, ConnectionFilter}; use bigint::prelude::U256; diff --git a/sync/src/blocks.rs b/sync/src/blocks.rs index 3696cd9d0..f7e616c6f 100644 --- a/sync/src/blocks.rs +++ b/sync/src/blocks.rs @@ -22,6 +22,7 @@ use heapsize::HeapSizeOf; use bigint::hash::H256; use triehash::ordered_trie_root; use util::*; +use bytes::Bytes; use rlp::*; use network::NetworkError; use ethcore::header::Header as BlockHeader; diff --git a/sync/src/chain.rs b/sync/src/chain.rs index f00baf5a6..42781fdc5 100644 --- a/sync/src/chain.rs +++ b/sync/src/chain.rs @@ -96,7 +96,7 @@ use heapsize::HeapSizeOf; use bigint::prelude::U256; use bigint::hash::{H256, H256FastMap}; use parking_lot::RwLock; -use util::*; +use bytes::Bytes; use rlp::*; use network::*; use ethcore::header::{BlockNumber, Header as BlockHeader}; @@ -2237,7 +2237,7 @@ mod tests { use bigint::hash::H256; use util::Address; use parking_lot::RwLock; - use util::bytes::Bytes; + use bytes::Bytes; use rlp::{Rlp, RlpStream, UntrustedRlp}; use super::*; use ::SyncConfig; diff --git a/sync/src/lib.rs b/sync/src/lib.rs index 4813bb474..6a65ec663 100644 --- a/sync/src/lib.rs +++ b/sync/src/lib.rs @@ -29,6 +29,7 @@ extern crate ethcore_network as network; extern crate ethcore_bigint as bigint; +extern crate ethcore_bytes as bytes; extern crate ethcore_io as io; extern crate ethcore; extern crate env_logger; diff --git a/sync/src/snapshot.rs b/sync/src/snapshot.rs index 3abd47af4..88725929f 100644 --- a/sync/src/snapshot.rs +++ b/sync/src/snapshot.rs @@ -137,7 +137,7 @@ impl Snapshot { #[cfg(test)] mod test { use hash::keccak; - use util::*; + use bytes::Bytes; use super::*; use ethcore::snapshot::ManifestData; diff --git a/sync/src/sync_io.rs b/sync/src/sync_io.rs index 6871a2e20..0c3bd38e6 100644 --- a/sync/src/sync_io.rs +++ b/sync/src/sync_io.rs @@ -16,7 +16,7 @@ use std::collections::HashMap; use network::{NetworkContext, PeerId, PacketId, NetworkError, SessionInfo, ProtocolId}; -use util::Bytes; +use bytes::Bytes; use ethcore::client::BlockChainClient; use ethcore::header::BlockNumber; use ethcore::snapshot::SnapshotService; diff --git a/sync/src/tests/helpers.rs b/sync/src/tests/helpers.rs index e676f5467..6fb104ef7 100644 --- a/sync/src/tests/helpers.rs +++ b/sync/src/tests/helpers.rs @@ -18,7 +18,7 @@ use std::collections::{VecDeque, HashSet, HashMap}; use std::sync::Arc; use bigint::hash::H256; use parking_lot::RwLock; -use util::*; +use bytes::Bytes; use network::*; use tests::snapshot::*; use ethcore::client::{TestBlockChainClient, BlockChainClient, Client as EthcoreClient, ClientConfig, ChainNotify}; diff --git a/sync/src/tests/snapshot.rs b/sync/src/tests/snapshot.rs index a39b3949f..6ed616bae 100644 --- a/sync/src/tests/snapshot.rs +++ b/sync/src/tests/snapshot.rs @@ -19,7 +19,7 @@ use std::sync::Arc; use hash::keccak; use bigint::hash::H256; use parking_lot::Mutex; -use util::*; +use bytes::Bytes; use ethcore::snapshot::{SnapshotService, ManifestData, RestorationStatus}; use ethcore::header::BlockNumber; use ethcore::client::{EachBlockWith}; diff --git a/updater/Cargo.toml b/updater/Cargo.toml index 8dad116d0..0d4b29025 100644 --- a/updater/Cargo.toml +++ b/updater/Cargo.toml @@ -17,6 +17,7 @@ ethcore = { path = "../ethcore" } ethsync = { path = "../sync" } ethcore-util = { path = "../util" } ethcore-bigint = { path = "../util/bigint" } +ethcore-bytes = { path = "../util/bytes" } futures = "0.1" parking_lot = "0.4" parity-hash-fetch = { path = "../hash-fetch" } diff --git a/updater/src/lib.rs b/updater/src/lib.rs index 265f8de4e..9ba948d9f 100644 --- a/updater/src/lib.rs +++ b/updater/src/lib.rs @@ -19,6 +19,7 @@ #[macro_use] extern crate log; extern crate ethcore_util as util; extern crate ethcore_bigint as bigint; +extern crate ethcore_bytes as bytes; extern crate ipc_common_types; extern crate parking_lot; extern crate parity_hash_fetch as hash_fetch; diff --git a/updater/src/updater.rs b/updater/src/updater.rs index 325048fab..04fe572a9 100644 --- a/updater/src/updater.rs +++ b/updater/src/updater.rs @@ -32,7 +32,8 @@ use service::{Service}; use target_info::Target; use types::all::{ReleaseInfo, OperationsInfo, CapState}; use bigint::hash::{H160, H256}; -use util::{Address, Bytes}; +use util::Address; +use bytes::Bytes; use parking_lot::Mutex; use util::misc; diff --git a/util/Cargo.toml b/util/Cargo.toml index cc684c6cd..cef815099 100644 --- a/util/Cargo.toml +++ b/util/Cargo.toml @@ -30,6 +30,12 @@ lru-cache = "0.1.0" ethcore-logger = { path = "../logger" } triehash = { path = "triehash" } error-chain = "0.11.0-rc.2" +hashdb = { path = "hashdb" } +trie = { path = "trie" } +nibbleslice = { path = "nibbleslice" } +nibblevec = { path = "nibblevec" } +ethcore-bytes = { path = "bytes" } +memorydb = { path = "memorydb" } [features] default = [] diff --git a/util/benches/trie.rs b/util/benches/trie.rs index fb41c0377..3ec2f9ba0 100644 --- a/util/benches/trie.rs +++ b/util/benches/trie.rs @@ -19,16 +19,19 @@ extern crate test; extern crate triehash; extern crate ethcore_util; +extern crate ethcore_bytes; extern crate ethcore_bigint; +extern crate memorydb; +extern crate trie; #[macro_use] extern crate log; extern crate hash; use test::{Bencher, black_box}; use ethcore_bigint::hash::*; -use ethcore_util::bytes::*; -use ethcore_util::trie::*; -use ethcore_util::memorydb::*; +use ethcore_bytes::*; +use trie::*; +use memorydb::*; use triehash::*; use hash::keccak; diff --git a/util/bytes/Cargo.toml b/util/bytes/Cargo.toml new file mode 100644 index 000000000..96dc0abb1 --- /dev/null +++ b/util/bytes/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "ethcore-bytes" +version = "0.1.0" +authors = ["Parity Technologies "] + +[dependencies] diff --git a/util/src/bytes.rs b/util/bytes/src/lib.rs similarity index 100% rename from util/src/bytes.rs rename to util/bytes/src/lib.rs diff --git a/util/hashdb/Cargo.toml b/util/hashdb/Cargo.toml new file mode 100644 index 000000000..d74e47a7e --- /dev/null +++ b/util/hashdb/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "hashdb" +version = "0.1.0" +authors = ["Parity Technologies "] + +[dependencies] +elastic-array = "0.9" +ethcore-bigint = { path = "../bigint" } diff --git a/util/src/hashdb.rs b/util/hashdb/src/lib.rs similarity index 57% rename from util/src/hashdb.rs rename to util/hashdb/src/lib.rs index 3c149a1a3..9162670e3 100644 --- a/util/src/hashdb.rs +++ b/util/hashdb/src/lib.rs @@ -15,6 +15,9 @@ // along with Parity. If not, see . //! Database of byte-slices keyed to their Keccak hash. +extern crate elastic_array; +extern crate ethcore_bigint as bigint; + use bigint::hash::*; use std::collections::HashMap; use elastic_array::ElasticArray128; @@ -29,59 +32,14 @@ pub trait HashDB: AsHashDB + Send + Sync { /// Look up a given hash into the bytes that hash to it, returning None if the /// hash is not known. - /// - /// # Examples - /// ```rust - /// extern crate ethcore_util; - /// use ethcore_util::hashdb::*; - /// use ethcore_util::memorydb::*; - /// fn main() { - /// let mut m = MemoryDB::new(); - /// let hello_bytes = "Hello world!".as_bytes(); - /// let hash = m.insert(hello_bytes); - /// assert_eq!(m.get(&hash).unwrap(), hello_bytes); - /// } - /// ``` fn get(&self, key: &H256) -> Option; /// Check for the existance of a hash-key. - /// - /// # Examples - /// ```rust - /// extern crate hash; - /// extern crate ethcore_util; - /// use ethcore_util::hashdb::*; - /// use ethcore_util::memorydb::*; - /// use hash::keccak; - /// fn main() { - /// let mut m = MemoryDB::new(); - /// let hello_bytes = "Hello world!".as_bytes(); - /// assert!(!m.contains(&keccak(hello_bytes))); - /// let key = m.insert(hello_bytes); - /// assert!(m.contains(&key)); - /// m.remove(&key); - /// assert!(!m.contains(&key)); - /// } - /// ``` fn contains(&self, key: &H256) -> bool; /// Insert a datum item into the DB and return the datum's hash for a later lookup. Insertions /// are counted and the equivalent number of `remove()`s must be performed before the data /// is considered dead. - /// - /// # Examples - /// ```rust - /// extern crate ethcore_util; - /// extern crate ethcore_bigint; - /// use ethcore_util::hashdb::*; - /// use ethcore_util::memorydb::*; - /// use ethcore_bigint::hash::*; - /// fn main() { - /// let mut m = MemoryDB::new(); - /// let key = m.insert("Hello world!".as_bytes()); - /// assert!(m.contains(&key)); - /// } - /// ``` fn insert(&mut self, value: &[u8]) -> H256; /// Like `insert()` , except you provide the key and the data is all moved. @@ -89,30 +47,6 @@ pub trait HashDB: AsHashDB + Send + Sync { /// Remove a datum previously inserted. Insertions can be "owed" such that the same number of `insert()`s may /// happen without the data being eventually being inserted into the DB. It can be "owed" more than once. - /// - /// # Examples - /// ```rust - /// extern crate ethcore_util; - /// extern crate hash; - /// use ethcore_util::hashdb::*; - /// use ethcore_util::memorydb::*; - /// use hash::keccak; - /// fn main() { - /// let mut m = MemoryDB::new(); - /// let d = "Hello world!".as_bytes(); - /// let key = &keccak(d); - /// m.remove(key); // OK - we now owe an insertion. - /// assert!(!m.contains(key)); - /// m.remove(key); // OK - we now owe two insertions. - /// assert!(!m.contains(key)); - /// m.insert(d); // OK - still owed. - /// assert!(!m.contains(key)); - /// m.insert(d); // OK - now it's "empty" again. - /// assert!(!m.contains(key)); - /// m.insert(d); // OK - now we've - /// assert_eq!(m.get(key).unwrap(), d); - /// } - /// ``` fn remove(&mut self, key: &H256); } diff --git a/util/memorydb/Cargo.toml b/util/memorydb/Cargo.toml new file mode 100644 index 000000000..1df95a049 --- /dev/null +++ b/util/memorydb/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "memorydb" +version = "0.1.0" +authors = ["Parity Technologies "] + +[dependencies] +bigint = "4.0" +elastic-array = "0.9" +heapsize = "0.4" +ethcore-bigint = { path = "../bigint", features = ["heapsizeof"] } +hash = { path = "../hash" } +hashdb = { path = "../hashdb" } +rlp = { path = "../rlp" } diff --git a/util/src/memorydb.rs b/util/memorydb/src/lib.rs similarity index 96% rename from util/src/memorydb.rs rename to util/memorydb/src/lib.rs index bffb7ea29..041d97250 100644 --- a/util/src/memorydb.rs +++ b/util/memorydb/src/lib.rs @@ -15,6 +15,11 @@ // along with Parity. If not, see . //! Reference-counted memory-based `HashDB` implementation. +extern crate heapsize; +extern crate ethcore_bigint as bigint; +extern crate rlp; +extern crate hash as keccak; +extern crate hashdb; use std::mem; use std::collections::HashMap; @@ -34,9 +39,10 @@ use hashdb::*; /// /// # Example /// ```rust -/// extern crate ethcore_util; -/// use ethcore_util::hashdb::*; -/// use ethcore_util::memorydb::*; +/// extern crate hashdb; +/// extern crate memorydb; +/// use hashdb::*; +/// use memorydb::*; /// fn main() { /// let mut m = MemoryDB::new(); /// let d = "Hello world!".as_bytes(); @@ -85,9 +91,10 @@ impl MemoryDB { /// /// # Examples /// ```rust - /// extern crate ethcore_util; - /// use ethcore_util::hashdb::*; - /// use ethcore_util::memorydb::*; + /// extern crate hashdb; + /// extern crate memorydb; + /// use hashdb::*; + /// use memorydb::*; /// fn main() { /// let mut m = MemoryDB::new(); /// let hello_bytes = "Hello world!".as_bytes(); diff --git a/util/network/Cargo.toml b/util/network/Cargo.toml index f8d1e673b..ba34bfac7 100644 --- a/util/network/Cargo.toml +++ b/util/network/Cargo.toml @@ -25,6 +25,7 @@ rustc-serialize = "0.3" ethcore-io = { path = "../io" } ethcore-util = { path = ".." } ethcore-bigint = { path = "../bigint" } +ethcore-bytes = { path = "../bytes" } ethcore-devtools = { path = "../../devtools" } ethkey = { path = "../../ethkey" } ethcrypto = { path = "../../ethcrypto" } diff --git a/util/network/src/connection.rs b/util/network/src/connection.rs index f30d46838..fd61b4b38 100644 --- a/util/network/src/connection.rs +++ b/util/network/src/connection.rs @@ -23,7 +23,7 @@ use mio::{Token, Ready, PollOpt}; use mio::deprecated::{Handler, EventLoop, TryRead, TryWrite}; use mio::tcp::*; use bigint::hash::*; -use util::bytes::*; +use ethcore_bytes::*; use rlp::*; use std::io::{self, Cursor, Read, Write}; use error::*; @@ -510,7 +510,7 @@ mod tests { use std::io::{Read, Write, Error, Cursor, ErrorKind}; use mio::{Ready}; use std::collections::VecDeque; - use util::bytes::Bytes; + use ethcore_bytes::Bytes; use devtools::*; use io::*; diff --git a/util/network/src/discovery.rs b/util/network/src/discovery.rs index 205f101bf..4ff389b3c 100644 --- a/util/network/src/discovery.rs +++ b/util/network/src/discovery.rs @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -use util::bytes::Bytes; +use ethcore_bytes::Bytes; use std::net::SocketAddr; use std::collections::{HashSet, HashMap, BTreeMap, VecDeque}; use std::mem; diff --git a/util/network/src/handshake.rs b/util/network/src/handshake.rs index 40ad57d6f..bb5a5cb5d 100644 --- a/util/network/src/handshake.rs +++ b/util/network/src/handshake.rs @@ -19,7 +19,7 @@ use rand::random; use hash::write_keccak; use mio::tcp::*; use bigint::hash::*; -use util::bytes::Bytes; +use ethcore_bytes::Bytes; use rlp::*; use connection::{Connection}; use host::{HostInfo}; diff --git a/util/network/src/lib.rs b/util/network/src/lib.rs index beece7ad9..f23998984 100644 --- a/util/network/src/lib.rs +++ b/util/network/src/lib.rs @@ -60,6 +60,7 @@ extern crate ethcore_io as io; extern crate ethcore_util as util; extern crate ethcore_bigint as bigint; +extern crate ethcore_bytes; extern crate parking_lot; extern crate mio; extern crate tiny_keccak; diff --git a/util/network/src/tests.rs b/util/network/src/tests.rs index f6c8ed1e8..bf0e08623 100644 --- a/util/network/src/tests.rs +++ b/util/network/src/tests.rs @@ -20,7 +20,7 @@ use std::sync::Arc; use std::thread; use std::time::*; use parking_lot::Mutex; -use util::Bytes; +use ethcore_bytes::Bytes; use io::TimerToken; use ethkey::{Random, Generator}; diff --git a/util/nibbleslice/Cargo.toml b/util/nibbleslice/Cargo.toml new file mode 100644 index 000000000..0d0021d85 --- /dev/null +++ b/util/nibbleslice/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "nibbleslice" +version = "0.1.0" +authors = ["Parity Technologies "] + +[dependencies] +elastic-array = "0.9" diff --git a/util/src/nibbleslice.rs b/util/nibbleslice/src/lib.rs similarity index 99% rename from util/src/nibbleslice.rs rename to util/nibbleslice/src/lib.rs index d56c5ca48..60fa11227 100644 --- a/util/src/nibbleslice.rs +++ b/util/nibbleslice/src/lib.rs @@ -15,6 +15,8 @@ // along with Parity. If not, see . //! Nibble-orientated view onto byte-slice, allowing nibble-precision offsets. +extern crate elastic_array; + use std::cmp::*; use std::fmt; use elastic_array::ElasticArray36; @@ -25,8 +27,8 @@ use elastic_array::ElasticArray36; /// /// # Example /// ```rust -/// extern crate ethcore_util; -/// use ethcore_util::nibbleslice::*; +/// extern crate nibbleslice; +/// use nibbleslice::*; /// fn main() { /// let d1 = &[0x01u8, 0x23, 0x45]; /// let d2 = &[0x34u8, 0x50, 0x12]; diff --git a/util/nibblevec/Cargo.toml b/util/nibblevec/Cargo.toml new file mode 100644 index 000000000..df8e990d4 --- /dev/null +++ b/util/nibblevec/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "nibblevec" +version = "0.1.0" +authors = ["Parity Technologies "] + +[dependencies] +elastic-array = "0.9" +nibbleslice = { path = "../nibbleslice" } diff --git a/util/src/nibblevec.rs b/util/nibblevec/src/lib.rs similarity index 98% rename from util/src/nibblevec.rs rename to util/nibblevec/src/lib.rs index b38198593..c33056467 100644 --- a/util/src/nibblevec.rs +++ b/util/nibblevec/src/lib.rs @@ -16,6 +16,8 @@ //! An owning, nibble-oriented byte vector. +extern crate nibbleslice; +extern crate elastic_array; use nibbleslice::NibbleSlice; use elastic_array::ElasticArray36; diff --git a/util/src/journaldb/archivedb.rs b/util/src/journaldb/archivedb.rs index e77c908d3..52f80a39f 100644 --- a/util/src/journaldb/archivedb.rs +++ b/util/src/journaldb/archivedb.rs @@ -21,13 +21,13 @@ use std::collections::hash_map::Entry; use std::sync::Arc; use rlp::*; use hashdb::*; -use memorydb::*; +use super::super::memorydb::*; use super::{DB_PREFIX_LEN, LATEST_ERA_KEY}; use super::traits::JournalDB; use kvdb::{KeyValueDB, DBTransaction}; use bigint::hash::H256; use error::{BaseDataError, UtilError}; -use {Bytes}; +use bytes::Bytes; /// Implementation of the `HashDB` trait for a disk-backed database with a memory overlay /// and latent-removal semantics. diff --git a/util/src/journaldb/earlymergedb.rs b/util/src/journaldb/earlymergedb.rs index 2502fe219..a21a6eedb 100644 --- a/util/src/journaldb/earlymergedb.rs +++ b/util/src/journaldb/earlymergedb.rs @@ -30,7 +30,7 @@ use super::traits::JournalDB; use kvdb::{KeyValueDB, DBTransaction}; use bigint::hash::H256; use error::{BaseDataError, UtilError}; -use {Bytes}; +use bytes::Bytes; #[derive(Clone, PartialEq, Eq)] struct RefInfo { diff --git a/util/src/journaldb/overlayrecentdb.rs b/util/src/journaldb/overlayrecentdb.rs index c450e53d8..687333d67 100644 --- a/util/src/journaldb/overlayrecentdb.rs +++ b/util/src/journaldb/overlayrecentdb.rs @@ -29,7 +29,7 @@ use kvdb::{KeyValueDB, DBTransaction}; use super::JournalDB; use bigint::hash::{H256, H256FastMap}; use error::{BaseDataError, UtilError}; -use {Bytes}; +use bytes::Bytes; /// Implementation of the `JournalDB` trait for a disk-backed database with a memory overlay /// and, possibly, latent-removal semantics. diff --git a/util/src/journaldb/refcounteddb.rs b/util/src/journaldb/refcounteddb.rs index 7b970d640..bcdcdabb5 100644 --- a/util/src/journaldb/refcounteddb.rs +++ b/util/src/journaldb/refcounteddb.rs @@ -27,7 +27,8 @@ use super::{DB_PREFIX_LEN, LATEST_ERA_KEY}; use super::traits::JournalDB; use kvdb::{KeyValueDB, DBTransaction}; use bigint::hash::H256; -use {UtilError, Bytes}; +use UtilError; +use bytes::Bytes; /// Implementation of the `HashDB` trait for a disk-backed database with a memory overlay /// and latent-removal semantics. diff --git a/util/src/journaldb/traits.rs b/util/src/journaldb/traits.rs index b70bbdcd9..c4cd2ad16 100644 --- a/util/src/journaldb/traits.rs +++ b/util/src/journaldb/traits.rs @@ -20,7 +20,8 @@ use std::sync::Arc; use hashdb::*; use kvdb::{self, DBTransaction}; use bigint::hash::H256; -use {Bytes, UtilError}; +use UtilError; +use bytes::Bytes; /// A `HashDB` which can manage a short-term journal potentially containing many forks of mutually /// exclusive actions. diff --git a/util/src/kvdb.rs b/util/src/kvdb.rs index 1e2510c0a..4f394b2d4 100644 --- a/util/src/kvdb.rs +++ b/util/src/kvdb.rs @@ -28,7 +28,8 @@ use hashdb::DBValue; use rlp::{UntrustedRlp, RlpType, Compressible}; use rocksdb::{DB, Writable, WriteBatch, WriteOptions, IteratorMode, DBIterator, Options, DBCompactionStyle, BlockBasedOptions, Direction, Cache, Column, ReadOptions}; -use {UtilError, Bytes}; +use UtilError; +use bytes::Bytes; #[cfg(target_os = "linux")] diff --git a/util/src/lib.rs b/util/src/lib.rs index 00399b823..1866ea54a 100644 --- a/util/src/lib.rs +++ b/util/src/lib.rs @@ -96,6 +96,7 @@ extern crate ethcore_devtools as devtools; extern crate libc; extern crate target_info; extern crate ethcore_bigint as bigint; +extern crate ethcore_bytes as bytes; extern crate parking_lot; extern crate tiny_keccak; extern crate rlp; @@ -104,6 +105,9 @@ extern crate lru_cache; extern crate heapsize; extern crate ethcore_logger; extern crate hash as keccak; +extern crate hashdb; +extern crate memorydb; +extern crate trie; #[macro_use] extern crate error_chain; @@ -114,17 +118,11 @@ extern crate log as rlog; #[macro_use] pub mod common; pub mod error; -pub mod bytes; pub mod misc; -pub mod hashdb; -pub mod memorydb; pub mod migration; pub mod overlaydb; pub mod journaldb; pub mod kvdb; -pub mod trie; -pub mod nibbleslice; -pub mod nibblevec; pub mod snappy; pub mod cache; @@ -133,10 +131,8 @@ pub use hashdb::*; pub use memorydb::MemoryDB; pub use overlaydb::*; pub use journaldb::JournalDB; -pub use trie::{Trie, TrieMut, TrieDB, TrieDBMut, TrieFactory, TrieError, SecTrieDB, SecTrieDBMut}; pub use kvdb::*; pub use error::UtilError; -pub use bytes::*; /// 160-bit integer representing account address pub type Address = bigint::hash::H160; diff --git a/util/src/misc.rs b/util/src/misc.rs index e33b5e857..6a1a11708 100644 --- a/util/src/misc.rs +++ b/util/src/misc.rs @@ -18,7 +18,7 @@ use rlp::RlpStream; use target_info::Target; -use Bytes; +use bytes::Bytes; include!(concat!(env!("OUT_DIR"), "/version.rs")); include!(concat!(env!("OUT_DIR"), "/rustc_version.rs")); diff --git a/util/trie/Cargo.toml b/util/trie/Cargo.toml new file mode 100644 index 000000000..f3df821e5 --- /dev/null +++ b/util/trie/Cargo.toml @@ -0,0 +1,21 @@ +[package] +name = "trie" +version = "0.1.0" +authors = ["Parity Technologies "] + +[dependencies] +elastic-array = "0.9" +log = "0.3" +rand = "0.3" +ethcore-bytes = { path = "../bytes" } +ethcore-bigint = { path = "../bigint" } +hash = { path = "../hash" } +hashdb = { path = "../hashdb" } +rlp = { path = "../rlp" } +nibbleslice = { path = "../nibbleslice" } +nibblevec = { path = "../nibblevec" } +triehash = { path = "../triehash" } +memorydb = { path = "../memorydb" } +ethcore-logger = { path = "../../logger" } + + diff --git a/util/src/trie/fatdb.rs b/util/trie/src/fatdb.rs similarity index 98% rename from util/src/trie/fatdb.rs rename to util/trie/src/fatdb.rs index 0793c1ba5..4602482b1 100644 --- a/util/src/trie/fatdb.rs +++ b/util/trie/src/fatdb.rs @@ -105,7 +105,8 @@ impl<'db> Iterator for FatDBIterator<'db> { fn fatdb_to_trie() { use memorydb::MemoryDB; use hashdb::DBValue; - use trie::{FatDBMut, TrieMut}; + use super::fatdbmut::FatDBMut; + use super::TrieMut; let mut memdb = MemoryDB::new(); let mut root = H256::default(); diff --git a/util/src/trie/fatdbmut.rs b/util/trie/src/fatdbmut.rs similarity index 100% rename from util/src/trie/fatdbmut.rs rename to util/trie/src/fatdbmut.rs diff --git a/util/src/trie/mod.rs b/util/trie/src/lib.rs similarity index 96% rename from util/src/trie/mod.rs rename to util/trie/src/lib.rs index 457cc13e8..b927437d6 100644 --- a/util/src/trie/mod.rs +++ b/util/trie/src/lib.rs @@ -15,6 +15,20 @@ // along with Parity. If not, see . //! Trie interface and implementation. +extern crate rand; +extern crate ethcore_bigint as bigint; +extern crate hash as keccak; +extern crate rlp; +extern crate hashdb; +extern crate ethcore_bytes as bytes; +extern crate nibbleslice; +extern crate nibblevec; +extern crate elastic_array; +extern crate memorydb; +extern crate ethcore_logger; + +#[macro_use] +extern crate log; use std::fmt; use bigint::hash::H256; diff --git a/util/src/trie/lookup.rs b/util/trie/src/lookup.rs similarity index 100% rename from util/src/trie/lookup.rs rename to util/trie/src/lookup.rs diff --git a/util/src/trie/node.rs b/util/trie/src/node.rs similarity index 100% rename from util/src/trie/node.rs rename to util/trie/src/node.rs diff --git a/util/src/trie/recorder.rs b/util/trie/src/recorder.rs similarity index 98% rename from util/src/trie/recorder.rs rename to util/trie/src/recorder.rs index f2b7fd91f..ce52ff780 100644 --- a/util/src/trie/recorder.rs +++ b/util/trie/src/recorder.rs @@ -18,7 +18,7 @@ use keccak::keccak; use bigint::hash::H256; -use Bytes; +use bytes::Bytes; /// A record of a visited node. #[derive(PartialEq, Eq, Debug, Clone)] @@ -136,7 +136,7 @@ mod tests { #[test] fn trie_record() { - use trie::{TrieDB, TrieDBMut, Trie, TrieMut}; + use super::super::{TrieDB, TrieDBMut, Trie, TrieMut}; use memorydb::MemoryDB; let mut db = MemoryDB::new(); diff --git a/util/src/trie/sectriedb.rs b/util/trie/src/sectriedb.rs similarity index 98% rename from util/src/trie/sectriedb.rs rename to util/trie/src/sectriedb.rs index ce617d9d0..2bf55dd92 100644 --- a/util/src/trie/sectriedb.rs +++ b/util/trie/src/sectriedb.rs @@ -71,7 +71,7 @@ fn trie_to_sectrie() { use memorydb::MemoryDB; use hashdb::DBValue; use super::triedbmut::TrieDBMut; - use super::super::TrieMut; + use super::TrieMut; let mut memdb = MemoryDB::new(); let mut root = H256::default(); diff --git a/util/src/trie/sectriedbmut.rs b/util/trie/src/sectriedbmut.rs similarity index 100% rename from util/src/trie/sectriedbmut.rs rename to util/trie/src/sectriedbmut.rs diff --git a/util/src/trie/standardmap.rs b/util/trie/src/standardmap.rs similarity index 100% rename from util/src/trie/standardmap.rs rename to util/trie/src/standardmap.rs diff --git a/util/src/trie/triedb.rs b/util/trie/src/triedb.rs similarity index 98% rename from util/src/trie/triedb.rs rename to util/trie/src/triedb.rs index 208d257bb..6e46b5a7c 100644 --- a/util/src/trie/triedb.rs +++ b/util/trie/src/triedb.rs @@ -22,7 +22,7 @@ use super::node::{Node, OwnedNode}; use super::lookup::Lookup; use super::{Trie, TrieItem, TrieError, TrieIterator, Query}; use bigint::hash::H256; -use {ToPretty, Bytes}; +use bytes::{ToPretty, Bytes}; /// A `Trie` implementation using a generic `HashDB` backing database. /// @@ -31,12 +31,14 @@ use {ToPretty, Bytes}; /// /// # Example /// ``` -/// extern crate ethcore_util as util; +/// extern crate trie; +/// extern crate hashdb; +/// extern crate memorydb; /// extern crate ethcore_bigint as bigint; /// -/// use util::trie::*; -/// use util::hashdb::*; -/// use util::memorydb::*; +/// use trie::*; +/// use hashdb::*; +/// use memorydb::*; /// use bigint::hash::*; /// /// fn main() { diff --git a/util/src/trie/triedbmut.rs b/util/trie/src/triedbmut.rs similarity index 99% rename from util/src/trie/triedbmut.rs rename to util/trie/src/triedbmut.rs index 594bb1380..4ec5d78f9 100644 --- a/util/src/trie/triedbmut.rs +++ b/util/trie/src/triedbmut.rs @@ -21,10 +21,10 @@ use super::lookup::Lookup; use super::node::Node as RlpNode; use super::node::NodeKey; -use ::HashDB; -use ::bytes::ToPretty; -use ::nibbleslice::NibbleSlice; -use ::rlp::{Rlp, RlpStream}; +use hashdb::HashDB; +use bytes::ToPretty; +use nibbleslice::NibbleSlice; +use rlp::{Rlp, RlpStream}; use hashdb::DBValue; use std::collections::{HashSet, VecDeque}; @@ -261,14 +261,16 @@ impl<'a> Index<&'a StorageHandle> for NodeStorage { /// /// # Example /// ``` -/// extern crate ethcore_util as util; +/// extern crate trie; +/// extern crate hashdb; +/// extern crate memorydb; /// extern crate ethcore_bigint as bigint; /// extern crate hash; /// /// use hash::KECCAK_NULL_RLP; -/// use util::trie::*; -/// use util::hashdb::*; -/// use util::memorydb::*; +/// use trie::*; +/// use hashdb::*; +/// use memorydb::*; /// use bigint::hash::*; /// /// fn main() { From dd7a60c7a8e8216f0d797ef0e1dfea229a1fb527 Mon Sep 17 00:00:00 2001 From: Hawstein Date: Wed, 13 Sep 2017 01:23:02 +0800 Subject: [PATCH 6/9] rename trie to patricia-trie --- Cargo.lock | 62 +++++++++---------- ethcore/Cargo.toml | 2 +- ethcore/light/Cargo.toml | 2 +- ethcore/light/src/lib.rs | 2 +- ethcore/light/src/types/request/mod.rs | 2 +- ethcore/res/wasm-tests | 2 +- ethcore/src/lib.rs | 2 +- ethcore/vm/Cargo.toml | 2 +- ethcore/vm/src/lib.rs | 2 +- util/Cargo.toml | 2 +- util/benches/trie.rs | 2 +- util/{trie => patricia_trie}/Cargo.toml | 2 +- util/{trie => patricia_trie}/src/fatdb.rs | 0 util/{trie => patricia_trie}/src/fatdbmut.rs | 0 util/{trie => patricia_trie}/src/lib.rs | 0 util/{trie => patricia_trie}/src/lookup.rs | 0 util/{trie => patricia_trie}/src/node.rs | 0 util/{trie => patricia_trie}/src/recorder.rs | 0 util/{trie => patricia_trie}/src/sectriedb.rs | 0 .../src/sectriedbmut.rs | 0 .../src/standardmap.rs | 0 util/{trie => patricia_trie}/src/triedb.rs | 2 +- util/{trie => patricia_trie}/src/triedbmut.rs | 2 +- util/src/lib.rs | 2 +- 24 files changed, 45 insertions(+), 45 deletions(-) rename util/{trie => patricia_trie}/Cargo.toml (95%) rename util/{trie => patricia_trie}/src/fatdb.rs (100%) rename util/{trie => patricia_trie}/src/fatdbmut.rs (100%) rename util/{trie => patricia_trie}/src/lib.rs (100%) rename util/{trie => patricia_trie}/src/lookup.rs (100%) rename util/{trie => patricia_trie}/src/node.rs (100%) rename util/{trie => patricia_trie}/src/recorder.rs (100%) rename util/{trie => patricia_trie}/src/sectriedb.rs (100%) rename util/{trie => patricia_trie}/src/sectriedbmut.rs (100%) rename util/{trie => patricia_trie}/src/standardmap.rs (100%) rename util/{trie => patricia_trie}/src/triedb.rs (99%) rename util/{trie => patricia_trie}/src/triedbmut.rs (99%) diff --git a/Cargo.lock b/Cargo.lock index e3fd78eb9..3c88f0cdb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -576,8 +576,8 @@ dependencies = [ "futures 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", "hardware-wallet 1.8.0", "hash 0.1.0", - "heapsize 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "hashdb 0.1.0", + "heapsize 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "hyper 0.10.0-a.0 (git+https://github.com/paritytech/hyper)", "itertools 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -589,6 +589,7 @@ dependencies = [ "num 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", + "patricia_trie 0.1.0", "price-info 1.7.0", "rand 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)", "rayon 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -602,7 +603,6 @@ dependencies = [ "table 0.1.0", "time 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)", "transient-hashmap 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "trie 0.1.0", "triehash 0.1.0", "unexpected 0.1.0", "using_queue 0.1.0", @@ -733,9 +733,10 @@ dependencies = [ "heapsize 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "itertools 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)", "memorydb 0.1.0", + "parking_lot 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", + "patricia_trie 0.1.0", + "rand 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)", "rlp 0.2.0", "rlp_derive 0.1.0", "serde 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)", @@ -743,7 +744,6 @@ dependencies = [ "smallvec 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", "stats 0.1.0", "time 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)", - "trie 0.1.0", "triehash 0.1.0", "vm 0.1.0", ] @@ -871,23 +871,23 @@ dependencies = [ "ethcore-devtools 1.8.0", "ethcore-logger 1.8.0", "hash 0.1.0", + "hashdb 0.1.0", "heapsize 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.30 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "lru-cache 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "hashdb 0.1.0", "memorydb 0.1.0", "nibbleslice 0.1.0", "nibblevec 0.1.0", + "parking_lot 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", + "patricia_trie 0.1.0", + "regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "rlp 0.2.0", "rocksdb 0.4.5 (git+https://github.com/paritytech/rust-rocksdb)", "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "target_info 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "tiny-keccak 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "trie 0.1.0", "triehash 0.1.0", "vergen 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1580,12 +1580,12 @@ dependencies = [ name = "memorydb" version = "0.1.0" dependencies = [ - "bigint 4.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "bigint 4.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "elastic-array 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "ethcore-bigint 0.1.3", "hash 0.1.0", "hashdb 0.1.0", - "heapsize 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "heapsize 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "rlp 0.2.0", ] @@ -2373,6 +2373,25 @@ dependencies = [ name = "path" version = "0.1.0" +[[package]] +name = "patricia_trie" +version = "0.1.0" +dependencies = [ + "elastic-array 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ethcore-bigint 0.1.3", + "ethcore-bytes 0.1.0", + "ethcore-logger 1.8.0", + "hash 0.1.0", + "hashdb 0.1.0", + "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "memorydb 0.1.0", + "nibbleslice 0.1.0", + "nibblevec 0.1.0", + "rand 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)", + "rlp 0.2.0", + "triehash 0.1.0", +] + [[package]] name = "percent-encoding" version = "1.0.0" @@ -3304,25 +3323,6 @@ dependencies = [ "protobuf 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "trie" -version = "0.1.0" -dependencies = [ - "elastic-array 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "ethcore-bigint 0.1.3", - "ethcore-bytes 0.1.0", - "ethcore-logger 1.8.0", - "hash 0.1.0", - "hashdb 0.1.0", - "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", - "memorydb 0.1.0", - "nibbleslice 0.1.0", - "nibblevec 0.1.0", - "rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", - "rlp 0.2.0", - "triehash 0.1.0", -] - [[package]] name = "triehash" version = "0.1.0" @@ -3464,8 +3464,8 @@ dependencies = [ "hash 0.1.0", "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "patricia_trie 0.1.0", "rlp 0.2.0", - "trie 0.1.0", ] [[package]] diff --git a/ethcore/Cargo.toml b/ethcore/Cargo.toml index 638454aac..9d82efd27 100644 --- a/ethcore/Cargo.toml +++ b/ethcore/Cargo.toml @@ -26,7 +26,7 @@ ethcore-bloom-journal = { path = "../util/bloom" } ethcore-bytes = { path = "../util/bytes" } hashdb = { path = "../util/hashdb" } memorydb = { path = "../util/memorydb" } -trie = { path = "../util/trie" } +patricia_trie = { path = "../util/patricia_trie" } ethcore-devtools = { path = "../devtools" } ethcore-io = { path = "../util/io" } ethcore-ipc = { path = "../ipc/rpc" } diff --git a/ethcore/light/Cargo.toml b/ethcore/light/Cargo.toml index e7cf959ad..477b7077a 100644 --- a/ethcore/light/Cargo.toml +++ b/ethcore/light/Cargo.toml @@ -17,7 +17,7 @@ ethcore-util = { path = "../../util" } ethcore-bigint = { path = "../../util/bigint" } ethcore-bytes = { path = "../../util/bytes" } memorydb = { path = "../../util/memorydb" } -trie = { path = "../../util/trie" } +patricia_trie = { path = "../../util/patricia_trie" } ethcore-network = { path = "../../util/network" } ethcore-io = { path = "../../util/io" } ethcore-ipc = { path = "../../ipc/rpc", optional = true } diff --git a/ethcore/light/src/lib.rs b/ethcore/light/src/lib.rs index 4cf0b3e58..09eade4e7 100644 --- a/ethcore/light/src/lib.rs +++ b/ethcore/light/src/lib.rs @@ -78,7 +78,7 @@ extern crate heapsize; extern crate futures; extern crate itertools; extern crate memorydb; -extern crate trie; +extern crate patricia_trie as trie; extern crate rand; extern crate rlp; extern crate parking_lot; diff --git a/ethcore/light/src/types/request/mod.rs b/ethcore/light/src/types/request/mod.rs index c33d8b4cc..d96278c23 100644 --- a/ethcore/light/src/types/request/mod.rs +++ b/ethcore/light/src/types/request/mod.rs @@ -1542,7 +1542,7 @@ pub mod epoch_signal { use super::{Field, NoSuchOutput, OutputKind, Output}; use rlp::{Encodable, Decodable, DecoderError, RlpStream, UntrustedRlp}; use bigint::hash::H256; - use util::Bytes; + use bytes::Bytes; /// Potentially incomplete epoch signal request. #[derive(Debug, Clone, PartialEq, Eq)] diff --git a/ethcore/res/wasm-tests b/ethcore/res/wasm-tests index 5fd27564f..fcac936bf 160000 --- a/ethcore/res/wasm-tests +++ b/ethcore/res/wasm-tests @@ -1 +1 @@ -Subproject commit 5fd27564f1ab49b25bb419bfc0cc68137e1f12f2 +Subproject commit fcac936bf68cc271a6a6ac088efb458f3a08f38a diff --git a/ethcore/src/lib.rs b/ethcore/src/lib.rs index 6edd2261e..689cc67f8 100644 --- a/ethcore/src/lib.rs +++ b/ethcore/src/lib.rs @@ -109,7 +109,7 @@ extern crate rlp; extern crate hash; extern crate heapsize; extern crate memorydb; -extern crate trie; +extern crate patricia_trie as trie; extern crate triehash; extern crate ansi_term; extern crate semantic_version; diff --git a/ethcore/vm/Cargo.toml b/ethcore/vm/Cargo.toml index 957e6450d..ade675044 100644 --- a/ethcore/vm/Cargo.toml +++ b/ethcore/vm/Cargo.toml @@ -8,7 +8,7 @@ byteorder = "1.0" ethcore-util = { path = "../../util" } ethcore-bytes = { path = "../../util/bytes" } ethcore-bigint = { path = "../../util/bigint" } -trie = { path = "../../util/trie" } +patricia_trie = { path = "../../util/patricia_trie" } log = "0.3" common-types = { path = "../types" } evmjit = { path = "../../evmjit", optional = true } diff --git a/ethcore/vm/src/lib.rs b/ethcore/vm/src/lib.rs index 0bbef3702..56a380597 100644 --- a/ethcore/vm/src/lib.rs +++ b/ethcore/vm/src/lib.rs @@ -23,7 +23,7 @@ extern crate common_types as types; extern crate ethjson; extern crate rlp; extern crate hash; -extern crate trie; +extern crate patricia_trie as trie; mod action_params; mod call_type; diff --git a/util/Cargo.toml b/util/Cargo.toml index cef815099..28d53c6e5 100644 --- a/util/Cargo.toml +++ b/util/Cargo.toml @@ -31,7 +31,7 @@ ethcore-logger = { path = "../logger" } triehash = { path = "triehash" } error-chain = "0.11.0-rc.2" hashdb = { path = "hashdb" } -trie = { path = "trie" } +patricia_trie = { path = "patricia_trie" } nibbleslice = { path = "nibbleslice" } nibblevec = { path = "nibblevec" } ethcore-bytes = { path = "bytes" } diff --git a/util/benches/trie.rs b/util/benches/trie.rs index 3ec2f9ba0..953c18883 100644 --- a/util/benches/trie.rs +++ b/util/benches/trie.rs @@ -22,7 +22,7 @@ extern crate ethcore_util; extern crate ethcore_bytes; extern crate ethcore_bigint; extern crate memorydb; -extern crate trie; +extern crate patricia_trie as trie; #[macro_use] extern crate log; extern crate hash; diff --git a/util/trie/Cargo.toml b/util/patricia_trie/Cargo.toml similarity index 95% rename from util/trie/Cargo.toml rename to util/patricia_trie/Cargo.toml index f3df821e5..0dcd74e09 100644 --- a/util/trie/Cargo.toml +++ b/util/patricia_trie/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "trie" +name = "patricia_trie" version = "0.1.0" authors = ["Parity Technologies "] diff --git a/util/trie/src/fatdb.rs b/util/patricia_trie/src/fatdb.rs similarity index 100% rename from util/trie/src/fatdb.rs rename to util/patricia_trie/src/fatdb.rs diff --git a/util/trie/src/fatdbmut.rs b/util/patricia_trie/src/fatdbmut.rs similarity index 100% rename from util/trie/src/fatdbmut.rs rename to util/patricia_trie/src/fatdbmut.rs diff --git a/util/trie/src/lib.rs b/util/patricia_trie/src/lib.rs similarity index 100% rename from util/trie/src/lib.rs rename to util/patricia_trie/src/lib.rs diff --git a/util/trie/src/lookup.rs b/util/patricia_trie/src/lookup.rs similarity index 100% rename from util/trie/src/lookup.rs rename to util/patricia_trie/src/lookup.rs diff --git a/util/trie/src/node.rs b/util/patricia_trie/src/node.rs similarity index 100% rename from util/trie/src/node.rs rename to util/patricia_trie/src/node.rs diff --git a/util/trie/src/recorder.rs b/util/patricia_trie/src/recorder.rs similarity index 100% rename from util/trie/src/recorder.rs rename to util/patricia_trie/src/recorder.rs diff --git a/util/trie/src/sectriedb.rs b/util/patricia_trie/src/sectriedb.rs similarity index 100% rename from util/trie/src/sectriedb.rs rename to util/patricia_trie/src/sectriedb.rs diff --git a/util/trie/src/sectriedbmut.rs b/util/patricia_trie/src/sectriedbmut.rs similarity index 100% rename from util/trie/src/sectriedbmut.rs rename to util/patricia_trie/src/sectriedbmut.rs diff --git a/util/trie/src/standardmap.rs b/util/patricia_trie/src/standardmap.rs similarity index 100% rename from util/trie/src/standardmap.rs rename to util/patricia_trie/src/standardmap.rs diff --git a/util/trie/src/triedb.rs b/util/patricia_trie/src/triedb.rs similarity index 99% rename from util/trie/src/triedb.rs rename to util/patricia_trie/src/triedb.rs index 6e46b5a7c..6c1a0da01 100644 --- a/util/trie/src/triedb.rs +++ b/util/patricia_trie/src/triedb.rs @@ -31,7 +31,7 @@ use bytes::{ToPretty, Bytes}; /// /// # Example /// ``` -/// extern crate trie; +/// extern crate patricia_trie as trie; /// extern crate hashdb; /// extern crate memorydb; /// extern crate ethcore_bigint as bigint; diff --git a/util/trie/src/triedbmut.rs b/util/patricia_trie/src/triedbmut.rs similarity index 99% rename from util/trie/src/triedbmut.rs rename to util/patricia_trie/src/triedbmut.rs index 4ec5d78f9..d0e22d2fb 100644 --- a/util/trie/src/triedbmut.rs +++ b/util/patricia_trie/src/triedbmut.rs @@ -261,7 +261,7 @@ impl<'a> Index<&'a StorageHandle> for NodeStorage { /// /// # Example /// ``` -/// extern crate trie; +/// extern crate patricia_trie as trie; /// extern crate hashdb; /// extern crate memorydb; /// extern crate ethcore_bigint as bigint; diff --git a/util/src/lib.rs b/util/src/lib.rs index 1866ea54a..d4b1e544d 100644 --- a/util/src/lib.rs +++ b/util/src/lib.rs @@ -107,7 +107,7 @@ extern crate ethcore_logger; extern crate hash as keccak; extern crate hashdb; extern crate memorydb; -extern crate trie; +extern crate patricia_trie as trie; #[macro_use] extern crate error_chain; From 54bd7d26dc137fb3455b18cdabaf030591d63084 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Fri, 15 Sep 2017 14:45:55 +0200 Subject: [PATCH 7/9] Downgrade futures. (#6521) --- Cargo.lock | 66 +++++++++++++++++++++++++++--------------------------- 1 file changed, 33 insertions(+), 33 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3c88f0cdb..bca7d8ed7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -573,7 +573,7 @@ dependencies = [ "ethkey 0.2.0", "ethstore 0.1.0", "evm 0.1.0", - "futures 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", "hardware-wallet 1.8.0", "hash 0.1.0", "hashdb 0.1.0", @@ -728,7 +728,7 @@ dependencies = [ "ethcore-network 1.8.0", "ethcore-util 1.8.0", "evm 0.1.0", - "futures 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", "hash 0.1.0", "heapsize 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "itertools 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)", @@ -813,7 +813,7 @@ dependencies = [ "ethcore-util 1.8.0", "ethcrypto 0.1.0", "ethkey 0.2.0", - "futures 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", "futures-cpupool 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "hash 0.1.0", "hyper 0.10.13 (registry+https://github.com/rust-lang/crates.io-index)", @@ -844,7 +844,7 @@ dependencies = [ "ethcore-ipc-nano 1.8.0", "ethcore-logger 1.8.0", "ethcore-util 1.8.0", - "futures 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", "hash 0.1.0", "jsonrpc-core 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)", "jsonrpc-macros 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)", @@ -1069,7 +1069,7 @@ dependencies = [ name = "fetch" version = "0.1.0" dependencies = [ - "futures 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", "futures-cpupool 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "mime 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1098,7 +1098,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "futures" -version = "0.1.15" +version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -1106,7 +1106,7 @@ name = "futures-cpupool" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "futures 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.6.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1348,7 +1348,7 @@ name = "jsonrpc-core" version = "7.0.0" source = "git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7#b5490782884218c5ccf74cd61e54904cb3a3aeed" dependencies = [ - "futures 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1727,7 +1727,7 @@ dependencies = [ "byteorder 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "ethabi 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "ethcore-bigint 0.1.3", - "futures 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", "native-contract-generator 0.1.0", ] @@ -1780,7 +1780,7 @@ dependencies = [ "ethcore-io 1.8.0", "ethcore-network 1.8.0", "ethcore-util 1.8.0", - "futures 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "native-contracts 0.1.0", "parking_lot 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1790,7 +1790,7 @@ dependencies = [ name = "node-health" version = "0.1.0" dependencies = [ - "futures 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", "futures-cpupool 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "ntp 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2005,7 +2005,7 @@ dependencies = [ "ethkey 0.2.0", "ethsync 1.8.0", "fdlimit 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", "futures-cpupool 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "hash 0.1.0", "ipnetwork 0.12.7 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2057,7 +2057,7 @@ dependencies = [ "ethcore-devtools 1.8.0", "ethcore-util 1.8.0", "fetch 0.1.0", - "futures 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", "hash 0.1.0", "itertools 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)", "jsonrpc-core 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)", @@ -2106,7 +2106,7 @@ dependencies = [ "ethcore-bytes 0.1.0", "ethcore-util 1.8.0", "fetch 0.1.0", - "futures 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", "hash 0.1.0", "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "mime 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2152,7 +2152,7 @@ dependencies = [ name = "parity-reactor" version = "0.1.0" dependencies = [ - "futures 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-core 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2180,7 +2180,7 @@ dependencies = [ "ethstore 0.1.0", "ethsync 1.8.0", "fetch 0.1.0", - "futures 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", "futures-cpupool 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "hardware-wallet 1.8.0", "hash 0.1.0", @@ -2220,7 +2220,7 @@ name = "parity-rpc-client" version = "1.4.0" dependencies = [ "ethcore-util 1.8.0", - "futures 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", "hash 0.1.0", "jsonrpc-core 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)", "jsonrpc-ws-server 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)", @@ -2241,7 +2241,7 @@ version = "0.1.5" source = "git+https://github.com/nikvolf/parity-tokio-ipc#d6c5b3cfcc913a1b9cf0f0562a10b083ceb9fb7c" dependencies = [ "bytes 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "mio-named-pipes 0.1.4 (git+https://github.com/alexcrichton/mio-named-pipes)", "miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2288,7 +2288,7 @@ dependencies = [ "ethcore-ipc-codegen 1.8.0", "ethcore-util 1.8.0", "ethsync 1.8.0", - "futures 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", "ipc-common-types 1.8.0", "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "parity-hash-fetch 1.8.0", @@ -2318,7 +2318,7 @@ dependencies = [ "ethcore-network 1.8.0", "ethcrypto 0.1.0", "ethkey 0.2.0", - "futures 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", "hex 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "jsonrpc-core 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)", "jsonrpc-macros 7.0.0 (git+https://github.com/paritytech/jsonrpc.git?branch=parity-1.7)", @@ -2462,7 +2462,7 @@ name = "price-info" version = "1.7.0" dependencies = [ "fetch 0.1.0", - "futures 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2606,7 +2606,7 @@ version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "coco 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.30 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.6.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2746,7 +2746,7 @@ version = "1.4.0" dependencies = [ "bigint 4.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "ethcore-util 1.8.0", - "futures 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", "parity-rpc 1.8.0", "parity-rpc-client 1.4.0", "rpassword 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3172,7 +3172,7 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", "iovec 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3187,7 +3187,7 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -3197,7 +3197,7 @@ version = "0.1.0" source = "git+https://github.com/tomusdrw/tokio-minihttp#67a400060bd29e51beaf206c552845255b6f699f" dependencies = [ "bytes 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", "httparse 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "net2 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3214,7 +3214,7 @@ version = "0.1.0" source = "git+https://github.com/nikvolf/tokio-named-pipes#0b9b728eaeb0a6673c287ac7692be398fd651752" dependencies = [ "bytes 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", "mio-named-pipes 0.1.4 (git+https://github.com/alexcrichton/mio-named-pipes)", "tokio-core 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3225,7 +3225,7 @@ name = "tokio-proto" version = "0.1.0" source = "git+https://github.com/tomusdrw/tokio-proto#f6ee08cb594fa2fc1b4178eaaca0855d66e68fd3" dependencies = [ - "futures 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "net2 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3241,7 +3241,7 @@ name = "tokio-proto" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "futures 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "net2 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3258,7 +3258,7 @@ name = "tokio-service" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "futures 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -3266,7 +3266,7 @@ name = "tokio-timer" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "futures 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -3276,7 +3276,7 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", "iovec 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.30 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3616,7 +3616,7 @@ dependencies = [ "checksum flate2 0.2.19 (registry+https://github.com/rust-lang/crates.io-index)" = "36df0166e856739905cd3d7e0b210fe818592211a008862599845e012d8d304c" "checksum fnv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6cc484842f1e2884faf56f529f960cc12ad8c71ce96cc7abba0a067c98fee344" "checksum foreign-types 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3e4056b9bd47f8ac5ba12be771f77a0dae796d1bbaaf5fd0b9c2d38b69b8a29d" -"checksum futures 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)" = "a82bdc62350ca9d7974c760e9665102fc9d740992a528c2254aa930e53b783c4" +"checksum futures 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "4b63a4792d4f8f686defe3b39b92127fea6344de5d38202b2ee5a11bbbf29d6a" "checksum futures-cpupool 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "a283c84501e92cade5ea673a2a7ca44f71f209ccdd302a3e0896f50083d2c5ff" "checksum gcc 0.3.53 (registry+https://github.com/rust-lang/crates.io-index)" = "e8310f7e9c890398b0e80e301c4f474e9918d2b27fca8f48486ca775fa9ffc5a" "checksum getopts 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)" = "65922871abd2f101a2eb0eaebadc66668e54a87ad9c3dd82520b5f86ede5eff9" From b602fb4a5ead81cff4e5b7e75c42183c25bc1b6d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Fri, 15 Sep 2017 15:06:42 +0200 Subject: [PATCH 8/9] Fix extension detection (#6452) * Fix extension detection. * Fix mobx quirks. * Update submodule. --- js/src/ui/SelectionList/selectionList.css | 1 + js/src/views/Application/Extension/store.js | 28 +++++++++++++-------- 2 files changed, 19 insertions(+), 10 deletions(-) diff --git a/js/src/ui/SelectionList/selectionList.css b/js/src/ui/SelectionList/selectionList.css index b6e6b05f9..73721e54a 100644 --- a/js/src/ui/SelectionList/selectionList.css +++ b/js/src/ui/SelectionList/selectionList.css @@ -22,6 +22,7 @@ height: 100%; position: relative; width: 100%; + max-width: 100%; &:hover { filter: none; diff --git a/js/src/views/Application/Extension/store.js b/js/src/views/Application/Extension/store.js index d1df2eb5b..af4b1a205 100644 --- a/js/src/views/Application/Extension/store.js +++ b/js/src/views/Application/Extension/store.js @@ -39,7 +39,6 @@ export default class Store { constructor () { this.nextDisplay = store.get(NEXT_DISPLAY) || 0; - this.testInstall(); } @computed get showWarning () { @@ -59,20 +58,29 @@ export default class Store { store.set(NEXT_DISPLAY, this.nextDisplay); } - @action testInstall = () => { - this.shouldInstall = this.readStatus(); + @action setShouldInstall = (status) => { + this.shouldInstall = status; + } + + testInstall = () => { + this.readStatus().then(this.setShouldInstall); } readStatus = () => { - const hasExtension = Symbol.for('parity.extension') in window; - const ua = browser.analyze(navigator.userAgent || ''); + return new Promise((resolve, reject) => { + // Defer checking for the extension since it may not have loaded yet. + setTimeout(() => { + const hasExtension = Symbol.for('parity.extension') in window; + const ua = browser.analyze(navigator.userAgent || ''); - if (hasExtension) { - this.setExtensionActive(); - return false; - } + if (hasExtension) { + this.setExtensionActive(); + return resolve(false); + } - return (ua || {}).name.toLowerCase() === 'chrome'; + return resolve((ua || {}).name.toLowerCase() === 'chrome'); + }, 5000); + }); } installExtension = () => { From 25b35ebddd11e400d48c891bf5ea4b75851ea4cf Mon Sep 17 00:00:00 2001 From: Arkadiy Paronyan Date: Fri, 15 Sep 2017 21:07:54 +0200 Subject: [PATCH 9/9] Byzantium updates (#5855) * EIP-211 updates * benchmarks * blockhash instruction gas cost updated * More benches * EIP-684 * EIP-649 * EIP-658 * Updated some tests * Modexp fixes * STATICCALL fixes * Pairing fixes * More STATICALL fixes * Use paritytech/bn * Fixed REVERTing of contract creation * Fixed more tests * Fixed more tests * Blockchain tests * Enable previously broken tests * Transition test * Updated tests * Fixed modexp reading huge numbers * Enabled max_code_size test * Review fixes * Updated pairing pricing * missing commas (style) * Update test.rs * Small improvements * eip161abc --- ethcore/benches/evm.rs | 97 ++++++++ ethcore/evm/src/evm.rs | 3 +- ethcore/evm/src/interpreter/mod.rs | 42 +++- ethcore/light/src/on_demand/request.rs | 1 + ethcore/res/ethereum/byzantium_test.json | 60 +++++ ...lis_test.json => constantinople_test.json} | 22 +- ethcore/res/ethereum/foundation.json | 8 +- ethcore/res/ethereum/tests | 2 +- ethcore/res/ethereum/transition_test.json | 157 ++---------- ethcore/src/blockchain/blockchain.rs | 3 + ethcore/src/builtin.rs | 233 ++++++++++-------- ethcore/src/client/client.rs | 2 + ethcore/src/client/evm_test_client.rs | 29 ++- ethcore/src/client/test_client.rs | 1 + ethcore/src/engines/mod.rs | 4 +- ethcore/src/ethereum/ethash.rs | 29 ++- ethcore/src/ethereum/mod.rs | 7 +- ethcore/src/executive.rs | 65 +++-- ethcore/src/externalities.rs | 37 ++- ethcore/src/json_tests/chain.rs | 115 ++++----- ethcore/src/json_tests/executive.rs | 33 ++- ethcore/src/json_tests/homestead_chain.rs | 39 --- ethcore/src/json_tests/mod.rs | 1 - ethcore/src/json_tests/state.rs | 9 +- ethcore/src/json_tests/transaction.rs | 29 +-- ethcore/src/spec/spec.rs | 33 ++- ethcore/src/state/mod.rs | 22 +- ethcore/src/tests/evm.rs | 2 +- ethcore/src/tests/helpers.rs | 23 +- ethcore/src/trace/types/error.rs | 12 + ethcore/types/src/receipt.rs | 28 ++- ethcore/vm/src/error.rs | 6 + ethcore/vm/src/ext.rs | 17 +- ethcore/vm/src/schedule.rs | 9 +- ethcore/vm/src/tests.rs | 6 +- ethcore/wasm/src/runtime.rs | 16 +- evmbin/src/main.rs | 2 +- json/src/blockchain/blockchain.rs | 8 +- json/src/spec/builtin.rs | 12 + json/src/spec/ethash.rs | 18 ++ json/src/spec/params.rs | 3 + json/src/state/test.rs | 6 +- json/src/vm/log.rs | 54 ---- json/src/vm/mod.rs | 2 - json/src/vm/vm.rs | 11 +- rpc/src/v1/tests/eth.rs | 17 +- rpc/src/v1/tests/mod.rs | 35 +-- 47 files changed, 800 insertions(+), 570 deletions(-) create mode 100644 ethcore/benches/evm.rs create mode 100644 ethcore/res/ethereum/byzantium_test.json rename ethcore/res/ethereum/{metropolis_test.json => constantinople_test.json} (63%) delete mode 100644 ethcore/src/json_tests/homestead_chain.rs delete mode 100644 json/src/vm/log.rs diff --git a/ethcore/benches/evm.rs b/ethcore/benches/evm.rs new file mode 100644 index 000000000..384aa60a6 --- /dev/null +++ b/ethcore/benches/evm.rs @@ -0,0 +1,97 @@ +// Copyright 2015-2017 Parity Technologies (UK) Ltd. +// This file is part of Parity. + +// Parity is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity. If not, see . + +#![feature(test)] + +extern crate test; +extern crate ethcore_util as util; +extern crate rand; +extern crate bn; +extern crate crypto; +extern crate rustc_serialize; +extern crate ethkey; + +use self::test::{Bencher}; +use rand::{StdRng}; + + +#[bench] +fn bn_128_pairing(b: &mut Bencher) { + use bn::{pairing, G1, G2, Fr, Group}; + + let rng = &mut ::rand::thread_rng(); + + let sk0 = Fr::random(rng); + let sk1 = Fr::random(rng); + + let pk0 = G1::one() * sk0; + let pk1 = G2::one() * sk1; + + b.iter(|| { + let _ = pairing(pk0, pk1); + }); +} + +#[bench] +fn bn_128_mul(b: &mut Bencher) { + use bn::{AffineG1, G1, Fr, Group}; + + let mut rng = StdRng::new().unwrap(); + let p: G1 = G1::random(&mut rng); + let fr = Fr::random(&mut rng); + + b.iter(|| { + let _ = AffineG1::from_jacobian(p * fr); + }); +} + +#[bench] +fn sha256(b: &mut Bencher) { + use crypto::sha2::Sha256; + use crypto::digest::Digest; + + let mut input: [u8; 256] = [0; 256]; + let mut out = [0; 32]; + + b.iter(|| { + let mut sha = Sha256::new(); + sha.input(&input); + sha.result(&mut input[0..32]); + }); +} + +#[bench] +fn ecrecover(b: &mut Bencher) { + use rustc_serialize::hex::FromHex; + use ethkey::{Signature, recover as ec_recover}; + use util::H256; + let input = FromHex::from_hex("47173285a8d7341e5e972fc677286384f802f8ef42a5ec5f03bbfa254cb01fad000000000000000000000000000000000000000000000000000000000000001b650acf9d3f5f0a2c799776a1254355d5f4061762a237396a99a0e0e3fc2bcd6729514a0dacb2e623ac4abd157cb18163ff942280db4d5caad66ddf941ba12e03").unwrap(); + let hash = H256::from_slice(&input[0..32]); + let v = H256::from_slice(&input[32..64]); + let r = H256::from_slice(&input[64..96]); + let s = H256::from_slice(&input[96..128]); + + let bit = match v[31] { + 27 | 28 if &v.0[..31] == &[0; 31] => v[31] - 27, + _ => { return; }, + }; + + let s = Signature::from_rsv(&r, &s, bit); + b.iter(|| { + let _ = ec_recover(&s, &hash); + }); +} + diff --git a/ethcore/evm/src/evm.rs b/ethcore/evm/src/evm.rs index 9eedb3c51..9a887d040 100644 --- a/ethcore/evm/src/evm.rs +++ b/ethcore/evm/src/evm.rs @@ -17,7 +17,6 @@ //! Evm interface. use std::{ops, cmp, fmt}; - use bigint::prelude::{U128, U256, U512}; use vm::{Ext, Result, ReturnData, GasLeft, Error}; @@ -46,7 +45,7 @@ impl Finalize for Result { fn finalize(self, ext: E) -> Result { match self { Ok(GasLeft::Known(gas_left)) => Ok(FinalizationResult { gas_left: gas_left, apply_state: true, return_data: ReturnData::empty() }), - Ok(GasLeft::NeedsReturn {gas_left, data, apply_state}) => ext.ret(&gas_left, &data).map(|gas_left| FinalizationResult { + Ok(GasLeft::NeedsReturn {gas_left, data, apply_state}) => ext.ret(&gas_left, &data, apply_state).map(|gas_left| FinalizationResult { gas_left: gas_left, apply_state: apply_state, return_data: data, diff --git a/ethcore/evm/src/interpreter/mod.rs b/ethcore/evm/src/interpreter/mod.rs index a59a37db0..11959ee8e 100644 --- a/ethcore/evm/src/interpreter/mod.rs +++ b/ethcore/evm/src/interpreter/mod.rs @@ -328,6 +328,9 @@ impl Interpreter { let contract_code = self.mem.read_slice(init_off, init_size); let can_create = ext.balance(¶ms.address)? >= endowment && ext.depth() < ext.schedule().max_depth; + // clear return data buffer before creating new call frame. + self.return_data = ReturnData::empty(); + if !can_create { stack.push(U256::zero()); return Ok(InstructionResult::UnusedGas(create_gas)); @@ -339,10 +342,18 @@ impl Interpreter { stack.push(address_to_u256(address)); Ok(InstructionResult::UnusedGas(Cost::from_u256(gas_left).expect("Gas left cannot be greater."))) }, + ContractCreateResult::Reverted(gas_left, return_data) => { + stack.push(U256::zero()); + self.return_data = return_data; + Ok(InstructionResult::UnusedGas(Cost::from_u256(gas_left).expect("Gas left cannot be greater."))) + }, ContractCreateResult::Failed => { stack.push(U256::zero()); Ok(InstructionResult::Ok) - } + }, + ContractCreateResult::FailedInStaticCall => { + Err(vm::Error::MutableCallInStaticContext) + }, }; }, instructions::CALL | instructions::CALLCODE | instructions::DELEGATECALL | instructions::STATICCALL => { @@ -353,8 +364,10 @@ impl Interpreter { let code_address = stack.pop_back(); let code_address = u256_to_address(&code_address); - let value = if instruction == instructions::DELEGATECALL || instruction == instructions::STATICCALL { + let value = if instruction == instructions::DELEGATECALL { None + } else if instruction == instructions::STATICCALL { + Some(U256::zero()) } else { Some(stack.pop_back()) }; @@ -373,6 +386,9 @@ impl Interpreter { // Get sender & receive addresses, check if we have balance let (sender_address, receive_address, has_balance, call_type) = match instruction { instructions::CALL => { + if ext.is_static() && value.map_or(false, |v| !v.is_zero()) { + return Err(vm::Error::MutableCallInStaticContext); + } let has_balance = ext.balance(¶ms.address)? >= value.expect("value set for all but delegate call; qed"); (¶ms.address, &code_address, has_balance, CallType::Call) }, @@ -381,10 +397,13 @@ impl Interpreter { (¶ms.address, ¶ms.address, has_balance, CallType::CallCode) }, instructions::DELEGATECALL => (¶ms.sender, ¶ms.address, true, CallType::DelegateCall), - instructions::STATICCALL => (¶ms.sender, ¶ms.address, true, CallType::StaticCall), + instructions::STATICCALL => (¶ms.address, &code_address, true, CallType::StaticCall), _ => panic!(format!("Unexpected instruction {} in CALL branch.", instruction)) }; + // clear return data buffer before creating new call frame. + self.return_data = ReturnData::empty(); + let can_call = has_balance && ext.depth() < ext.schedule().max_depth; if !can_call { stack.push(U256::zero()); @@ -403,12 +422,17 @@ impl Interpreter { MessageCallResult::Success(gas_left, data) => { stack.push(U256::one()); self.return_data = data; - Ok(InstructionResult::UnusedGas(Cost::from_u256(gas_left).expect("Gas left cannot be greater then current one"))) + Ok(InstructionResult::UnusedGas(Cost::from_u256(gas_left).expect("Gas left cannot be greater than current one"))) + }, + MessageCallResult::Reverted(gas_left, data) => { + stack.push(U256::zero()); + self.return_data = data; + Ok(InstructionResult::UnusedGas(Cost::from_u256(gas_left).expect("Gas left cannot be greater than current one"))) }, MessageCallResult::Failed => { stack.push(U256::zero()); Ok(InstructionResult::Ok) - } + }, }; }, instructions::RETURN => { @@ -546,6 +570,14 @@ impl Interpreter { Self::copy_data_to_memory(&mut self.mem, stack, params.data.as_ref().map_or_else(|| &[] as &[u8], |d| &*d as &[u8])); }, instructions::RETURNDATACOPY => { + { + let source_offset = stack.peek(1); + let size = stack.peek(2); + let return_data_len = U256::from(self.return_data.len()); + if source_offset.overflow_add(*size).0 > return_data_len { + return Err(vm::Error::OutOfBounds); + } + } Self::copy_data_to_memory(&mut self.mem, stack, &*self.return_data); }, instructions::CODECOPY => { diff --git a/ethcore/light/src/on_demand/request.rs b/ethcore/light/src/on_demand/request.rs index 162e2bb3a..495d56bd9 100644 --- a/ethcore/light/src/on_demand/request.rs +++ b/ethcore/light/src/on_demand/request.rs @@ -974,6 +974,7 @@ mod tests { fn check_receipts() { let receipts = (0..5).map(|_| Receipt { state_root: Some(H256::random()), + status_code: None, gas_used: 21_000u64.into(), log_bloom: Default::default(), logs: Vec::new(), diff --git a/ethcore/res/ethereum/byzantium_test.json b/ethcore/res/ethereum/byzantium_test.json new file mode 100644 index 000000000..4d239c04e --- /dev/null +++ b/ethcore/res/ethereum/byzantium_test.json @@ -0,0 +1,60 @@ +{ + "name": "Byzantium (Test)", + "engine": { + "Ethash": { + "params": { + "minimumDifficulty": "0x020000", + "difficultyBoundDivisor": "0x0800", + "durationLimit": "0x0d", + "homesteadTransition": "0x0", + "eip150Transition": "0x0", + "eip160Transition": "0x0", + "eip161abcTransition": "0x0", + "eip161dTransition": "0x0", + "maxCodeSize": 24576, + "eip649Reward": "0x29A2241AF62C0000", + "eip100bTransition": "0x0", + "eip649Transition": "0x0" + } + } + }, + "params": { + "gasLimitBoundDivisor": "0x0400", + "blockReward": "0x4563918244F40000", + "registrar" : "0xc6d9d2cd449a754c494264e1809c50e34d64562b", + "accountStartNonce": "0x00", + "maximumExtraDataSize": "0x20", + "minGasLimit": "0x1388", + "networkID" : "0x1", + "eip98Transition": "0xffffffffffffffff", + "eip140Transition": "0x0", + "eip211Transition": "0x0", + "eip214Transition": "0x0", + "eip155Transition": "0x0", + "eip658Transition": "0x0" + }, + "genesis": { + "seal": { + "ethereum": { + "nonce": "0x0000000000000042", + "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000" + } + }, + "difficulty": "0x400000000", + "author": "0x0000000000000000000000000000000000000000", + "timestamp": "0x00", + "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "extraData": "0x11bbe8db4e347b4e8c937c1c8370e4b5ed33adb3db69cbdb7a38e1e50b1b82fa", + "gasLimit": "0x1388" + }, + "accounts": { + "0000000000000000000000000000000000000001": { "balance": "1", "builtin": { "name": "ecrecover", "pricing": { "linear": { "base": 3000, "word": 0 } } } }, + "0000000000000000000000000000000000000002": { "balance": "1", "builtin": { "name": "sha256", "pricing": { "linear": { "base": 60, "word": 12 } } } }, + "0000000000000000000000000000000000000003": { "balance": "1", "builtin": { "name": "ripemd160", "pricing": { "linear": { "base": 600, "word": 120 } } } }, + "0000000000000000000000000000000000000004": { "balance": "1", "builtin": { "name": "identity", "pricing": { "linear": { "base": 15, "word": 3 } } } }, + "0000000000000000000000000000000000000005": { "builtin": { "name": "modexp", "activate_at": "0x00", "pricing": { "modexp": { "divisor": 20 } } } }, + "0000000000000000000000000000000000000006": { "builtin": { "name": "alt_bn128_add", "activate_at": "0x00", "pricing": { "linear": { "base": 500, "word": 0 } } } }, + "0000000000000000000000000000000000000007": { "builtin": { "name": "alt_bn128_mul", "activate_at": "0x00", "pricing": { "linear": { "base": 40000, "word": 0 } } } }, + "0000000000000000000000000000000000000008": { "builtin": { "name": "alt_bn128_pairing", "activate_at": "0x00", "pricing": { "alt_bn128_pairing": { "base": 100000, "pair": 80000 } } } } + } +} diff --git a/ethcore/res/ethereum/metropolis_test.json b/ethcore/res/ethereum/constantinople_test.json similarity index 63% rename from ethcore/res/ethereum/metropolis_test.json rename to ethcore/res/ethereum/constantinople_test.json index a452e5a80..d6df0dddb 100644 --- a/ethcore/res/ethereum/metropolis_test.json +++ b/ethcore/res/ethereum/constantinople_test.json @@ -1,18 +1,20 @@ { - "name": "Metropolis (Test)", + "name": "Byzantium (Test)", "engine": { "Ethash": { "params": { "minimumDifficulty": "0x020000", "difficultyBoundDivisor": "0x0800", "durationLimit": "0x0d", - "homesteadTransition": "0x0", "eip150Transition": "0x0", "eip160Transition": "0x0", "eip161abcTransition": "0x0", "eip161dTransition": "0x0", - "maxCodeSize": 24576 + "maxCodeSize": 24576, + "eip649Reward": "0x29A2241AF62C0000", + "eip100bTransition": "0x0", + "eip649Transition": "0x0" } } }, @@ -24,11 +26,13 @@ "maximumExtraDataSize": "0x20", "minGasLimit": "0x1388", "networkID" : "0x1", - "eip98Transition": "0x0", - "eip86Transition": "0x0", + "eip98Transition": "0xffffffffffffffff", "eip140Transition": "0x0", "eip210Transition": "0x0", - "eip155Transition": "0x0" + "eip211Transition": "0x0", + "eip214Transition": "0x0", + "eip155Transition": "0x0", + "eip658Transition": "0x0" }, "genesis": { "seal": { @@ -48,6 +52,10 @@ "0000000000000000000000000000000000000001": { "balance": "1", "builtin": { "name": "ecrecover", "pricing": { "linear": { "base": 3000, "word": 0 } } } }, "0000000000000000000000000000000000000002": { "balance": "1", "builtin": { "name": "sha256", "pricing": { "linear": { "base": 60, "word": 12 } } } }, "0000000000000000000000000000000000000003": { "balance": "1", "builtin": { "name": "ripemd160", "pricing": { "linear": { "base": 600, "word": 120 } } } }, - "0000000000000000000000000000000000000004": { "balance": "1", "builtin": { "name": "identity", "pricing": { "linear": { "base": 15, "word": 3 } } } } + "0000000000000000000000000000000000000004": { "balance": "1", "builtin": { "name": "identity", "pricing": { "linear": { "base": 15, "word": 3 } } } }, + "0000000000000000000000000000000000000005": { "builtin": { "name": "modexp", "activate_at": "0x00", "pricing": { "modexp": { "divisor": 100 } } } }, + "0000000000000000000000000000000000000006": { "builtin": { "name": "alt_bn128_add", "activate_at": "0x00", "pricing": { "linear": { "base": 500, "word": 0 } } } }, + "0000000000000000000000000000000000000007": { "builtin": { "name": "alt_bn128_mul", "activate_at": "0x00", "pricing": { "linear": { "base": 2000, "word": 0 } } } }, + "0000000000000000000000000000000000000008": { "builtin": { "name": "alt_bn128_pairing", "activate_at": "0x00", "pricing": { "alt_bn128_pairing": { "base": 100000, "pair": 80000 } } } } } } diff --git a/ethcore/res/ethereum/foundation.json b/ethcore/res/ethereum/foundation.json index b30453082..3e87d2e14 100644 --- a/ethcore/res/ethereum/foundation.json +++ b/ethcore/res/ethereum/foundation.json @@ -191,10 +191,10 @@ "0000000000000000000000000000000000000002": { "builtin": { "name": "sha256", "pricing": { "linear": { "base": 60, "word": 12 } } } }, "0000000000000000000000000000000000000003": { "builtin": { "name": "ripemd160", "pricing": { "linear": { "base": 600, "word": 120 } } } }, "0000000000000000000000000000000000000004": { "builtin": { "name": "identity", "pricing": { "linear": { "base": 15, "word": 3 } } } }, - "0000000000000000000000000000000000000005": { "builtin": { "name": "modexp", "activate_at": "0x7fffffffffffff", "pricing": { "modexp": { "divisor": 20 } } } }, - "0000000000000000000000000000000000000006": { "builtin": { "name": "bn128_add", "activate_at": "0x7fffffffffffff", "pricing": { "linear": { "base": 999999, "word": 0 } } } }, - "0000000000000000000000000000000000000007": { "builtin": { "name": "bn128_mul", "activate_at": "0x7fffffffffffff", "pricing": { "linear": { "base": 999999, "word": 0 } } } }, - "0000000000000000000000000000000000000008": { "builtin": { "name": "bn128_pairing", "activate_at": "0x7fffffffffffff", "pricing": { "linear": { "base": 999999, "word": 0 } } } }, + "0000000000000000000000000000000000000005": { "builtin": { "name": "modexp", "activate_at": "0x7fffffffffffff", "pricing": { "modexp": { "divisor": 100 } } } }, + "0000000000000000000000000000000000000006": { "builtin": { "name": "alt_bn128_add", "activate_at": "0x7fffffffffffff", "pricing": { "linear": { "base": 500, "word": 0 } } } }, + "0000000000000000000000000000000000000007": { "builtin": { "name": "alt_bn128_mul", "activate_at": "0x7fffffffffffff", "pricing": { "linear": { "base": 2000, "word": 0 } } } }, + "0000000000000000000000000000000000000008": { "builtin": { "name": "alt_bn128_pairing", "activate_at": "0x7fffffffffffff", "pricing": { "alt_bn128_pairing": { "base": 100000, "pair": 80000 } } } }, "3282791d6fd713f1e94f4bfd565eaa78b3a0599d": { "balance": "1337000000000000000000" }, diff --git a/ethcore/res/ethereum/tests b/ethcore/res/ethereum/tests index ef191fdc6..9b722a014 160000 --- a/ethcore/res/ethereum/tests +++ b/ethcore/res/ethereum/tests @@ -1 +1 @@ -Subproject commit ef191fdc61cf76cdb9cdc147465fb447304b0ed2 +Subproject commit 9b722a014a2b2c9ea6eac456fe01a5c3dd1042a8 diff --git a/ethcore/res/ethereum/transition_test.json b/ethcore/res/ethereum/transition_test.json index 409210a76..064b651e2 100644 --- a/ethcore/res/ethereum/transition_test.json +++ b/ethcore/res/ethereum/transition_test.json @@ -1,136 +1,20 @@ { - "name": "EIP150.1b hard-fork consensus test", + "name": "Transition consensus test spec template", "engine": { "Ethash": { "params": { "minimumDifficulty": "0x020000", "difficultyBoundDivisor": "0x0800", "durationLimit": "0x0d", - "homesteadTransition": "0x5", - "daoHardforkTransition": "0x8", - "daoHardforkBeneficiary": "0xbf4ed7b27f1d666546e30d74d50d173d20bca754", - "daoHardforkAccounts": [ - "0xd4fe7bc31cedb7bfb8a345f31e668033056b2728", - "0xb3fb0e5aba0e20e5c49d252dfd30e102b171a425", - "0x2c19c7f9ae8b751e37aeb2d93a699722395ae18f", - "0xecd135fa4f61a655311e86238c92adcd779555d2", - "0x1975bd06d486162d5dc297798dfc41edd5d160a7", - "0xa3acf3a1e16b1d7c315e23510fdd7847b48234f6", - "0x319f70bab6845585f412ec7724b744fec6095c85", - "0x06706dd3f2c9abf0a21ddcc6941d9b86f0596936", - "0x5c8536898fbb74fc7445814902fd08422eac56d0", - "0x6966ab0d485353095148a2155858910e0965b6f9", - "0x779543a0491a837ca36ce8c635d6154e3c4911a6", - "0x2a5ed960395e2a49b1c758cef4aa15213cfd874c", - "0x5c6e67ccd5849c0d29219c4f95f1a7a93b3f5dc5", - "0x9c50426be05db97f5d64fc54bf89eff947f0a321", - "0x200450f06520bdd6c527622a273333384d870efb", - "0xbe8539bfe837b67d1282b2b1d61c3f723966f049", - "0x6b0c4d41ba9ab8d8cfb5d379c69a612f2ced8ecb", - "0xf1385fb24aad0cd7432824085e42aff90886fef5", - "0xd1ac8b1ef1b69ff51d1d401a476e7e612414f091", - "0x8163e7fb499e90f8544ea62bbf80d21cd26d9efd", - "0x51e0ddd9998364a2eb38588679f0d2c42653e4a6", - "0x627a0a960c079c21c34f7612d5d230e01b4ad4c7", - "0xf0b1aa0eb660754448a7937c022e30aa692fe0c5", - "0x24c4d950dfd4dd1902bbed3508144a54542bba94", - "0x9f27daea7aca0aa0446220b98d028715e3bc803d", - "0xa5dc5acd6a7968a4554d89d65e59b7fd3bff0f90", - "0xd9aef3a1e38a39c16b31d1ace71bca8ef58d315b", - "0x63ed5a272de2f6d968408b4acb9024f4cc208ebf", - "0x6f6704e5a10332af6672e50b3d9754dc460dfa4d", - "0x77ca7b50b6cd7e2f3fa008e24ab793fd56cb15f6", - "0x492ea3bb0f3315521c31f273e565b868fc090f17", - "0x0ff30d6de14a8224aa97b78aea5388d1c51c1f00", - "0x9ea779f907f0b315b364b0cfc39a0fde5b02a416", - "0xceaeb481747ca6c540a000c1f3641f8cef161fa7", - "0xcc34673c6c40e791051898567a1222daf90be287", - "0x579a80d909f346fbfb1189493f521d7f48d52238", - "0xe308bd1ac5fda103967359b2712dd89deffb7973", - "0x4cb31628079fb14e4bc3cd5e30c2f7489b00960c", - "0xac1ecab32727358dba8962a0f3b261731aad9723", - "0x4fd6ace747f06ece9c49699c7cabc62d02211f75", - "0x440c59b325d2997a134c2c7c60a8c61611212bad", - "0x4486a3d68fac6967006d7a517b889fd3f98c102b", - "0x9c15b54878ba618f494b38f0ae7443db6af648ba", - "0x27b137a85656544b1ccb5a0f2e561a5703c6a68f", - "0x21c7fdb9ed8d291d79ffd82eb2c4356ec0d81241", - "0x23b75c2f6791eef49c69684db4c6c1f93bf49a50", - "0x1ca6abd14d30affe533b24d7a21bff4c2d5e1f3b", - "0xb9637156d330c0d605a791f1c31ba5890582fe1c", - "0x6131c42fa982e56929107413a9d526fd99405560", - "0x1591fc0f688c81fbeb17f5426a162a7024d430c2", - "0x542a9515200d14b68e934e9830d91645a980dd7a", - "0xc4bbd073882dd2add2424cf47d35213405b01324", - "0x782495b7b3355efb2833d56ecb34dc22ad7dfcc4", - "0x58b95c9a9d5d26825e70a82b6adb139d3fd829eb", - "0x3ba4d81db016dc2890c81f3acec2454bff5aada5", - "0xb52042c8ca3f8aa246fa79c3feaa3d959347c0ab", - "0xe4ae1efdfc53b73893af49113d8694a057b9c0d1", - "0x3c02a7bc0391e86d91b7d144e61c2c01a25a79c5", - "0x0737a6b837f97f46ebade41b9bc3e1c509c85c53", - "0x97f43a37f595ab5dd318fb46e7a155eae057317a", - "0x52c5317c848ba20c7504cb2c8052abd1fde29d03", - "0x4863226780fe7c0356454236d3b1c8792785748d", - "0x5d2b2e6fcbe3b11d26b525e085ff818dae332479", - "0x5f9f3392e9f62f63b8eac0beb55541fc8627f42c", - "0x057b56736d32b86616a10f619859c6cd6f59092a", - "0x9aa008f65de0b923a2a4f02012ad034a5e2e2192", - "0x304a554a310c7e546dfe434669c62820b7d83490", - "0x914d1b8b43e92723e64fd0a06f5bdb8dd9b10c79", - "0x4deb0033bb26bc534b197e61d19e0733e5679784", - "0x07f5c1e1bc2c93e0402f23341973a0e043f7bf8a", - "0x35a051a0010aba705c9008d7a7eff6fb88f6ea7b", - "0x4fa802324e929786dbda3b8820dc7834e9134a2a", - "0x9da397b9e80755301a3b32173283a91c0ef6c87e", - "0x8d9edb3054ce5c5774a420ac37ebae0ac02343c6", - "0x0101f3be8ebb4bbd39a2e3b9a3639d4259832fd9", - "0x5dc28b15dffed94048d73806ce4b7a4612a1d48f", - "0xbcf899e6c7d9d5a215ab1e3444c86806fa854c76", - "0x12e626b0eebfe86a56d633b9864e389b45dcb260", - "0xa2f1ccba9395d7fcb155bba8bc92db9bafaeade7", - "0xec8e57756626fdc07c63ad2eafbd28d08e7b0ca5", - "0xd164b088bd9108b60d0ca3751da4bceb207b0782", - "0x6231b6d0d5e77fe001c2a460bd9584fee60d409b", - "0x1cba23d343a983e9b5cfd19496b9a9701ada385f", - "0xa82f360a8d3455c5c41366975bde739c37bfeb8a", - "0x9fcd2deaff372a39cc679d5c5e4de7bafb0b1339", - "0x005f5cee7a43331d5a3d3eec71305925a62f34b6", - "0x0e0da70933f4c7849fc0d203f5d1d43b9ae4532d", - "0xd131637d5275fd1a68a3200f4ad25c71a2a9522e", - "0xbc07118b9ac290e4622f5e77a0853539789effbe", - "0x47e7aa56d6bdf3f36be34619660de61275420af8", - "0xacd87e28b0c9d1254e868b81cba4cc20d9a32225", - "0xadf80daec7ba8dcf15392f1ac611fff65d94f880", - "0x5524c55fb03cf21f549444ccbecb664d0acad706", - "0x40b803a9abce16f50f36a77ba41180eb90023925", - "0xfe24cdd8648121a43a7c86d289be4dd2951ed49f", - "0x17802f43a0137c506ba92291391a8a8f207f487d", - "0x253488078a4edf4d6f42f113d1e62836a942cf1a", - "0x86af3e9626fce1957c82e88cbf04ddf3a2ed7915", - "0xb136707642a4ea12fb4bae820f03d2562ebff487", - "0xdbe9b615a3ae8709af8b93336ce9b477e4ac0940", - "0xf14c14075d6c4ed84b86798af0956deef67365b5", - "0xca544e5c4687d109611d0f8f928b53a25af72448", - "0xaeeb8ff27288bdabc0fa5ebb731b6f409507516c", - "0xcbb9d3703e651b0d496cdefb8b92c25aeb2171f7", - "0x6d87578288b6cb5549d5076a207456a1f6a63dc0", - "0xb2c6f0dfbb716ac562e2d85d6cb2f8d5ee87603e", - "0xaccc230e8a6e5be9160b8cdf2864dd2a001c28b6", - "0x2b3455ec7fedf16e646268bf88846bd7a2319bb2", - "0x4613f3bca5c44ea06337a9e439fbc6d42e501d0a", - "0xd343b217de44030afaa275f54d31a9317c7f441e", - "0x84ef4b2357079cd7a7c69fd7a37cd0609a679106", - "0xda2fef9e4a3230988ff17df2165440f37e8b1708", - "0xf4c64518ea10f995918a454158c6b61407ea345c", - "0x7602b46df5390e432ef1c307d4f2c9ff6d65cc97", - "0xbb9bc244d798123fde783fcc1c72d3bb8c189413", - "0x807640a13483f8ac783c557fcdf27be11ea4ac7a" - ], - "eip150Transition": "0xa", - "eip160Transition": "0x7fffffffffffffff", - "eip161abcTransition": "0x7fffffffffffffff", - "eip161dTransition": "0x7fffffffffffffff" + "homesteadTransition": "0", + "eip150Transition": "0", + "eip160Transition": "0", + "eip161abcTransition": "0", + "eip161dTransition": "0", + "maxCodeSize": 24576, + "eip649Reward": "0x29A2241AF62C0000", + "eip100bTransition": "5", + "eip649Transition": "5" } } }, @@ -142,9 +26,12 @@ "maximumExtraDataSize": "0x20", "minGasLimit": "0x1388", "networkID" : "0x1", - "eip98Transition": "0x7fffffffffffff", - "eip86Transition": "0x7fffffffffffff", - "eip155Transition": "0x7fffffffffffffff" + "eip98Transition": "5", + "eip140Transition": "5", + "eip211Transition": "5", + "eip214Transition": "5", + "eip155Transition": "5", + "eip658Transition": "5" }, "genesis": { "seal": { @@ -161,9 +48,13 @@ "gasLimit": "0x1388" }, "accounts": { - "0000000000000000000000000000000000000001": { "builtin": { "name": "ecrecover", "pricing": { "linear": { "base": 3000, "word": 0 } } } }, - "0000000000000000000000000000000000000002": { "builtin": { "name": "sha256", "pricing": { "linear": { "base": 60, "word": 12 } } } }, - "0000000000000000000000000000000000000003": { "builtin": { "name": "ripemd160", "pricing": { "linear": { "base": 600, "word": 120 } } } }, - "0000000000000000000000000000000000000004": { "builtin": { "name": "identity", "pricing": { "linear": { "base": 15, "word": 3 } } } } + "0000000000000000000000000000000000000001": { "balance": "1", "builtin": { "name": "ecrecover", "pricing": { "linear": { "base": 3000, "word": 0 } } } }, + "0000000000000000000000000000000000000002": { "balance": "1", "builtin": { "name": "sha256", "pricing": { "linear": { "base": 60, "word": 12 } } } }, + "0000000000000000000000000000000000000003": { "balance": "1", "builtin": { "name": "ripemd160", "pricing": { "linear": { "base": 600, "word": 120 } } } }, + "0000000000000000000000000000000000000004": { "balance": "1", "builtin": { "name": "identity", "pricing": { "linear": { "base": 15, "word": 3 } } } }, + "0000000000000000000000000000000000000005": { "builtin": { "name": "modexp", "activate_at": "5", "pricing": { "modexp": { "divisor": 100 } } } }, + "0000000000000000000000000000000000000006": { "builtin": { "name": "alt_bn128_add", "activate_at": "5", "pricing": { "linear": { "base": 500, "word": 0 } } } }, + "0000000000000000000000000000000000000007": { "builtin": { "name": "alt_bn128_mul", "activate_at": "5", "pricing": { "linear": { "base": 2000, "word": 0 } } } }, + "0000000000000000000000000000000000000008": { "builtin": { "name": "alt_bn128_pairing", "activate_at": "5", "pricing": { "alt_bn128_pairing": { "base": 100000, "pair": 80000 } } } } } } diff --git a/ethcore/src/blockchain/blockchain.rs b/ethcore/src/blockchain/blockchain.rs index 88bed91a3..7eb7a9f2d 100644 --- a/ethcore/src/blockchain/blockchain.rs +++ b/ethcore/src/blockchain/blockchain.rs @@ -2049,6 +2049,7 @@ mod tests { let bc = new_chain(&genesis, db.clone()); insert_block(&db, &bc, &b1, vec![Receipt { state_root: Some(H256::default()), + status_code: None, gas_used: 10_000.into(), log_bloom: Default::default(), logs: vec![ @@ -2058,6 +2059,7 @@ mod tests { }, Receipt { state_root: Some(H256::default()), + status_code: None, gas_used: 10_000.into(), log_bloom: Default::default(), logs: vec![ @@ -2067,6 +2069,7 @@ mod tests { insert_block(&db, &bc, &b2, vec![ Receipt { state_root: Some(H256::default()), + status_code: None, gas_used: 10_000.into(), log_bloom: Default::default(), logs: vec![ diff --git a/ethcore/src/builtin.rs b/ethcore/src/builtin.rs index 191e04dc6..9d3290a7c 100644 --- a/ethcore/src/builtin.rs +++ b/ethcore/src/builtin.rs @@ -64,7 +64,7 @@ struct Linear { } /// A special pricing model for modular exponentiation. -struct Modexp { +struct ModexpPricer { divisor: usize, } @@ -74,7 +74,20 @@ impl Pricer for Linear { } } -impl Pricer for Modexp { +/// A alt_bn128_parinig pricing model. This computes a price using a base cost and a cost per pair. +struct AltBn128PairingPricer { + base: usize, + pair: usize, +} + +impl Pricer for AltBn128PairingPricer { + fn cost(&self, input: &[u8]) -> U256 { + let cost = U256::from(self.base) + U256::from(self.pair) * U256::from(input.len() / 192); + cost + } +} + +impl Pricer for ModexpPricer { fn cost(&self, input: &[u8]) -> U256 { let mut reader = input.chain(io::repeat(0)); let mut buf = [0; 32]; @@ -88,17 +101,49 @@ impl Pricer for Modexp { let exp_len = read_len(); let mod_len = read_len(); - // floor(max(length_of_MODULUS, length_of_BASE) ** 2 * max(length_of_EXPONENT, 1) / GQUADDIVISOR) - // TODO: is saturating the best behavior here? + let max_len = U256::from(u32::max_value() / 2); + if base_len > max_len || mod_len > max_len { + return U256::max_value(); + } + + let base_len = base_len.low_u64(); + let exp_len = exp_len.low_u64(); + let mod_len = mod_len.low_u64(); let m = max(mod_len, base_len); - match m.overflowing_mul(m) { - (_, true) => U256::max_value(), - (val, _) => { - match val.overflowing_mul(max(exp_len, U256::one())) { - (_, true) => U256::max_value(), - (val, _) => val / (self.divisor as u64).into() - } - } + if m == 0 { + return U256::zero(); + } + // read fist 32-byte word of the exponent. + let exp_low = if base_len + 96 >= input.len() as u64 { U256::zero() } else { + let mut buf = [0; 32]; + let mut reader = input[(96 + base_len as usize)..].chain(io::repeat(0)); + let len = min(exp_len, 32) as usize; + reader.read_exact(&mut buf[(32 - len)..]).expect("reading from zero-extended memory cannot fail; qed"); + U256::from(H256::from_slice(&buf[..])) + }; + + let adjusted_exp_len = Self::adjusted_exp_len(exp_len, exp_low); + + (Self::mult_complexity(m) * max(adjusted_exp_len, 1) / self.divisor as u64).into() + } +} + +impl ModexpPricer { + fn adjusted_exp_len(len: u64, exp_low: U256) -> u64 { + let bit_index = if exp_low.is_zero() { 0 } else { (255 - exp_low.leading_zeros()) as u64 }; + if len <= 32 { + bit_index + } + else { + 8 * (len - 32) + bit_index + } + } + + fn mult_complexity(x: u64) -> u64 { + match x { + x if x <= 64 => x * x, + x if x <= 1024 => (x * x) / 4 + 96 * x - 3072, + x => (x * x) / 16 + 480 * x - 199680, } } } @@ -138,7 +183,7 @@ impl From for Builtin { }) } ethjson::spec::Pricing::Modexp(exp) => { - Box::new(Modexp { + Box::new(ModexpPricer { divisor: if exp.divisor == 0 { warn!("Zero modexp divisor specified. Falling back to default."); 10 @@ -147,6 +192,12 @@ impl From for Builtin { } }) } + ethjson::spec::Pricing::AltBn128Pairing(pricer) => { + Box::new(AltBn128PairingPricer { + base: pricer.base, + pair: pricer.pair, + }) + } }; Builtin { @@ -165,9 +216,9 @@ fn ethereum_builtin(name: &str) -> Box { "sha256" => Box::new(Sha256) as Box, "ripemd160" => Box::new(Ripemd160) as Box, "modexp" => Box::new(ModexpImpl) as Box, - "bn128_add" => Box::new(Bn128AddImpl) as Box, - "bn128_mul" => Box::new(Bn128MulImpl) as Box, - "bn128_pairing" => Box::new(Bn128PairingImpl) as Box, + "alt_bn128_add" => Box::new(Bn128AddImpl) as Box, + "alt_bn128_mul" => Box::new(Bn128MulImpl) as Box, + "alt_bn128_pairing" => Box::new(Bn128PairingImpl) as Box, _ => panic!("invalid builtin name: {}", name), } } @@ -273,11 +324,16 @@ impl Impl for Ripemd160 { fn modexp(mut base: BigUint, mut exp: BigUint, modulus: BigUint) -> BigUint { use num::Integer; - match (base.is_zero(), exp.is_zero()) { - (_, true) => return BigUint::one(), // n^0 % m - (true, false) => return BigUint::zero(), // 0^n % m, n>0 - (false, false) if modulus <= BigUint::one() => return BigUint::zero(), // a^b % 1 = 0. - _ => {} + if modulus <= BigUint::one() { // n^m % 0 || n^m % 1 + return BigUint::zero(); + } + + if exp.is_zero() { // n^0 % m + return BigUint::one(); + } + + if base.is_zero() { // 0^n % m, n>0 + return BigUint::zero(); } let mut result = BigUint::one(); @@ -293,7 +349,6 @@ fn modexp(mut base: BigUint, mut exp: BigUint, modulus: BigUint) -> BigUint { exp = exp >> 1; base = (base.clone() * base) % &modulus; } - result } @@ -314,19 +369,25 @@ impl Impl for ModexpImpl { let exp_len = read_len(&mut reader); let mod_len = read_len(&mut reader); - // read the numbers themselves. - let mut buf = vec![0; max(mod_len, max(base_len, exp_len))]; - let mut read_num = |len| { - reader.read_exact(&mut buf[..len]).expect("reading from zero-extended memory cannot fail; qed"); - BigUint::from_bytes_be(&buf[..len]) + // Gas formula allows arbitrary large exp_len when base and modulus are empty, so we need to handle empty base first. + let r = if base_len == 0 && mod_len == 0 { + BigUint::zero() + } else { + // read the numbers themselves. + let mut buf = vec![0; max(mod_len, max(base_len, exp_len))]; + let mut read_num = |len| { + reader.read_exact(&mut buf[..len]).expect("reading from zero-extended memory cannot fail; qed"); + BigUint::from_bytes_be(&buf[..len]) + }; + + let base = read_num(base_len); + let exp = read_num(exp_len); + let modulus = read_num(mod_len); + modexp(base, exp, modulus) }; - let base = read_num(base_len); - let exp = read_num(exp_len); - let modulus = read_num(mod_len); - // write output to given memory, left padded and same length as the modulus. - let bytes = modexp(base, exp, modulus).to_bytes_be(); + let bytes = r.to_bytes_be(); // always true except in the case of zero-length modulus, which leads to // output of length and value 1. @@ -356,7 +417,6 @@ fn read_point(reader: &mut io::Chain<&[u8], io::Repeat>) -> Result<::bn::G1, Err reader.read_exact(&mut buf[..]).expect("reading from zero-extended memory cannot fail; qed"); let py = Fq::from_slice(&buf[0..32]).map_err(|_| Error::from("Invalid point y coordinate"))?; - Ok( if px == Fq::zero() && py == Fq::zero() { G1::zero() @@ -407,50 +467,29 @@ impl Impl for Bn128MulImpl { } } -mod bn128_gen { - use bn::{AffineG1, AffineG2, Fq, Fq2, G1, G2, Gt, pairing}; - - lazy_static! { - pub static ref P1: G1 = G1::from(AffineG1::new( - Fq::from_str("1").expect("1 is a valid field element"), - Fq::from_str("2").expect("2 is a valid field element"), - ).expect("Generator P1(1, 2) is a valid curve point")); - } - - lazy_static! { - pub static ref P2: G2 = G2::from(AffineG2::new( - Fq2::new( - Fq::from_str("10857046999023057135944570762232829481370756359578518086990519993285655852781") - .expect("a valid field element"), - Fq::from_str("11559732032986387107991004021392285783925812861821192530917403151452391805634") - .expect("a valid field element"), - ), - Fq2::new( - Fq::from_str("8495653923123431417604973247489272438418190587263600148770280649306958101930") - .expect("a valid field element"), - Fq::from_str("4082367875863433681332203403145435568316851327593401208105741076214120093531") - .expect("a valid field element"), - ), - ).expect("the generator P2(10857046999023057135944570762232829481370756359578518086990519993285655852781 + 11559732032986387107991004021392285783925812861821192530917403151452391805634i, 8495653923123431417604973247489272438418190587263600148770280649306958101930 + 4082367875863433681332203403145435568316851327593401208105741076214120093531i) is a valid curve point")); - } - - lazy_static! { - pub static ref P1_P2_PAIRING: Gt = pairing(P1.clone(), P2.clone()); - } -} - impl Impl for Bn128PairingImpl { /// Can fail if: /// - input length is not a multiple of 192 /// - any of odd points does not belong to bn128 curve /// - any of even points does not belong to the twisted bn128 curve over the field F_p^2 = F_p[i] / (i^2 + 1) fn execute(&self, input: &[u8], output: &mut BytesRef) -> Result<(), Error> { - use bn::{AffineG1, AffineG2, Fq, Fq2, pairing, G1, G2, Gt}; - - let elements = input.len() / 192; // (a, b_a, b_b - each 64-byte affine coordinates) if input.len() % 192 != 0 { return Err("Invalid input length, must be multiple of 192 (3 * (32*2))".into()) } + + if let Err(err) = self.execute_with_error(input, output) { + trace!("Pairining error: {:?}", err); + return Err(err) + } + Ok(()) + } +} + +impl Bn128PairingImpl { + fn execute_with_error(&self, input: &[u8], output: &mut BytesRef) -> Result<(), Error> { + use bn::{AffineG1, AffineG2, Fq, Fq2, pairing, G1, G2, Gt, Group}; + + let elements = input.len() / 192; // (a, b_a, b_b - each 64-byte affine coordinates) let ret_val = if input.len() == 0 { U256::one() } else { @@ -462,34 +501,36 @@ impl Impl for Bn128PairingImpl { let a_y = Fq::from_slice(&input[idx*192+32..idx*192+64]) .map_err(|_| Error::from("Invalid a argument y coordinate"))?; - let b_b_x = Fq::from_slice(&input[idx*192+64..idx*192+96]) + let b_a_y = Fq::from_slice(&input[idx*192+64..idx*192+96]) .map_err(|_| Error::from("Invalid b argument imaginary coeff x coordinate"))?; - let b_b_y = Fq::from_slice(&input[idx*192+96..idx*192+128]) + let b_a_x = Fq::from_slice(&input[idx*192+96..idx*192+128]) .map_err(|_| Error::from("Invalid b argument imaginary coeff y coordinate"))?; - let b_a_x = Fq::from_slice(&input[idx*192+128..idx*192+160]) + let b_b_y = Fq::from_slice(&input[idx*192+128..idx*192+160]) .map_err(|_| Error::from("Invalid b argument real coeff x coordinate"))?; - let b_a_y = Fq::from_slice(&input[idx*192+160..idx*192+192]) + let b_b_x = Fq::from_slice(&input[idx*192+160..idx*192+192]) .map_err(|_| Error::from("Invalid b argument real coeff y coordinate"))?; - vals.push(( - G1::from( - AffineG1::new(a_x, a_y).map_err(|_| Error::from("Invalid a argument - not on curve"))? - ), - G2::from( - AffineG2::new( - Fq2::new(b_a_x, b_a_y), - Fq2::new(b_b_x, b_b_y), - ).map_err(|_| Error::from("Invalid b argument - not on curve"))? - ), - )); + let b_a = Fq2::new(b_a_x, b_a_y); + let b_b = Fq2::new(b_b_x, b_b_y); + let b = if b_a.is_zero() && b_b.is_zero() { + G2::zero() + } else { + G2::from(AffineG2::new(b_a, b_b).map_err(|_| Error::from("Invalid b argument - not on curve"))?) + }; + let a = if a_x.is_zero() && a_y.is_zero() { + G1::zero() + } else { + G1::from(AffineG1::new(a_x, a_y).map_err(|_| Error::from("Invalid a argument - not on curve"))?) + }; + vals.push((a, b)); }; let mul = vals.into_iter().fold(Gt::one(), |s, (a, b)| s * pairing(a, b)); - if mul == *bn128_gen::P1_P2_PAIRING { + if mul == Gt::one() { U256::one() } else { U256::zero() @@ -506,7 +547,7 @@ impl Impl for Bn128PairingImpl { #[cfg(test)] mod tests { - use super::{Builtin, Linear, ethereum_builtin, Pricer, Modexp, modexp as me}; + use super::{Builtin, Linear, ethereum_builtin, Pricer, ModexpPricer, modexp as me}; use ethjson; use bigint::prelude::U256; use bytes::BytesRef; @@ -662,7 +703,7 @@ mod tests { fn modexp() { let f = Builtin { - pricer: Box::new(Modexp { divisor: 20 }), + pricer: Box::new(ModexpPricer { divisor: 20 }), native: ethereum_builtin("modexp"), activate_at: 0, }; @@ -679,7 +720,7 @@ mod tests { let mut output = vec![0u8; 32]; let expected = FromHex::from_hex("0000000000000000000000000000000000000000000000000000000000000001").unwrap(); - let expected_cost = 1638; + let expected_cost = 13056; f.execute(&input[..], &mut BytesRef::Fixed(&mut output[..])).expect("Builtin should not fail"); assert_eq!(output, expected); @@ -690,15 +731,15 @@ mod tests { { let input = FromHex::from_hex("\ 0000000000000000000000000000000000000000000000000000000000000000\ - 0000000000000000000000000000000000000000000000000000000000000020\ - 0000000000000000000000000000000000000000000000000000000000000020\ - fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2e\ - fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f" + 0000000000000000000000000000000000000000000000000000000000000020\ + 0000000000000000000000000000000000000000000000000000000000000020\ + fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2e\ + fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f" ).unwrap(); let mut output = vec![0u8; 32]; let expected = FromHex::from_hex("0000000000000000000000000000000000000000000000000000000000000000").unwrap(); - let expected_cost = 1638; + let expected_cost = 13056; f.execute(&input[..], &mut BytesRef::Fixed(&mut output[..])).expect("Builtin should not fail"); assert_eq!(output, expected); @@ -718,7 +759,7 @@ mod tests { let mut output = vec![0u8; 32]; let expected = FromHex::from_hex("3b01b01ac41f2d6e917c6d6a221ce793802469026d9ab7578fa2e79e4da6aaab").unwrap(); - let expected_cost = 102; + let expected_cost = 768; f.execute(&input[..], &mut BytesRef::Fixed(&mut output[..])).expect("Builtin should not fail"); assert_eq!(output, expected); @@ -749,7 +790,7 @@ mod tests { let f = Builtin { pricer: Box::new(Linear { base: 0, word: 0 }), - native: ethereum_builtin("bn128_add"), + native: ethereum_builtin("alt_bn128_add"), activate_at: 0, }; @@ -810,7 +851,7 @@ mod tests { let f = Builtin { pricer: Box::new(Linear { base: 0, word: 0 }), - native: ethereum_builtin("bn128_mul"), + native: ethereum_builtin("alt_bn128_mul"), activate_at: 0, }; @@ -850,7 +891,7 @@ mod tests { fn builtin_pairing() -> Builtin { Builtin { pricer: Box::new(Linear { base: 0, word: 0 }), - native: ethereum_builtin("bn128_pairing"), + native: ethereum_builtin("alt_bn128_pairing"), activate_at: 0, } } diff --git a/ethcore/src/client/client.rs b/ethcore/src/client/client.rs index 9fe9a4573..8659ade6f 100644 --- a/ethcore/src/client/client.rs +++ b/ethcore/src/client/client.rs @@ -2140,11 +2140,13 @@ mod tests { }]; let receipts = vec![Receipt { state_root: state_root, + status_code: None, gas_used: 5.into(), log_bloom: Default::default(), logs: vec![logs[0].clone()], }, Receipt { state_root: state_root, + status_code: None, gas_used: gas_used, log_bloom: Default::default(), logs: logs.clone(), diff --git a/ethcore/src/client/evm_test_client.rs b/ethcore/src/client/evm_test_client.rs index 2c465a24b..db1a11f79 100644 --- a/ethcore/src/client/evm_test_client.rs +++ b/ethcore/src/client/evm_test_client.rs @@ -26,7 +26,7 @@ use bytes; use util::kvdb::{self, KeyValueDB}; use {state, state_db, client, executive, trace, transaction, db, spec, pod_state}; use factory::Factories; -use evm::{self, VMType}; +use evm::{self, VMType, FinalizationResult}; use vm::{self, ActionParams}; /// EVM test Error. @@ -72,7 +72,8 @@ lazy_static! { pub static ref HOMESTEAD: spec::Spec = ethereum::new_homestead_test(); pub static ref EIP150: spec::Spec = ethereum::new_eip150_test(); pub static ref EIP161: spec::Spec = ethereum::new_eip161_test(); - pub static ref _METROPOLIS: spec::Spec = ethereum::new_metropolis_test(); + pub static ref BYZANTIUM: spec::Spec = ethereum::new_byzantium_test(); + pub static ref BYZANTIUM_TRANSITION: spec::Spec = ethereum::new_transition_test(); } /// Simplified, single-block EVM test client. @@ -89,7 +90,10 @@ impl<'a> EvmTestClient<'a> { ForkSpec::Homestead => Some(&*HOMESTEAD), ForkSpec::EIP150 => Some(&*EIP150), ForkSpec::EIP158 => Some(&*EIP161), - ForkSpec::Metropolis | ForkSpec::Byzantium | ForkSpec::Constantinople => None, + ForkSpec::Byzantium => Some(&*BYZANTIUM), + ForkSpec::EIP158ToByzantiumAt5 => Some(&BYZANTIUM_TRANSITION), + ForkSpec::FrontierToHomesteadAt5 | ForkSpec::HomesteadToDaoAt5 | ForkSpec::HomesteadToEIP150At5 => None, + _ => None, } } @@ -162,7 +166,7 @@ impl<'a> EvmTestClient<'a> { /// Execute the VM given ActionParams and tracer. /// Returns amount of gas left and the output. pub fn call(&mut self, params: ActionParams, vm_tracer: &mut T) - -> Result<(U256, Vec), EvmTestError> + -> Result { let genesis = self.spec.genesis_header(); let info = client::EnvInfo { @@ -178,15 +182,13 @@ impl<'a> EvmTestClient<'a> { let mut tracer = trace::NoopTracer; let mut output = vec![]; let mut executive = executive::Executive::new(&mut self.state, &info, &*self.spec.engine); - let (gas_left, _) = executive.call( + executive.call( params, &mut substate, bytes::BytesRef::Flexible(&mut output), &mut tracer, vm_tracer, - ).map_err(EvmTestError::Evm)?; - - Ok((gas_left, output)) + ).map_err(EvmTestError::Evm) } /// Executes a SignedTransaction within context of the provided state and `EnvInfo`. @@ -212,10 +214,13 @@ impl<'a> EvmTestClient<'a> { let result = self.state.apply_with_tracing(&env_info, &*self.spec.engine, &transaction, tracer, vm_tracer); match result { - Ok(result) => TransactResult::Ok { - state_root: *self.state.root(), - gas_left: initial_gas - result.receipt.gas_used, - output: result.output + Ok(result) => { + self.state.commit().ok(); + TransactResult::Ok { + state_root: *self.state.root(), + gas_left: initial_gas - result.receipt.gas_used, + output: result.output + } }, Err(error) => TransactResult::Err { state_root: *self.state.root(), diff --git a/ethcore/src/client/test_client.rs b/ethcore/src/client/test_client.rs index eb3706e01..5052b67d6 100644 --- a/ethcore/src/client/test_client.rs +++ b/ethcore/src/client/test_client.rs @@ -619,6 +619,7 @@ impl BlockChainClient for TestBlockChainClient { if *hash > H256::from("f000000000000000000000000000000000000000000000000000000000000000") { let receipt = BlockReceipts::new(vec![Receipt::new( Some(H256::zero()), + None, U256::zero(), vec![])]); let mut rlp = RlpStream::new(); diff --git a/ethcore/src/engines/mod.rs b/ethcore/src/engines/mod.rs index b48ff2f3f..50f787c2b 100644 --- a/ethcore/src/engines/mod.rs +++ b/ethcore/src/engines/mod.rs @@ -62,8 +62,8 @@ use unexpected::{Mismatch, OutOfBounds}; use bytes::Bytes; /// Default EIP-210 contrat code. -/// As defined in https://github.com/ethereum/EIPs/pull/210/commits/9df24a3714af42e3bf350265bdc75b486c909d7f#diff-e02a92c2fb96c1a1bfb05e4c6e2ef5daR49 -pub const DEFAULT_BLOCKHASH_CONTRACT: &'static str = "73fffffffffffffffffffffffffffffffffffffffe33141561007a57600143036020526000356101006020510755600061010060205107141561005057600035610100610100602051050761010001555b6000620100006020510714156100755760003561010062010000602051050761020001555b610161565b436000351215801561008c5780610095565b623567e0600035125b9050156100a757600060605260206060f35b610100600035430312156100ca57610100600035075460805260206080f3610160565b62010000600035430312156100e857600061010060003507146100eb565b60005b1561010d576101006101006000350507610100015460a052602060a0f361015f565b63010000006000354303121561012d576000620100006000350714610130565b60005b1561015357610100620100006000350507610200015460c052602060c0f361015e565b600060e052602060e0f35b5b5b5b5b"; +/// As defined in https://github.com/ethereum/EIPs/pull/210 +pub const DEFAULT_BLOCKHASH_CONTRACT: &'static str = "73fffffffffffffffffffffffffffffffffffffffe33141561006a5760014303600035610100820755610100810715156100455760003561010061010083050761010001555b6201000081071515610064576000356101006201000083050761020001555b5061013e565b4360003512151561008457600060405260206040f361013d565b61010060003543031315156100a857610100600035075460605260206060f361013c565b6101006000350715156100c55762010000600035430313156100c8565b60005b156100ea576101006101006000350507610100015460805260206080f361013b565b620100006000350715156101095763010000006000354303131561010c565b60005b1561012f57610100620100006000350507610200015460a052602060a0f361013a565b600060c052602060c0f35b5b5b5b5b"; /// Voting errors. #[derive(Debug)] diff --git a/ethcore/src/ethereum/ethash.rs b/ethcore/src/ethereum/ethash.rs index 11c04b628..91e326b64 100644 --- a/ethcore/src/ethereum/ethash.rs +++ b/ethcore/src/ethereum/ethash.rs @@ -51,6 +51,7 @@ const SNAPSHOT_BLOCKS: u64 = 5000; /// Maximum number of blocks allowed in an ethash snapshot. const MAX_SNAPSHOT_BLOCKS: u64 = 30000; +const DEFAULT_EIP649_DELAY: u64 = 3_000_000; /// Ethash params. #[derive(Debug, PartialEq)] @@ -105,6 +106,12 @@ pub struct EthashParams { pub min_gas_price_transition: u64, /// Do not alow transactions with lower gas price. pub min_gas_price: U256, + /// EIP-649 transition block. + pub eip649_transition: u64, + /// EIP-649 bomb delay. + pub eip649_delay: u64, + /// EIP-649 base reward. + pub eip649_reward: Option, } impl From for EthashParams { @@ -135,6 +142,9 @@ impl From for EthashParams { max_gas_limit: p.max_gas_limit.map_or(U256::max_value(), Into::into), min_gas_price_transition: p.min_gas_price_transition.map_or(u64::max_value(), Into::into), min_gas_price: p.min_gas_price.map_or(U256::zero(), Into::into), + eip649_transition: p.eip649_transition.map_or(u64::max_value(), Into::into), + eip649_delay: p.eip649_delay.map_or(DEFAULT_EIP649_DELAY, Into::into), + eip649_reward: p.eip649_reward.map(Into::into), } } } @@ -215,8 +225,10 @@ impl Engine for Arc { } else if block_number < self.ethash_params.eip150_transition { Schedule::new_homestead() } else { + /// There's no max_code_size transition so we tie it to eip161abc + let max_code_size = if block_number >= self.ethash_params.eip161abc_transition { self.ethash_params.max_code_size as usize } else { usize::max_value() }; let mut schedule = Schedule::new_post_eip150( - self.ethash_params.max_code_size as usize, + max_code_size, block_number >= self.ethash_params.eip160_transition, block_number >= self.ethash_params.eip161abc_transition, block_number >= self.ethash_params.eip161d_transition); @@ -296,9 +308,14 @@ impl Engine for Arc { /// This assumes that all uncles are valid uncles (i.e. of at least one generation before the current). fn on_close_block(&self, block: &mut ExecutedBlock) -> Result<(), Error> { use std::ops::Shr; - let reward = self.params().block_reward; let tracing_enabled = block.tracing_enabled(); let fields = block.fields_mut(); + let reward = if fields.header.number() >= self.ethash_params.eip649_transition { + self.ethash_params.eip649_reward.unwrap_or(self.params().block_reward) + } else { + self.params().block_reward + }; + let eras_rounds = self.ethash_params.ecip1017_era_rounds; let (eras, reward) = ecip1017_eras_block_reward(eras_rounds, reward, fields.header.number()); let mut tracer = ExecutiveTracer::default(); @@ -500,7 +517,7 @@ fn ecip1017_eras_block_reward(era_rounds: u64, mut reward: U256, block_number:u6 #[cfg_attr(feature="dev", allow(wrong_self_convention))] impl Ethash { fn calculate_difficulty(&self, header: &Header, parent: &Header) -> U256 { - const EXP_DIFF_PERIOD: u64 = 100000; + const EXP_DIFF_PERIOD: u64 = 100_000; if header.number() == 0 { panic!("Can't calculate genesis block difficulty"); } @@ -550,7 +567,11 @@ impl Ethash { target = cmp::max(min_difficulty, target); if header.number() < self.ethash_params.bomb_defuse_transition { if header.number() < self.ethash_params.ecip1010_pause_transition { - let period = ((parent.number() + 1) / EXP_DIFF_PERIOD) as usize; + let mut number = header.number(); + if number >= self.ethash_params.eip649_transition { + number = number.saturating_sub(self.ethash_params.eip649_delay); + } + let period = (number / EXP_DIFF_PERIOD) as usize; if period > 1 { target = cmp::max(min_difficulty, target + (U256::from(1) << (period - 2))); } diff --git a/ethcore/src/ethereum/mod.rs b/ethcore/src/ethereum/mod.rs index 8cc9446a6..2135ea267 100644 --- a/ethcore/src/ethereum/mod.rs +++ b/ethcore/src/ethereum/mod.rs @@ -87,8 +87,11 @@ pub fn new_transition_test() -> Spec { load(None, include_bytes!("../../res/ethe /// Create a new Foundation Mainnet chain spec without genesis accounts. pub fn new_mainnet_like() -> Spec { load(None, include_bytes!("../../res/ethereum/frontier_like_test.json")) } -/// Create a new Foundation Metropolis era spec. -pub fn new_metropolis_test() -> Spec { load(None, include_bytes!("../../res/ethereum/metropolis_test.json")) } +/// Create a new Foundation Byzantium era spec. +pub fn new_byzantium_test() -> Spec { load(None, include_bytes!("../../res/ethereum/byzantium_test.json")) } + +/// Create a new Foundation Constantinople era spec. +pub fn new_constantinople_test() -> Spec { load(None, include_bytes!("../../res/ethereum/constantinople_test.json")) } #[cfg(test)] mod tests { diff --git a/ethcore/src/executive.rs b/ethcore/src/executive.rs index 98ead0b8e..38239b4a4 100644 --- a/ethcore/src/executive.rs +++ b/ethcore/src/executive.rs @@ -291,7 +291,7 @@ impl<'a, B: 'a + StateBackend, E: Engine + ?Sized> Executive<'a, B, E> { let mut substate = Substate::new(); // NOTE: there can be no invalid transactions from this point. - if !t.is_unsigned() { + if !schedule.eip86 || !t.is_unsigned() { self.state.inc_nonce(&sender)?; } self.state.sub_balance(&sender, &U256::from(gas_cost), &mut substate.to_cleanup_mode(&schedule))?; @@ -383,12 +383,12 @@ impl<'a, B: 'a + StateBackend, E: Engine + ?Sized> Executive<'a, B, E> { mut output: BytesRef, tracer: &mut T, vm_tracer: &mut V - ) -> vm::Result<(U256, ReturnData)> where T: Tracer, V: VMTracer { + ) -> vm::Result where T: Tracer, V: VMTracer { - trace!("Executive::call(params={:?}) self.env_info={:?}", params, self.info); + trace!("Executive::call(params={:?}) self.env_info={:?}, static={}", params, self.info, self.static_flag); if (params.call_type == CallType::StaticCall || - ((params.call_type == CallType::Call || params.call_type == CallType::DelegateCall) && - self.static_flag)) + ((params.call_type == CallType::Call) && + self.static_flag)) && params.value.value() > 0.into() { return Err(vm::Error::MutableCallInStaticContext); } @@ -441,7 +441,11 @@ impl<'a, B: 'a + StateBackend, E: Engine + ?Sized> Executive<'a, B, E> { ); } - Ok((params.gas - cost, ReturnData::empty())) + Ok(FinalizationResult { + gas_left: params.gas - cost, + return_data: ReturnData::new(output.to_owned(), 0, output.len()), + apply_state: true, + }) } } else { // just drain the whole gas @@ -488,13 +492,17 @@ impl<'a, B: 'a + StateBackend, E: Engine + ?Sized> Executive<'a, B, E> { self.enact_result(&res, substate, unconfirmed_substate); trace!(target: "executive", "enacted: substate={:?}\n", substate); - res.map(|r| (r.gas_left, r.return_data)) + res } else { // otherwise it's just a basic transaction, only do tracing, if necessary. self.state.discard_checkpoint(); tracer.trace_call(trace_info, U256::zero(), trace_output, vec![]); - Ok((params.gas, ReturnData::empty())) + Ok(FinalizationResult { + gas_left: params.gas, + return_data: ReturnData::empty(), + apply_state: true, + }) } } } @@ -509,13 +517,18 @@ impl<'a, B: 'a + StateBackend, E: Engine + ?Sized> Executive<'a, B, E> { output: &mut Option, tracer: &mut T, vm_tracer: &mut V, - ) -> vm::Result<(U256, ReturnData)> where T: Tracer, V: VMTracer { + ) -> vm::Result where T: Tracer, V: VMTracer { - let scheme = self.engine.create_address_scheme(self.info.number); - if scheme != CreateContractAddress::FromSenderAndNonce && self.state.exists_and_has_code(¶ms.address)? { + // EIP-684: If a contract creation is attempted, due to either a creation transaction or the + // CREATE (or future CREATE2) opcode, and the destination address already has either + // nonzero nonce, or nonempty code, then the creation throws immediately, with exactly + // the same behavior as would arise if the first byte in the init code were an invalid + // opcode. This applies retroactively starting from genesis. + if self.state.exists_and_has_code_or_nonce(¶ms.address)? { return Err(vm::Error::OutOfGas); } + trace!("Executive::create(params={:?}) self.env_info={:?}, static={}", params, self.info, self.static_flag); if params.call_type == CallType::StaticCall || self.static_flag { let trace_info = tracer.prepare_trace_create(¶ms); tracer.trace_failed_create(trace_info, vec![], vm::Error::MutableCallInStaticContext.into()); @@ -565,7 +578,7 @@ impl<'a, B: 'a + StateBackend, E: Engine + ?Sized> Executive<'a, B, E> { }; self.enact_result(&res, substate, unconfirmed_substate); - res.map(|r| (r.gas_left, r.return_data)) + res } /// Finalizes the transaction (does refunds and suicides). @@ -573,7 +586,7 @@ impl<'a, B: 'a + StateBackend, E: Engine + ?Sized> Executive<'a, B, E> { &mut self, t: &SignedTransaction, mut substate: Substate, - result: vm::Result<(U256, ReturnData)>, + result: vm::Result, output: Bytes, trace: Vec, vm_trace: Option @@ -587,7 +600,7 @@ impl<'a, B: 'a + StateBackend, E: Engine + ?Sized> Executive<'a, B, E> { let refunds_bound = sstore_refunds + suicide_refunds; // real ammount to refund - let gas_left_prerefund = match result { Ok((x, _)) => x, _ => 0.into() }; + let gas_left_prerefund = match result { Ok(FinalizationResult{ gas_left, .. }) => gas_left, _ => 0.into() }; let refunded = cmp::min(refunds_bound, (t.gas - gas_left_prerefund) >> 1); let gas_left = gas_left_prerefund + refunded; @@ -631,9 +644,9 @@ impl<'a, B: 'a + StateBackend, E: Engine + ?Sized> Executive<'a, B, E> { state_diff: None, }) }, - _ => { + Ok(r) => { Ok(Executed { - exception: None, + exception: if r.apply_state { None } else { Some(vm::Error::Reverted) }, gas: t.gas, gas_used: gas_used, refunded: refunded, @@ -659,6 +672,8 @@ impl<'a, B: 'a + StateBackend, E: Engine + ?Sized> Executive<'a, B, E> { | Err(vm::Error::Wasm {..}) | Err(vm::Error::OutOfStack {..}) | Err(vm::Error::MutableCallInStaticContext) + | Err(vm::Error::OutOfBounds) + | Err(vm::Error::Reverted) | Ok(FinalizationResult { apply_state: false, .. }) => { self.state.revert_to_checkpoint(); }, @@ -716,7 +731,7 @@ mod tests { let engine = TestEngine::new(0); let mut substate = Substate::new(); - let (gas_left, _) = { + let FinalizationResult { gas_left, .. } = { let mut ex = Executive::new(&mut state, &info, &engine); ex.create(params, &mut substate, &mut None, &mut NoopTracer, &mut NoopVMTracer).unwrap() }; @@ -774,7 +789,7 @@ mod tests { let engine = TestEngine::new(0); let mut substate = Substate::new(); - let (gas_left, _) = { + let FinalizationResult { gas_left, .. } = { let mut ex = Executive::new(&mut state, &info, &engine); ex.create(params, &mut substate, &mut None, &mut NoopTracer, &mut NoopVMTracer).unwrap() }; @@ -832,7 +847,7 @@ mod tests { let mut tracer = ExecutiveTracer::default(); let mut vm_tracer = ExecutiveVMTracer::toplevel(); - let (gas_left, _) = { + let FinalizationResult { gas_left, .. } = { let mut ex = Executive::new(&mut state, &info, &engine); let output = BytesRef::Fixed(&mut[0u8;0]); ex.call(params, &mut substate, output, &mut tracer, &mut vm_tracer).unwrap() @@ -941,7 +956,7 @@ mod tests { let mut tracer = ExecutiveTracer::default(); let mut vm_tracer = ExecutiveVMTracer::toplevel(); - let (gas_left, _) = { + let FinalizationResult { gas_left, .. } = { let mut ex = Executive::new(&mut state, &info, &engine); ex.create(params.clone(), &mut substate, &mut None, &mut tracer, &mut vm_tracer).unwrap() }; @@ -1026,7 +1041,7 @@ mod tests { let engine = TestEngine::new(0); let mut substate = Substate::new(); - let (gas_left, _) = { + let FinalizationResult { gas_left, .. } = { let mut ex = Executive::new(&mut state, &info, &engine); ex.create(params, &mut substate, &mut None, &mut NoopTracer, &mut NoopVMTracer).unwrap() }; @@ -1137,7 +1152,7 @@ mod tests { let engine = TestEngine::new(0); let mut substate = Substate::new(); - let (gas_left, _) = { + let FinalizationResult { gas_left, .. } = { let mut ex = Executive::new(&mut state, &info, &engine); ex.call(params, &mut substate, BytesRef::Fixed(&mut []), &mut NoopTracer, &mut NoopVMTracer).unwrap() }; @@ -1181,7 +1196,7 @@ mod tests { let engine = TestEngine::new(0); let mut substate = Substate::new(); - let (gas_left, _) = { + let FinalizationResult { gas_left, .. } = { let mut ex = Executive::new(&mut state, &info, &engine); ex.call(params, &mut substate, BytesRef::Fixed(&mut []), &mut NoopTracer, &mut NoopVMTracer).unwrap() }; @@ -1382,11 +1397,11 @@ mod tests { let mut state = get_temp_state_with_factory(factory); state.add_balance(&sender, &U256::from_str("152d02c7e14af68000000").unwrap(), CleanupMode::NoEmpty).unwrap(); let info = EnvInfo::default(); - let engine = TestEngine::new_metropolis(); + let engine = TestEngine::new_byzantium(); let mut substate = Substate::new(); let mut output = [0u8; 14]; - let (result, _) = { + let FinalizationResult { gas_left: result, .. } = { let mut ex = Executive::new(&mut state, &info, &engine); ex.call(params, &mut substate, BytesRef::Fixed(&mut output), &mut NoopTracer, &mut NoopVMTracer).unwrap() }; diff --git a/ethcore/src/externalities.rs b/ethcore/src/externalities.rs index b84fbfe5b..d429f1277 100644 --- a/ethcore/src/externalities.rs +++ b/ethcore/src/externalities.rs @@ -29,6 +29,7 @@ use vm::{ Ext, ContractCreateResult, MessageCallResult, CreateContractAddress, ReturnData }; +use evm::FinalizationResult; use transaction::UNSIGNED_SENDER; use trace::{Tracer, VMTracer}; @@ -127,6 +128,10 @@ impl<'a, T: 'a, V: 'a, B: 'a, E: 'a> Ext for Externalities<'a, T, V, B, E> } } + fn is_static(&self) -> bool { + return self.static_flag + } + fn exists(&self, address: &Address) -> vm::Result { self.state.exists(address).map_err(Into::into) } @@ -216,21 +221,27 @@ impl<'a, T: 'a, V: 'a, B: 'a, E: 'a> Ext for Externalities<'a, T, V, B, E> call_type: CallType::None, }; - if params.sender != UNSIGNED_SENDER { - if let Err(e) = self.state.inc_nonce(&self.origin_info.address) { - debug!(target: "ext", "Database corruption encountered: {:?}", e); - return ContractCreateResult::Failed + if !self.static_flag { + if !self.schedule.eip86 || params.sender != UNSIGNED_SENDER { + if let Err(e) = self.state.inc_nonce(&self.origin_info.address) { + debug!(target: "ext", "Database corruption encountered: {:?}", e); + return ContractCreateResult::Failed + } } } let mut ex = Executive::from_parent(self.state, self.env_info, self.engine, self.depth, self.static_flag); // TODO: handle internal error separately match ex.create(params, self.substate, &mut None, self.tracer, self.vm_tracer) { - Ok((gas_left, _)) => { + Ok(FinalizationResult{ gas_left, apply_state: true, .. }) => { self.substate.contracts_created.push(address.clone()); ContractCreateResult::Created(address, gas_left) }, - _ => ContractCreateResult::Failed + Ok(FinalizationResult{ gas_left, apply_state: false, return_data }) => { + ContractCreateResult::Reverted(gas_left, return_data) + }, + Err(vm::Error::MutableCallInStaticContext) => ContractCreateResult::FailedInStaticCall, + _ => ContractCreateResult::Failed, } } @@ -275,7 +286,8 @@ impl<'a, T: 'a, V: 'a, B: 'a, E: 'a> Ext for Externalities<'a, T, V, B, E> let mut ex = Executive::from_parent(self.state, self.env_info, self.engine, self.depth, self.static_flag); match ex.call(params, self.substate, BytesRef::Fixed(output), self.tracer, self.vm_tracer) { - Ok((gas_left, return_data)) => MessageCallResult::Success(gas_left, return_data), + Ok(FinalizationResult{ gas_left, return_data, apply_state: true }) => MessageCallResult::Success(gas_left, return_data), + Ok(FinalizationResult{ gas_left, return_data, apply_state: false }) => MessageCallResult::Reverted(gas_left, return_data), _ => MessageCallResult::Failed } } @@ -289,7 +301,7 @@ impl<'a, T: 'a, V: 'a, B: 'a, E: 'a> Ext for Externalities<'a, T, V, B, E> } #[cfg_attr(feature="dev", allow(match_ref_pats))] - fn ret(mut self, gas: &U256, data: &ReturnData) -> vm::Result + fn ret(mut self, gas: &U256, data: &ReturnData, apply_state: bool) -> vm::Result where Self: Sized { let handle_copy = |to: &mut Option<&mut Bytes>| { to.as_mut().map(|b| **b = data.to_vec()); @@ -309,7 +321,7 @@ impl<'a, T: 'a, V: 'a, B: 'a, E: 'a> Ext for Externalities<'a, T, V, B, E> vec.extend_from_slice(&*data); Ok(*gas) }, - OutputPolicy::InitContract(ref mut copy) => { + OutputPolicy::InitContract(ref mut copy) if apply_state => { let return_cost = U256::from(data.len()) * U256::from(self.schedule.create_data_gas); if return_cost > *gas || data.len() > self.schedule.create_data_limit { return match self.schedule.exceptional_failed_code_deposit { @@ -317,12 +329,13 @@ impl<'a, T: 'a, V: 'a, B: 'a, E: 'a> Ext for Externalities<'a, T, V, B, E> false => Ok(*gas) } } - handle_copy(copy); - self.state.init_code(&self.origin_info.address, data.to_vec())?; Ok(*gas - return_cost) - } + }, + OutputPolicy::InitContract(_) => { + Ok(*gas) + }, } } diff --git a/ethcore/src/json_tests/chain.rs b/ethcore/src/json_tests/chain.rs index 7047c9882..9ae55f73d 100644 --- a/ethcore/src/json_tests/chain.rs +++ b/ethcore/src/json_tests/chain.rs @@ -15,16 +15,14 @@ // along with Parity. If not, see . use std::sync::Arc; -use client::{BlockChainClient, Client, ClientConfig}; +use client::{EvmTestClient, BlockChainClient, Client, ClientConfig}; use block::Block; -use ethereum; -use tests::helpers::*; use spec::Genesis; use ethjson; use miner::Miner; use io::IoChannel; -pub fn json_chain_test(json_data: &[u8], era: ChainEra) -> Vec { +pub fn json_chain_test(json_data: &[u8]) -> Vec { ::ethcore_logger::init_log(); let tests = ethjson::blockchain::Test::load(json_data).unwrap(); let mut failed = Vec::new(); @@ -42,15 +40,16 @@ pub fn json_chain_test(json_data: &[u8], era: ChainEra) -> Vec { flush!(" - {}...", name); let spec = { + let mut spec = match EvmTestClient::spec_from_json(&blockchain.network) { + Some(spec) => (*spec).clone(), + None => { + println!(" - {} | {:?} Ignoring tests because of missing spec", name, blockchain.network); + continue; + } + }; + let genesis = Genesis::from(blockchain.genesis()); let state = From::from(blockchain.pre_state.clone()); - let mut spec = match era { - ChainEra::Frontier => ethereum::new_frontier_test(), - ChainEra::Homestead => ethereum::new_homestead_test(), - ChainEra::Eip150 => ethereum::new_eip150_test(), - ChainEra::_Eip161 => ethereum::new_eip161_test(), - ChainEra::TransitionTest => ethereum::new_transition_test(), - }; spec.set_genesis_state(state).expect("Failed to overwrite genesis state"); spec.overwrite_genesis_params(genesis); assert!(spec.is_state_root_valid()); @@ -86,67 +85,69 @@ pub fn json_chain_test(json_data: &[u8], era: ChainEra) -> Vec { failed } -mod frontier_era_tests { - use tests::helpers::*; +mod block_tests { use super::json_chain_test; fn do_json_test(json_data: &[u8]) -> Vec { - json_chain_test(json_data, ChainEra::Frontier) + json_chain_test(json_data) } declare_test!{BlockchainTests_bcBlockGasLimitTest, "BlockchainTests/bcBlockGasLimitTest"} - declare_test!{BlockchainTests_bcForkBlockTest, "BlockchainTests/bcForkBlockTest"} + declare_test!{BlockchainTests_bcExploitTest, "BlockchainTests/bcExploitTest"} + declare_test!{BlockchainTests_bcForgedTest, "BlockchainTests/bcForgedTest"} declare_test!{BlockchainTests_bcForkStressTest, "BlockchainTests/bcForkStressTest"} - declare_test!{BlockchainTests_bcForkUncle, "BlockchainTests/bcForkUncle"} declare_test!{BlockchainTests_bcGasPricerTest, "BlockchainTests/bcGasPricerTest"} declare_test!{BlockchainTests_bcInvalidHeaderTest, "BlockchainTests/bcInvalidHeaderTest"} - // TODO [ToDr] Ignored because of incorrect JSON (https://github.com/ethereum/tests/pull/113) - declare_test!{ignore => BlockchainTests_bcInvalidRLPTest, "BlockchainTests/bcInvalidRLPTest"} declare_test!{BlockchainTests_bcMultiChainTest, "BlockchainTests/bcMultiChainTest"} - declare_test!{BlockchainTests_bcRPC_API_Test, "BlockchainTests/bcRPC_API_Test"} - declare_test!{BlockchainTests_bcStateTest, "BlockchainTests/bcStateTest"} + declare_test!{BlockchainTests_bcRandomBlockhashTest, "BlockchainTests/bcRandomBlockhashTest"} declare_test!{BlockchainTests_bcTotalDifficultyTest, "BlockchainTests/bcTotalDifficultyTest"} declare_test!{BlockchainTests_bcUncleHeaderValiditiy, "BlockchainTests/bcUncleHeaderValiditiy"} declare_test!{BlockchainTests_bcUncleTest, "BlockchainTests/bcUncleTest"} declare_test!{BlockchainTests_bcValidBlockTest, "BlockchainTests/bcValidBlockTest"} declare_test!{BlockchainTests_bcWalletTest, "BlockchainTests/bcWalletTest"} - declare_test!{BlockchainTests_RandomTests_bl10251623GO, "BlockchainTests/RandomTests/bl10251623GO"} - declare_test!{BlockchainTests_RandomTests_bl201507071825GO, "BlockchainTests/RandomTests/bl201507071825GO"} + declare_test!{BlockchainTests_GeneralStateTest_stAttackTest, "BlockchainTests/GeneralStateTests/stAttackTest/"} + declare_test!{BlockchainTests_GeneralStateTest_stBadOpcodeTest, "BlockchainTests/GeneralStateTests/stBadOpcode/"} + declare_test!{BlockchainTests_GeneralStateTest_stCallCodes, "BlockchainTests/GeneralStateTests/stCallCodes/"} + declare_test!{BlockchainTests_GeneralStateTest_stCallDelegateCodesCallCodeHomestead, "BlockchainTests/GeneralStateTests/stCallDelegateCodesCallCodeHomestead/"} + declare_test!{BlockchainTests_GeneralStateTest_stCallDelegateCodesHomestead, "BlockchainTests/GeneralStateTests/stCallDelegateCodesHomestead/"} + declare_test!{BlockchainTests_GeneralStateTest_stChangedEIP150, "BlockchainTests/GeneralStateTests/stChangedEIP150/"} + declare_test!{BlockchainTests_GeneralStateTest_stCodeSizeLimit, "BlockchainTests/GeneralStateTests/stCodeSizeLimit/"} + declare_test!{BlockchainTests_GeneralStateTest_stCreateTest, "BlockchainTests/GeneralStateTests/stCreateTest/"} + declare_test!{BlockchainTests_GeneralStateTest_stDelegatecallTestHomestead, "BlockchainTests/GeneralStateTests/stDelegatecallTestHomestead/"} + declare_test!{BlockchainTests_GeneralStateTest_stEIP150singleCodeGasPrices, "BlockchainTests/GeneralStateTests/stEIP150singleCodeGasPrices/"} + declare_test!{BlockchainTests_GeneralStateTest_stEIP150Specific, "BlockchainTests/GeneralStateTests/stEIP150Specific/"} + declare_test!{BlockchainTests_GeneralStateTest_stEIP158Specific, "BlockchainTests/GeneralStateTests/stEIP158Specific/"} + declare_test!{BlockchainTests_GeneralStateTest_stExample, "BlockchainTests/GeneralStateTests/stExample/"} + declare_test!{BlockchainTests_GeneralStateTest_stHomesteadSpecific, "BlockchainTests/GeneralStateTests/stHomesteadSpecific/"} + declare_test!{BlockchainTests_GeneralStateTest_stInitCodeTest, "BlockchainTests/GeneralStateTests/stInitCodeTest/"} + declare_test!{BlockchainTests_GeneralStateTest_stLogTests, "BlockchainTests/GeneralStateTests/stLogTests/"} + declare_test!{BlockchainTests_GeneralStateTest_stMemExpandingEIP150Calls, "BlockchainTests/GeneralStateTests/stMemExpandingEIP150Calls/"} + declare_test!{heavy => BlockchainTests_GeneralStateTest_stMemoryStressTest, "BlockchainTests/GeneralStateTests/stMemoryStressTest/"} + declare_test!{BlockchainTests_GeneralStateTest_stMemoryTest, "BlockchainTests/GeneralStateTests/stMemoryTest/"} + declare_test!{BlockchainTests_GeneralStateTest_stNonZeroCallsTest, "BlockchainTests/GeneralStateTests/stNonZeroCallsTest/"} + declare_test!{BlockchainTests_GeneralStateTest_stPreCompiledContracts, "BlockchainTests/GeneralStateTests/stPreCompiledContracts/"} + declare_test!{heavy => BlockchainTests_GeneralStateTest_stQuadraticComplexityTest, "BlockchainTests/GeneralStateTests/stQuadraticComplexityTest/"} + declare_test!{BlockchainTests_GeneralStateTest_stRandom, "BlockchainTests/GeneralStateTests/stRandom/"} + declare_test!{BlockchainTests_GeneralStateTest_stRecursiveCreate, "BlockchainTests/GeneralStateTests/stRecursiveCreate/"} + declare_test!{BlockchainTests_GeneralStateTest_stRefundTest, "BlockchainTests/GeneralStateTests/stRefundTest/"} + declare_test!{BlockchainTests_GeneralStateTest_stReturnDataTest, "BlockchainTests/GeneralStateTests/stReturnDataTest/"} + declare_test!{BlockchainTests_GeneralStateTest_stRevertTest, "BlockchainTests/GeneralStateTests/stRevertTest/"} + declare_test!{BlockchainTests_GeneralStateTest_stSolidityTest, "BlockchainTests/GeneralStateTests/stSolidityTest/"} + declare_test!{BlockchainTests_GeneralStateTest_stSpecialTest, "BlockchainTests/GeneralStateTests/stSpecialTest/"} + declare_test!{BlockchainTests_GeneralStateTest_stStackTests, "BlockchainTests/GeneralStateTests/stStackTests/"} + declare_test!{BlockchainTests_GeneralStateTest_stStaticCall, "BlockchainTests/GeneralStateTests/stStaticCall/"} + declare_test!{BlockchainTests_GeneralStateTest_stSystemOperationsTest, "BlockchainTests/GeneralStateTests/stSystemOperationsTest/"} + declare_test!{BlockchainTests_GeneralStateTest_stTransactionTest, "BlockchainTests/GeneralStateTests/stTransactionTest/"} + declare_test!{BlockchainTests_GeneralStateTest_stTransitionTest, "BlockchainTests/GeneralStateTests/stTransitionTest/"} + declare_test!{BlockchainTests_GeneralStateTest_stWalletTest, "BlockchainTests/GeneralStateTests/stWalletTest/"} + declare_test!{BlockchainTests_GeneralStateTest_stZeroCallsRevert, "BlockchainTests/GeneralStateTests/stZeroCallsRevert/"} + declare_test!{BlockchainTests_GeneralStateTest_stZeroCallsTest, "BlockchainTests/GeneralStateTests/stZeroCallsTest/"} + declare_test!{BlockchainTests_GeneralStateTest_stZeroKnowledge, "BlockchainTests/GeneralStateTests/stZeroKnowledge/"} + + declare_test!{BlockchainTests_TransitionTests_bcEIP158ToByzantium, "BlockchainTests/TransitionTests/bcEIP158ToByzantium/"} + declare_test!{BlockchainTests_TransitionTests_bcFrontierToHomestead, "BlockchainTests/TransitionTests/bcFrontierToHomestead/"} + declare_test!{BlockchainTests_TransitionTests_bcHomesteadToDao, "BlockchainTests/TransitionTests/bcHomesteadToDao/"} + declare_test!{BlockchainTests_TransitionTests_bcHomesteadToEIP150, "BlockchainTests/TransitionTests/bcHomesteadToEIP150/"} } -mod transition_tests { - use tests::helpers::*; - use super::json_chain_test; - - fn do_json_test(json_data: &[u8]) -> Vec { - json_chain_test(json_data, ChainEra::TransitionTest) - } - - declare_test!{BlockchainTests_TestNetwork_bcSimpleTransitionTest, "BlockchainTests/TestNetwork/bcSimpleTransitionTest"} - declare_test!{BlockchainTests_TestNetwork_bcTheDaoTest, "BlockchainTests/TestNetwork/bcTheDaoTest"} - declare_test!{BlockchainTests_TestNetwork_bcEIP150Test, "BlockchainTests/TestNetwork/bcEIP150Test"} -} - -mod eip150_blockchain_tests { - use tests::helpers::*; - use super::json_chain_test; - - fn do_json_test(json_data: &[u8]) -> Vec { - json_chain_test(json_data, ChainEra::Eip150) - } - - declare_test!{BlockchainTests_EIP150_bcBlockGasLimitTest, "BlockchainTests/EIP150/bcBlockGasLimitTest"} - declare_test!{BlockchainTests_EIP150_bcForkStressTest, "BlockchainTests/EIP150/bcForkStressTest"} - declare_test!{BlockchainTests_EIP150_bcGasPricerTest, "BlockchainTests/EIP150/bcGasPricerTest"} - declare_test!{BlockchainTests_EIP150_bcInvalidHeaderTest, "BlockchainTests/EIP150/bcInvalidHeaderTest"} - declare_test!{BlockchainTests_EIP150_bcInvalidRLPTest, "BlockchainTests/EIP150/bcInvalidRLPTest"} - declare_test!{BlockchainTests_EIP150_bcMultiChainTest, "BlockchainTests/EIP150/bcMultiChainTest"} - declare_test!{BlockchainTests_EIP150_bcRPC_API_Test, "BlockchainTests/EIP150/bcRPC_API_Test"} - declare_test!{BlockchainTests_EIP150_bcStateTest, "BlockchainTests/EIP150/bcStateTest"} - declare_test!{BlockchainTests_EIP150_bcTotalDifficultyTest, "BlockchainTests/EIP150/bcTotalDifficultyTest"} - declare_test!{BlockchainTests_EIP150_bcUncleHeaderValiditiy, "BlockchainTests/EIP150/bcUncleHeaderValiditiy"} - declare_test!{BlockchainTests_EIP150_bcUncleTest, "BlockchainTests/EIP150/bcUncleTest"} - declare_test!{BlockchainTests_EIP150_bcValidBlockTest, "BlockchainTests/EIP150/bcValidBlockTest"} - declare_test!{BlockchainTests_EIP150_bcWalletTest, "BlockchainTests/EIP150/bcWalletTest"} -} diff --git a/ethcore/src/json_tests/executive.rs b/ethcore/src/json_tests/executive.rs index f6d3023c9..3a28a4825 100644 --- a/ethcore/src/json_tests/executive.rs +++ b/ethcore/src/json_tests/executive.rs @@ -32,6 +32,8 @@ use trace::{Tracer, NoopTracer}; use trace::{VMTracer, NoopVMTracer}; use bytes::{Bytes, BytesRef}; use trie; +use rlp::RlpStream; +use hash::keccak; #[derive(Debug, PartialEq, Clone)] struct CallCreate { @@ -162,8 +164,8 @@ impl<'a, T: 'a, V: 'a, B: 'a, E: 'a> Ext for TestExt<'a, T, V, B, E> self.ext.log(topics, data) } - fn ret(self, gas: &U256, data: &ReturnData) -> Result { - self.ext.ret(gas, data) + fn ret(self, gas: &U256, data: &ReturnData, apply_state: bool) -> Result { + self.ext.ret(gas, data, apply_state) } fn suicide(&mut self, refund_address: &Address) -> vm::Result<()> { @@ -182,6 +184,10 @@ impl<'a, T: 'a, V: 'a, B: 'a, E: 'a> Ext for TestExt<'a, T, V, B, E> 0 } + fn is_static(&self) -> bool { + false + } + fn inc_sstore_clears(&mut self) { self.ext.inc_sstore_clears() } @@ -255,6 +261,14 @@ fn do_json_test_for(vm_type: &VMType, json_data: &[u8]) -> Vec { (res.finalize(ex), callcreates) }; + let log_hash = { + let mut rlp = RlpStream::new_list(substate.logs.len()); + for l in &substate.logs { + rlp.append(l); + } + keccak(&rlp.drain()) + }; + match res { Err(_) => fail_unless(out_of_gas, "didn't expect to run out of gas."), Ok(res) => { @@ -262,6 +276,7 @@ fn do_json_test_for(vm_type: &VMType, json_data: &[u8]) -> Vec { fail_unless(Some(res.gas_left) == vm.gas_left.map(Into::into), "gas_left is incorrect"); let vm_output: Option> = vm.output.map(Into::into); fail_unless(Some(output) == vm_output, "output is incorrect"); + fail_unless(Some(log_hash) == vm.logs.map(|h| h.0), "logs are incorrect"); for (address, account) in vm.post_state.unwrap().into_iter() { let address = address.into(); @@ -295,15 +310,15 @@ fn do_json_test_for(vm_type: &VMType, json_data: &[u8]) -> Vec { } declare_test!{ExecutiveTests_vmArithmeticTest, "VMTests/vmArithmeticTest"} -declare_test!{ExecutiveTests_vmBitwiseLogicOperationTest, "VMTests/vmBitwiseLogicOperationTest"} +declare_test!{ExecutiveTests_vmBitwiseLogicOperationTest, "VMTests/vmBitwiseLogicOperation"} declare_test!{ExecutiveTests_vmBlockInfoTest, "VMTests/vmBlockInfoTest"} // TODO [todr] Fails with Signal 11 when using JIT -declare_test!{ExecutiveTests_vmEnvironmentalInfoTest, "VMTests/vmEnvironmentalInfoTest"} -declare_test!{ExecutiveTests_vmIOandFlowOperationsTest, "VMTests/vmIOandFlowOperationsTest"} -declare_test!{heavy => ExecutiveTests_vmInputLimits, "VMTests/vmInputLimits"} +declare_test!{ExecutiveTests_vmEnvironmentalInfoTest, "VMTests/vmEnvironmentalInfo"} +declare_test!{ExecutiveTests_vmIOandFlowOperationsTest, "VMTests/vmIOandFlowOperations"} declare_test!{ExecutiveTests_vmLogTest, "VMTests/vmLogTest"} -declare_test!{ExecutiveTests_vmPerformanceTest, "VMTests/vmPerformanceTest"} +declare_test!{heavy => ExecutiveTests_vmPerformance, "VMTests/vmPerformance"} declare_test!{ExecutiveTests_vmPushDupSwapTest, "VMTests/vmPushDupSwapTest"} +declare_test!{ExecutiveTests_vmRandomTest, "VMTests/vmRandomTest"} declare_test!{ExecutiveTests_vmSha3Test, "VMTests/vmSha3Test"} -declare_test!{ExecutiveTests_vmSystemOperationsTest, "VMTests/vmSystemOperationsTest"} -declare_test!{ExecutiveTests_vmtests, "VMTests/vmtests"} +declare_test!{ExecutiveTests_vmSystemOperationsTest, "VMTests/vmSystemOperations"} +declare_test!{ExecutiveTests_vmTests, "VMTests/vmTests"} diff --git a/ethcore/src/json_tests/homestead_chain.rs b/ethcore/src/json_tests/homestead_chain.rs deleted file mode 100644 index 5f0fe5769..000000000 --- a/ethcore/src/json_tests/homestead_chain.rs +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright 2015-2017 Parity Technologies (UK) Ltd. -// This file is part of Parity. - -// Parity is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Parity is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Parity. If not, see . - -use super::chain::json_chain_test; -use tests::helpers::*; - -fn do_json_test(json_data: &[u8]) -> Vec { - json_chain_test(json_data, ChainEra::Homestead) -} - -declare_test!{BlockchainTests_Homestead_bcBlockGasLimitTest, "BlockchainTests/Homestead/bcBlockGasLimitTest"} -declare_test!{BlockchainTests_Homestead_bcForkStressTest, "BlockchainTests/Homestead/bcForkStressTest"} -declare_test!{BlockchainTests_Homestead_bcGasPricerTest, "BlockchainTests/Homestead/bcGasPricerTest"} -declare_test!{BlockchainTests_Homestead_bcInvalidHeaderTest, "BlockchainTests/Homestead/bcInvalidHeaderTest"} -declare_test!{BlockchainTests_Homestead_bcInvalidRLPTest, "BlockchainTests/Homestead/bcInvalidRLPTest"} -declare_test!{BlockchainTests_Homestead_bcMultiChainTest, "BlockchainTests/Homestead/bcMultiChainTest"} -declare_test!{BlockchainTests_Homestead_bcRPC_API_Test, "BlockchainTests/Homestead/bcRPC_API_Test"} -declare_test!{BlockchainTests_Homestead_bcStateTest, "BlockchainTests/Homestead/bcStateTest"} -declare_test!{BlockchainTests_Homestead_bcTotalDifficultyTest, "BlockchainTests/Homestead/bcTotalDifficultyTest"} -declare_test!{BlockchainTests_Homestead_bcUncleHeaderValiditiy, "BlockchainTests/Homestead/bcUncleHeaderValiditiy"} -declare_test!{BlockchainTests_Homestead_bcUncleTest, "BlockchainTests/Homestead/bcUncleTest"} -declare_test!{BlockchainTests_Homestead_bcValidBlockTest, "BlockchainTests/Homestead/bcValidBlockTest"} -declare_test!{BlockchainTests_Homestead_bcWalletTest, "BlockchainTests/Homestead/bcWalletTest"} -declare_test!{BlockchainTests_Homestead_bcShanghaiLove, "BlockchainTests/Homestead/bcShanghaiLove"} -declare_test!{BlockchainTests_Homestead_bcSuicideIssue, "BlockchainTests/Homestead/bcSuicideIssue"} -declare_test!{BlockchainTests_Homestead_bcExploitTest, "BlockchainTests/Homestead/bcExploitTest"} diff --git a/ethcore/src/json_tests/mod.rs b/ethcore/src/json_tests/mod.rs index 406782072..ab3205d18 100644 --- a/ethcore/src/json_tests/mod.rs +++ b/ethcore/src/json_tests/mod.rs @@ -21,5 +21,4 @@ mod transaction; mod executive; mod state; mod chain; -mod homestead_chain; mod trie; diff --git a/ethcore/src/json_tests/state.rs b/ethcore/src/json_tests/state.rs index 51961a2bb..cc6b0ed1d 100644 --- a/ethcore/src/json_tests/state.rs +++ b/ethcore/src/json_tests/state.rs @@ -97,9 +97,8 @@ mod state_tests { } declare_test!{GeneralStateTest_stAttackTest, "GeneralStateTests/stAttackTest/"} - declare_test!{GeneralStateTest_stBoundsTest, "GeneralStateTests/stBoundsTest/"} + declare_test!{GeneralStateTest_stBadOpcodeTest, "GeneralStateTests/stBadOpcode/"} declare_test!{GeneralStateTest_stCallCodes, "GeneralStateTests/stCallCodes/"} - declare_test!{skip => [ "createJS_ExampleContract" ], GeneralStateTest_stCallCreateCallCodeTest, "GeneralStateTests/stCallCreateCallCodeTest/"} declare_test!{GeneralStateTest_stCallDelegateCodesCallCodeHomestead, "GeneralStateTests/stCallDelegateCodesCallCodeHomestead/"} declare_test!{GeneralStateTest_stCallDelegateCodesHomestead, "GeneralStateTests/stCallDelegateCodesHomestead/"} declare_test!{GeneralStateTest_stChangedEIP150, "GeneralStateTests/stChangedEIP150/"} @@ -108,6 +107,7 @@ mod state_tests { declare_test!{GeneralStateTest_stDelegatecallTestHomestead, "GeneralStateTests/stDelegatecallTestHomestead/"} declare_test!{GeneralStateTest_stEIP150singleCodeGasPrices, "GeneralStateTests/stEIP150singleCodeGasPrices/"} declare_test!{GeneralStateTest_stEIP150Specific, "GeneralStateTests/stEIP150Specific/"} + declare_test!{GeneralStateTest_stEIP158Specific, "GeneralStateTests/stEIP158Specific/"} declare_test!{GeneralStateTest_stExample, "GeneralStateTests/stExample/"} declare_test!{GeneralStateTest_stHomesteadSpecific, "GeneralStateTests/stHomesteadSpecific/"} declare_test!{GeneralStateTest_stInitCodeTest, "GeneralStateTests/stInitCodeTest/"} @@ -121,15 +121,18 @@ mod state_tests { declare_test!{GeneralStateTest_stRandom, "GeneralStateTests/stRandom/"} declare_test!{GeneralStateTest_stRecursiveCreate, "GeneralStateTests/stRecursiveCreate/"} declare_test!{GeneralStateTest_stRefundTest, "GeneralStateTests/stRefundTest/"} - declare_test!{skip => [ "RevertDepthCreateAddressCollision" ], GeneralStateTest_stRevertTest, "GeneralStateTests/stRevertTest/"} + declare_test!{GeneralStateTest_stReturnDataTest, "GeneralStateTests/stReturnDataTest/"} + declare_test!{GeneralStateTest_stRevertTest, "GeneralStateTests/stRevertTest/"} declare_test!{GeneralStateTest_stSolidityTest, "GeneralStateTests/stSolidityTest/"} declare_test!{GeneralStateTest_stSpecialTest, "GeneralStateTests/stSpecialTest/"} declare_test!{GeneralStateTest_stStackTests, "GeneralStateTests/stStackTests/"} + declare_test!{GeneralStateTest_stStaticCall, "GeneralStateTests/stStaticCall/"} declare_test!{GeneralStateTest_stSystemOperationsTest, "GeneralStateTests/stSystemOperationsTest/"} declare_test!{GeneralStateTest_stTransactionTest, "GeneralStateTests/stTransactionTest/"} declare_test!{GeneralStateTest_stTransitionTest, "GeneralStateTests/stTransitionTest/"} declare_test!{GeneralStateTest_stWalletTest, "GeneralStateTests/stWalletTest/"} declare_test!{GeneralStateTest_stZeroCallsRevert, "GeneralStateTests/stZeroCallsRevert/"} declare_test!{GeneralStateTest_stZeroCallsTest, "GeneralStateTests/stZeroCallsTest/"} + declare_test!{GeneralStateTest_stZeroKnowledge, "GeneralStateTests/stZeroKnowledge/"} } diff --git a/ethcore/src/json_tests/transaction.rs b/ethcore/src/json_tests/transaction.rs index 3d71a5faf..6ae8123f1 100644 --- a/ethcore/src/json_tests/transaction.rs +++ b/ethcore/src/json_tests/transaction.rs @@ -25,7 +25,7 @@ fn do_json_test(json_data: &[u8]) -> Vec { let mut failed = Vec::new(); let frontier_schedule = evm::Schedule::new_frontier(); let homestead_schedule = evm::Schedule::new_homestead(); - let metropolis_schedule = evm::Schedule::new_metropolis(); + let byzantium_schedule = evm::Schedule::new_byzantium(); for (name, test) in tests.into_iter() { let mut fail_unless = |cond: bool, title: &str| if !cond { failed.push(name.clone()); println!("Transaction failed: {:?}: {:?}", name, title); }; @@ -34,7 +34,7 @@ fn do_json_test(json_data: &[u8]) -> Vec { None => &frontier_schedule, Some(x) if x < 1_150_000 => &frontier_schedule, Some(x) if x < 3_000_000 => &homestead_schedule, - Some(_) => &metropolis_schedule + Some(_) => &byzantium_schedule }; let allow_chain_id_of_one = number.map_or(false, |n| n >= 2_675_000); let allow_unsigned = number.map_or(false, |n| n >= 3_000_000); @@ -75,18 +75,13 @@ fn do_json_test(json_data: &[u8]) -> Vec { failed } -declare_test!{TransactionTests_ttTransactionTest, "TransactionTests/ttTransactionTest"} -declare_test!{heavy => TransactionTests_tt10mbDataField, "TransactionTests/tt10mbDataField"} -declare_test!{TransactionTests_ttWrongRLPTransaction, "TransactionTests/ttWrongRLPTransaction"} -declare_test!{TransactionTests_Homestead_ttTransactionTest, "TransactionTests/Homestead/ttTransactionTest"} -declare_test!{heavy => TransactionTests_Homestead_tt10mbDataField, "TransactionTests/Homestead/tt10mbDataField"} -declare_test!{TransactionTests_Homestead_ttWrongRLPTransaction, "TransactionTests/Homestead/ttWrongRLPTransaction"} -declare_test!{TransactionTests_RandomTests_tr201506052141PYTHON, "TransactionTests/RandomTests/tr201506052141PYTHON"} -declare_test!{TransactionTests_Homestead_ttTransactionTestEip155VitaliksTests, "TransactionTests/Homestead/ttTransactionTestEip155VitaliksTests"} -declare_test!{TransactionTests_EIP155_ttTransactionTest, "TransactionTests/EIP155/ttTransactionTest"} -declare_test!{TransactionTests_EIP155_ttTransactionTestEip155VitaliksTests, "TransactionTests/EIP155/ttTransactionTestEip155VitaliksTests"} -declare_test!{TransactionTests_EIP155_ttTransactionTestVRule, "TransactionTests/EIP155/ttTransactionTestVRule"} - -declare_test!{TransactionTests_Metropolis_ttMetropolisTest, "TransactionTests/Metropolis/ttMetropolisTest"} -declare_test!{TransactionTests_Metropolis_ttTransactionTest, "TransactionTests/Metropolis/ttTransactionTest"} -declare_test!{TransactionTests_Metropolis_ttTransactionTestZeroSig, "TransactionTests/Metropolis/ttTransactionTestZeroSig"} +declare_test!{TransactionTests_ttEip155VitaliksHomesead, "TransactionTests/ttEip155VitaliksHomesead"} +declare_test!{TransactionTests_ttEip155VitaliksEip158, "TransactionTests/ttEip155VitaliksEip158"} +declare_test!{TransactionTests_ttEip158, "TransactionTests/ttEip158"} +declare_test!{TransactionTests_ttFrontier, "TransactionTests/ttFrontier"} +declare_test!{TransactionTests_ttHomestead, "TransactionTests/ttHomestead"} +declare_test!{TransactionTests_ttVRuleEip158, "TransactionTests/ttVRuleEip158"} +declare_test!{TransactionTests_ttWrongRLPFrontier, "TransactionTests/ttWrongRLPFrontier"} +declare_test!{TransactionTests_ttWrongRLPHomestead, "TransactionTests/ttWrongRLPHomestead"} +declare_test!{TransactionTests_ttConstantinople, "TransactionTests/ttConstantinople"} +declare_test!{TransactionTests_ttSpecConstantinople, "TransactionTests/ttSpecConstantinople"} diff --git a/ethcore/src/spec/spec.rs b/ethcore/src/spec/spec.rs index 0cf5e7eb5..f4f961cc0 100644 --- a/ethcore/src/spec/spec.rs +++ b/ethcore/src/spec/spec.rs @@ -70,6 +70,8 @@ pub struct CommonParams { pub fork_block: Option<(BlockNumber, H256)>, /// Number of first block where EIP-98 rules begin. pub eip98_transition: BlockNumber, + /// Number of first block where EIP-658 rules begin. + pub eip658_transition: BlockNumber, /// Number of first block where EIP-155 rules begin. pub eip155_transition: BlockNumber, /// Validate block receipts root. @@ -125,7 +127,7 @@ impl CommonParams { schedule.have_static_call = block_number >= self.eip214_transition; schedule.have_return_data = block_number >= self.eip211_transition; if block_number >= self.eip210_transition { - schedule.blockhash_gas = 350; + schedule.blockhash_gas = 800; } if block_number >= self.dust_protection_transition { schedule.kill_dust = match self.remove_dust_contracts { @@ -172,6 +174,7 @@ impl From for CommonParams { eip210_contract_gas: p.eip210_contract_gas.map_or(1000000.into(), Into::into), eip211_transition: p.eip211_transition.map_or(BlockNumber::max_value(), Into::into), eip214_transition: p.eip214_transition.map_or(BlockNumber::max_value(), Into::into), + eip658_transition: p.eip658_transition.map_or(BlockNumber::max_value(), Into::into), dust_protection_transition: p.dust_protection_transition.map_or(BlockNumber::max_value(), Into::into), nonce_cap_increment: p.nonce_cap_increment.map_or(64, Into::into), remove_dust_contracts: p.remove_dust_contracts.unwrap_or(false), @@ -229,7 +232,33 @@ pub struct Spec { genesis_state: PodState, } -fn load_from>(cache_dir: T, s: ethjson::spec::Spec) -> Result { +#[cfg(test)] +impl Clone for Spec { + fn clone(&self) -> Spec { + Spec { + name: self.name.clone(), + engine: self.engine.clone(), + data_dir: self.data_dir.clone(), + nodes: self.nodes.clone(), + parent_hash: self.parent_hash.clone(), + transactions_root: self.transactions_root.clone(), + receipts_root: self.receipts_root.clone(), + author: self.author.clone(), + difficulty: self.difficulty.clone(), + gas_limit: self.gas_limit.clone(), + gas_used: self.gas_used.clone(), + timestamp: self.timestamp.clone(), + extra_data: self.extra_data.clone(), + seal_rlp: self.seal_rlp.clone(), + constructors: self.constructors.clone(), + state_root_memo: RwLock::new(*self.state_root_memo.read()), + genesis_state: self.genesis_state.clone(), + } + } +} + +/// Load from JSON object. +pub fn load_from>(cache_dir: T, s: ethjson::spec::Spec) -> Result { let builtins = s.accounts.builtins().into_iter().map(|p| (p.0.into(), From::from(p.1))).collect(); let g = Genesis::from(s.genesis); let GenericSeal(seal_rlp) = g.seal.into(); diff --git a/ethcore/src/state/mod.rs b/ethcore/src/state/mod.rs index 8f7259c4b..3935d7d86 100644 --- a/ethcore/src/state/mod.rs +++ b/ethcore/src/state/mod.rs @@ -503,9 +503,10 @@ impl State { self.ensure_cached(a, RequireCache::None, false, |a| a.map_or(false, |a| !a.is_null())) } - /// Determine whether an account exists and has code. - pub fn exists_and_has_code(&self, a: &Address) -> trie::Result { - self.ensure_cached(a, RequireCache::CodeSize, false, |a| a.map_or(false, |a| a.code_size().map_or(false, |size| size != 0))) + /// Determine whether an account exists and has code or non-zero nonce. + pub fn exists_and_has_code_or_nonce(&self, a: &Address) -> trie::Result { + self.ensure_cached(a, RequireCache::CodeSize, false, + |a| a.map_or(false, |a| a.code_hash() != KECCAK_EMPTY || *a.nonce() != self.account_start_nonce)) } /// Get the balance of account `a`. @@ -697,15 +698,26 @@ impl State { let options = TransactOptions::new(tracer, vm_tracer); let e = self.execute(env_info, engine, t, options, false)?; - let state_root = if env_info.number < engine.params().eip98_transition || env_info.number < engine.params().validate_receipts_transition { + let eip658 = env_info.number >= engine.params().eip658_transition; + let no_intermediate_commits = + eip658 || + (env_info.number >= engine.params().eip98_transition && env_info.number >= engine.params().validate_receipts_transition); + + let state_root = if no_intermediate_commits { + None + } else { self.commit()?; Some(self.root().clone()) + }; + + let status_byte = if eip658 { + Some(if e.exception.is_some() { 0 } else { 1 }) } else { None }; let output = e.output; - let receipt = Receipt::new(state_root, e.cumulative_gas_used, e.logs); + let receipt = Receipt::new(state_root, status_byte, e.cumulative_gas_used, e.logs); trace!(target: "state", "Transaction receipt: {:?}", receipt); Ok(ApplyOutcome { diff --git a/ethcore/src/tests/evm.rs b/ethcore/src/tests/evm.rs index f8eb178d5..24f1e2acb 100644 --- a/ethcore/src/tests/evm.rs +++ b/ethcore/src/tests/evm.rs @@ -24,7 +24,7 @@ fn test_blockhash_eip210(factory: Factory) { let test_blockhash_contract = "73fffffffffffffffffffffffffffffffffffffffe33141561007a57600143036020526000356101006020510755600061010060205107141561005057600035610100610100602051050761010001555b6000620100006020510714156100755760003561010062010000602051050761020001555b61014a565b4360003512151561009057600060405260206040f35b610100600035430312156100b357610100600035075460605260206060f3610149565b62010000600035430312156100d157600061010060003507146100d4565b60005b156100f6576101006101006000350507610100015460805260206080f3610148565b630100000060003543031215610116576000620100006000350714610119565b60005b1561013c57610100620100006000350507610200015460a052602060a0f3610147565b600060c052602060c0f35b5b5b5b5b"; let blockhash_contract_code = Arc::new(test_blockhash_contract.from_hex().unwrap()); let blockhash_contract_code_hash = keccak(blockhash_contract_code.as_ref()); - let engine = TestEngine::new_metropolis(); + let engine = TestEngine::new_constantinople(); let mut env_info = EnvInfo::default(); // populate state with 256 last hashes diff --git a/ethcore/src/tests/helpers.rs b/ethcore/src/tests/helpers.rs index 80eadcfa5..f61fa9d5a 100644 --- a/ethcore/src/tests/helpers.rs +++ b/ethcore/src/tests/helpers.rs @@ -42,15 +42,6 @@ use transaction::{Action, Transaction, SignedTransaction}; use rlp::{self, RlpStream}; use views::BlockView; -#[cfg(feature = "json-tests")] -pub enum ChainEra { - Frontier, - Homestead, - Eip150, - _Eip161, - TransitionTest, -} - pub struct TestEngine { engine: Arc, max_depth: usize, @@ -64,9 +55,16 @@ impl TestEngine { } } - pub fn new_metropolis() -> TestEngine { + pub fn new_byzantium() -> TestEngine { TestEngine { - engine: ethereum::new_metropolis_test().engine, + engine: ethereum::new_byzantium_test().engine, + max_depth: 0, + } + } + + pub fn new_constantinople() -> TestEngine { + TestEngine { + engine: ethereum::new_constantinople_test().engine, max_depth: 0, } } @@ -427,5 +425,8 @@ pub fn get_default_ethash_params() -> EthashParams { max_gas_limit: U256::max_value(), min_gas_price_transition: u64::max_value(), min_gas_price: U256::zero(), + eip649_transition: u64::max_value(), + eip649_delay: 3_000_000, + eip649_reward: None, } } diff --git a/ethcore/src/trace/types/error.rs b/ethcore/src/trace/types/error.rs index 5cedefd09..70a3c315a 100644 --- a/ethcore/src/trace/types/error.rs +++ b/ethcore/src/trace/types/error.rs @@ -43,6 +43,10 @@ pub enum Error { MutableCallInStaticContext, /// Wasm error Wasm, + /// Contract tried to access past the return data buffer. + OutOfBounds, + /// Execution has been reverted with REVERT instruction. + Reverted, } impl<'a> From<&'a VmError> for Error { @@ -57,6 +61,8 @@ impl<'a> From<&'a VmError> for Error { VmError::Wasm { .. } => Error::Wasm, VmError::Internal(_) => Error::Internal, VmError::MutableCallInStaticContext => Error::MutableCallInStaticContext, + VmError::OutOfBounds => Error::OutOfBounds, + VmError::Reverted => Error::Reverted, } } } @@ -80,6 +86,8 @@ impl fmt::Display for Error { Wasm => "Wasm runtime error", Internal => "Internal error", MutableCallInStaticContext => "Mutable Call In Static Context", + OutOfBounds => "Out of bounds", + Reverted => "Reverted", }; message.fmt(f) } @@ -98,6 +106,8 @@ impl Encodable for Error { BuiltIn => 6, MutableCallInStaticContext => 7, Wasm => 8, + OutOfBounds => 9, + Reverted => 10, }; s.append_internal(&value); @@ -118,6 +128,8 @@ impl Decodable for Error { 6 => Ok(BuiltIn), 7 => Ok(MutableCallInStaticContext), 8 => Ok(Wasm), + 9 => Ok(OutOfBounds), + 10 => Ok(Reverted), _ => Err(DecoderError::Custom("Invalid error type")), } } diff --git a/ethcore/types/src/receipt.rs b/ethcore/types/src/receipt.rs index 759f67050..380a9fa8d 100644 --- a/ethcore/types/src/receipt.rs +++ b/ethcore/types/src/receipt.rs @@ -36,23 +36,29 @@ pub struct Receipt { pub log_bloom: LogBloom, /// The logs stemming from this transaction. pub logs: Vec, + /// Status byte. Optional before EIP-658. + pub status_code: Option, } impl Receipt { /// Create a new receipt. - pub fn new(state_root: Option, gas_used: U256, logs: Vec) -> Receipt { + pub fn new(state_root: Option, status_code: Option, gas_used: U256, logs: Vec) -> Receipt { Receipt { state_root: state_root, gas_used: gas_used, log_bloom: logs.iter().fold(LogBloom::default(), |mut b, l| { b = &b | &l.bloom(); b }), //TODO: use |= operator logs: logs, + status_code: status_code, } } } impl Encodable for Receipt { fn rlp_append(&self, s: &mut RlpStream) { - if let Some(ref root) = self.state_root { + if let Some(ref status) = self.status_code { + s.begin_list(4); + s.append(status); + } else if let Some(ref root) = self.state_root { s.begin_list(4); s.append(root); } else { @@ -69,17 +75,27 @@ impl Decodable for Receipt { if rlp.item_count()? == 3 { Ok(Receipt { state_root: None, + status_code: None, gas_used: rlp.val_at(0)?, log_bloom: rlp.val_at(1)?, logs: rlp.list_at(2)?, }) } else { - Ok(Receipt { - state_root: Some(rlp.val_at(0)?), + let mut receipt = Receipt { gas_used: rlp.val_at(1)?, log_bloom: rlp.val_at(2)?, logs: rlp.list_at(3)?, - }) + state_root: None, + status_code: None, + }; + + let first = rlp.at(0)?; + if first.is_data() && first.data()?.len() == 1 { + receipt.status_code = Some(first.as_val()?); + } else { + receipt.state_root = Some(first.as_val()?); + } + Ok(receipt) } } } @@ -145,6 +161,7 @@ mod tests { fn test_no_state_root() { let expected = ::rustc_hex::FromHex::from_hex("f9014183040caeb9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000f838f794dcf421d093428b096ca501a7cd1a740855a7976fc0a00000000000000000000000000000000000000000000000000000000000000000").unwrap(); let r = Receipt::new( + None, None, 0x40cae.into(), vec![LogEntry { @@ -161,6 +178,7 @@ mod tests { let expected = ::rustc_hex::FromHex::from_hex("f90162a02f697d671e9ae4ee24a43c4b0d7e15f1cb4ba6de1561120d43b9a4e8c4a8a6ee83040caeb9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000f838f794dcf421d093428b096ca501a7cd1a740855a7976fc0a00000000000000000000000000000000000000000000000000000000000000000").unwrap(); let r = Receipt::new( Some("2f697d671e9ae4ee24a43c4b0d7e15f1cb4ba6de1561120d43b9a4e8c4a8a6ee".into()), + None, 0x40cae.into(), vec![LogEntry { address: "dcf421d093428b096ca501a7cd1a740855a7976f".into(), diff --git a/ethcore/vm/src/error.rs b/ethcore/vm/src/error.rs index 2c2c9a38d..fe8d7054c 100644 --- a/ethcore/vm/src/error.rs +++ b/ethcore/vm/src/error.rs @@ -65,6 +65,10 @@ pub enum Error { Internal(String), /// Wasm runtime error Wasm(String), + /// Out of bounds access in RETURNDATACOPY. + OutOfBounds, + /// Execution has been reverted with REVERT. + Reverted, } @@ -93,6 +97,8 @@ impl fmt::Display for Error { Internal(ref msg) => write!(f, "Internal error: {}", msg), MutableCallInStaticContext => write!(f, "Mutable call in static context"), Wasm(ref msg) => write!(f, "Internal error: {}", msg), + OutOfBounds => write!(f, "Out of bounds"), + Reverted => write!(f, "Reverted"), } } } diff --git a/ethcore/vm/src/ext.rs b/ethcore/vm/src/ext.rs index a4610b672..574af9e82 100644 --- a/ethcore/vm/src/ext.rs +++ b/ethcore/vm/src/ext.rs @@ -34,7 +34,12 @@ pub enum ContractCreateResult { Created(Address, U256), /// Returned when contract creation failed. /// VM doesn't have to know the reason. - Failed + Failed, + /// Returned when contract creation failed. + /// VM doesn't have to know the reason. + FailedInStaticCall, + /// Reverted with REVERT. + Reverted(U256, ReturnData), } /// Result of externalities call function. @@ -44,7 +49,10 @@ pub enum MessageCallResult { Success(U256, ReturnData), /// Returned when message call failed. /// VM doesn't have to know the reason. - Failed + Failed, + /// Returned when message call was reverted. + /// Contains gas left and output data. + Reverted(U256, ReturnData), } /// Specifies how an address is calculated for a new contract. @@ -114,7 +122,7 @@ pub trait Ext { /// Should be called when transaction calls `RETURN` opcode. /// Returns gas_left if cost of returning the data is not too high. - fn ret(self, gas: &U256, data: &ReturnData) -> Result; + fn ret(self, gas: &U256, data: &ReturnData, apply_state: bool) -> Result; /// Should be called when contract commits suicide. /// Address to which funds should be refunded. @@ -143,4 +151,7 @@ pub trait Ext { /// Trace the finalised execution of a single instruction. fn trace_executed(&mut self, _gas_used: U256, _stack_push: &[U256], _mem_diff: Option<(usize, &[u8])>, _store_diff: Option<(U256, U256)>) {} + + /// Check if running in static context. + fn is_static(&self) -> bool; } diff --git a/ethcore/vm/src/schedule.rs b/ethcore/vm/src/schedule.rs index 6966c26e6..04c97b044 100644 --- a/ethcore/vm/src/schedule.rs +++ b/ethcore/vm/src/schedule.rs @@ -111,6 +111,8 @@ pub struct Schedule { pub have_return_data: bool, /// Kill basic accounts below this balance if touched. pub kill_dust: CleanDustMode, + /// Enable EIP-86 rules + pub eip86: bool, } /// Dust accounts cleanup mode. @@ -184,17 +186,17 @@ impl Schedule { blockhash_gas: 20, have_static_call: false, kill_dust: CleanDustMode::Off, + eip86: false, } } - /// Schedule for the Metropolis of the Ethereum main net. - pub fn new_metropolis() -> Schedule { + /// Schedule for the Byzantium fork of the Ethereum main net. + pub fn new_byzantium() -> Schedule { let mut schedule = Self::new_post_eip150(24576, true, true, true); schedule.have_create2 = true; schedule.have_revert = true; schedule.have_static_call = true; schedule.have_return_data = true; - schedule.blockhash_gas = 350; schedule } @@ -246,6 +248,7 @@ impl Schedule { blockhash_gas: 20, have_static_call: false, kill_dust: CleanDustMode::Off, + eip86: false, } } } diff --git a/ethcore/vm/src/tests.rs b/ethcore/vm/src/tests.rs index f56975a9e..40c23f40c 100644 --- a/ethcore/vm/src/tests.rs +++ b/ethcore/vm/src/tests.rs @@ -164,7 +164,7 @@ impl Ext for FakeExt { Ok(()) } - fn ret(self, _gas: &U256, _data: &ReturnData) -> Result { + fn ret(self, _gas: &U256, _data: &ReturnData, _apply_state: bool) -> Result { unimplemented!(); } @@ -185,6 +185,10 @@ impl Ext for FakeExt { self.depth } + fn is_static(&self) -> bool { + false + } + fn inc_sstore_clears(&mut self) { self.sstore_clears += 1; } diff --git a/ethcore/wasm/src/runtime.rs b/ethcore/wasm/src/runtime.rs index 6ddaa7a10..8376d0f39 100644 --- a/ethcore/wasm/src/runtime.rs +++ b/ethcore/wasm/src/runtime.rs @@ -220,7 +220,16 @@ impl<'a, 'b> Runtime<'a, 'b> { vm::ContractCreateResult::Failed => { trace!(target: "wasm", "runtime: create contract fail"); Ok(Some((-1i32).into())) - } + }, + vm::ContractCreateResult::Reverted(gas_left, _) => { + trace!(target: "wasm", "runtime: create contract reverted"); + self.gas_counter = self.gas_limit - gas_left.low_u64(); + Ok(Some((-1i32).into())) + }, + vm::ContractCreateResult::FailedInStaticCall => { + trace!(target: "wasm", "runtime: create contract called in static context"); + Err(interpreter::Error::Trap("CREATE in static context".to_owned())) + }, } } @@ -323,6 +332,11 @@ impl<'a, 'b> Runtime<'a, 'b> { self.memory.set(result_ptr, &result)?; Ok(Some(0i32.into())) }, + vm::MessageCallResult::Reverted(gas_left, _) => { + self.gas_counter = self.gas_limit - gas_left.low_u64(); + self.memory.set(result_ptr, &result)?; + Ok(Some((-1i32).into())) + }, vm::MessageCallResult::Failed => { Ok(Some((-1i32).into())) } diff --git a/evmbin/src/main.rs b/evmbin/src/main.rs index 695349db3..58b4e983b 100644 --- a/evmbin/src/main.rs +++ b/evmbin/src/main.rs @@ -162,7 +162,7 @@ fn run_call(args: Args, mut informant: T) { informant.set_gas(gas); let result = info::run(&spec, gas, None, |mut client| { - client.call(params, &mut informant) + client.call(params, &mut informant).map(|r| (r.gas_left, r.return_data.to_vec())) }); T::finish(result); } diff --git a/json/src/blockchain/blockchain.rs b/json/src/blockchain/blockchain.rs index 07014db07..9edd75313 100644 --- a/json/src/blockchain/blockchain.rs +++ b/json/src/blockchain/blockchain.rs @@ -21,6 +21,7 @@ use hash::H256; use blockchain::state::State; use blockchain::header::Header; use blockchain::block::Block; +use state::test::ForkSpec; use spec::{Genesis, Seal, Ethereum}; /// Blockchain deserialization. @@ -42,7 +43,9 @@ pub struct BlockChain { pub pre_state: State, /// Hash of best block. #[serde(rename="lastblockhash")] - pub best_block: H256 + pub best_block: H256, + /// Network. + pub network: ForkSpec, } impl BlockChain { @@ -102,7 +105,7 @@ mod tests { "rlp" : "0xf90285f90219a0f052d217bd5275a5177a3c3b7debdfe2670f1c8394b2965ccd5c1883cc1a524da01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a0bac6177a79e910c98d86ec31a09ae37ac2de15b754fd7bed1ba52362c49416bfa0498785da562aa0c5dd5937cf15f22139b0b1bcf3b4fc48986e1bb1dae9292796a0c7778a7376099ee2e5c455791c1885b5c361b95713fddcbe32d97fd01334d296b90100000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000400000000000000000000000000000000000000000000000000000008302000001832fefba82560b8456850c2ca00102030405060708091011121314151617181920212223242526272829303132a05266ca43e81d25925a9ba573c3e4f9180bc076d316d90e63c6f8708b272f5ce28859ba4daed1898e21f866f864800a82c35094095e7baea6a6c7c4c2dfeb977efac326af552d8785012a05f200801ca0ee0b9ec878fbd4258a9473199d8ecc32996a20c323c004e79e0cda20e0418ce3a04e6bc63927d1510bab54f37e46fa036faf4b2c465d271920d9afea1fadf7bd21c0", "transactions" : [ { - "data" : "0x", + "data" : "0x00", "gasLimit" : "0xc350", "gasPrice" : "0x0a", "nonce" : "0x00", @@ -116,6 +119,7 @@ mod tests { "uncleHeaders" : [ ] }], + "network" : "Frontier", "genesisBlockHeader" : { "bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "coinbase" : "8888f1f195afa192cfee860698584c030f4c9db1", diff --git a/json/src/spec/builtin.rs b/json/src/spec/builtin.rs index 892bf532e..34e9a2df1 100644 --- a/json/src/spec/builtin.rs +++ b/json/src/spec/builtin.rs @@ -34,6 +34,15 @@ pub struct Modexp { pub divisor: usize, } +/// Pricing for alt_bn128_pairing. +#[derive(Debug, PartialEq, Deserialize, Clone)] +pub struct AltBn128Pairing { + /// Base price. + pub base: usize, + /// Price per point pair. + pub pair: usize, +} + /// Pricing variants. #[derive(Debug, PartialEq, Deserialize, Clone)] pub enum Pricing { @@ -43,6 +52,9 @@ pub enum Pricing { /// Pricing for modular exponentiation. #[serde(rename="modexp")] Modexp(Modexp), + /// Pricing for alt_bn128_pairing exponentiation. + #[serde(rename="alt_bn128_pairing")] + AltBn128Pairing(AltBn128Pairing), } /// Spec builtin. diff --git a/json/src/spec/ethash.rs b/json/src/spec/ethash.rs index 784a9d477..bfc6fe315 100644 --- a/json/src/spec/ethash.rs +++ b/json/src/spec/ethash.rs @@ -111,6 +111,18 @@ pub struct EthashParams { /// See main EthashParams docs. #[serde(rename="minGasPrice")] pub min_gas_price: Option, + + /// EIP-649 transition block. + #[serde(rename="eip649Transition")] + pub eip649_transition: Option, + + /// EIP-649 bomb delay. + #[serde(rename="eip649Delay")] + pub eip649_delay: Option, + + /// EIP-649 base reward. + #[serde(rename="eip649Reward")] + pub eip649_reward: Option, } /// Ethash engine deserialization. @@ -221,6 +233,9 @@ mod tests { max_gas_limit: None, min_gas_price_transition: None, min_gas_price: None, + eip649_transition: None, + eip649_delay: None, + eip649_reward: None, } }); } @@ -262,6 +277,9 @@ mod tests { max_gas_limit: None, min_gas_price_transition: None, min_gas_price: None, + eip649_transition: None, + eip649_delay: None, + eip649_reward: None, } }); } diff --git a/json/src/spec/params.rs b/json/src/spec/params.rs index 4561bcada..73c9e8d1b 100644 --- a/json/src/spec/params.rs +++ b/json/src/spec/params.rs @@ -85,6 +85,9 @@ pub struct Params { #[serde(rename="eip214Transition")] pub eip214_transition: Option, /// See `CommonParams` docs. + #[serde(rename="eip658Transition")] + pub eip658_transition: Option, + /// See `CommonParams` docs. #[serde(rename="dustProtectionTransition")] pub dust_protection_transition: Option, /// See `CommonParams` docs. diff --git a/json/src/state/test.rs b/json/src/state/test.rs index a63b8ee8d..3a25c007d 100644 --- a/json/src/state/test.rs +++ b/json/src/state/test.rs @@ -104,10 +104,12 @@ pub enum ForkSpec { EIP158, Frontier, Homestead, - // TODO [ToDr] Deprecated - Metropolis, Byzantium, Constantinople, + EIP158ToByzantiumAt5, + FrontierToHomesteadAt5, + HomesteadToDaoAt5, + HomesteadToEIP150At5, } /// State test indexes deserialization. diff --git a/json/src/vm/log.rs b/json/src/vm/log.rs deleted file mode 100644 index c406253bc..000000000 --- a/json/src/vm/log.rs +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright 2015-2017 Parity Technologies (UK) Ltd. -// This file is part of Parity. - -// Parity is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// Parity is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with Parity. If not, see . - -//! Vm log deserialization. - -use hash::{Address, H256, Bloom}; -use bytes::Bytes; - -/// Vm log deserialization. -#[derive(Debug, PartialEq, Deserialize)] -pub struct Log { - /// Log address. - pub address: Address, - /// Log bloom. - pub bloom: Bloom, - /// Data. - pub data: Bytes, - /// Topics. - pub topics: Vec, -} - -#[cfg(test)] -mod tests { - use serde_json; - use vm::Log; - - #[test] - fn log_deserialization() { - let s = r#"{ - "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", - "bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008800000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000800000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000", - "data" : "0xaabbffffffffffffffffffffffffffffffffffffffffffffffffffffffffccdd", - "topics" : [ - "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" - ] - }"#; - let _deserialized: Log = serde_json::from_str(s).unwrap(); - // TODO: validate all fields - } -} - diff --git a/json/src/vm/mod.rs b/json/src/vm/mod.rs index 8917d89db..a2588e37c 100644 --- a/json/src/vm/mod.rs +++ b/json/src/vm/mod.rs @@ -19,13 +19,11 @@ pub mod env; pub mod transaction; pub mod vm; -pub mod log; pub mod call; pub mod test; pub use self::env::Env; pub use self::transaction::Transaction; pub use self::vm::Vm; -pub use self::log::Log; pub use self::call::Call; pub use self::test::Test; diff --git a/json/src/vm/vm.rs b/json/src/vm/vm.rs index 36a19cdad..c7e33b609 100644 --- a/json/src/vm/vm.rs +++ b/json/src/vm/vm.rs @@ -18,8 +18,9 @@ use bytes::Bytes; use uint::Uint; +use hash::H256; use blockchain::State; -use vm::{Transaction, Log, Call, Env}; +use vm::{Transaction, Call, Env}; /// Reporesents vm execution environment before and after exeuction of transaction. #[derive(Debug, PartialEq, Deserialize)] @@ -35,8 +36,8 @@ pub struct Vm { /// Gas left after transaction execution. #[serde(rename="gas")] pub gas_left: Option, - /// Logs created during execution of transaction. - pub logs: Option>, + /// Hash of logs created during execution of transaction. + pub logs: Option, /// Transaction output. #[serde(rename="out")] pub output: Option, @@ -83,9 +84,9 @@ mod tests { "value" : "0x0de0b6b3a7640000" }, "gas" : "0x013874", - "logs" : [ - ], + "logs" : "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", "out" : "0x", + "network" : "Frontier", "post" : { "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { "balance" : "0x0de0b6b3a7640000", diff --git a/rpc/src/v1/tests/eth.rs b/rpc/src/v1/tests/eth.rs index c7a580c58..4563f76e3 100644 --- a/rpc/src/v1/tests/eth.rs +++ b/rpc/src/v1/tests/eth.rs @@ -28,6 +28,7 @@ use ethcore::ethereum; use ethcore::miner::{MinerOptions, Banning, GasPricer, MinerService, ExternalMiner, Miner, PendingSet, PrioritizationStrategy, GasLimit}; use ethcore::account_provider::AccountProvider; use ethjson::blockchain::BlockChain; +use ethjson::state::test::ForkSpec; use io::IoChannel; use bigint::prelude::U256; use bigint::hash::H256; @@ -168,13 +169,13 @@ impl EthTester { #[test] fn harness_works() { - let chain: BlockChain = extract_chain!("BlockchainTests/bcUncleTest"); + let chain: BlockChain = extract_chain!("BlockchainTests/bcWalletTest/wallet2outOf3txs"); let _ = EthTester::from_chain(&chain); } #[test] fn eth_get_balance() { - let chain = extract_chain!("BlockchainTests/bcWalletTest", "wallet2outOf3txs"); + let chain = extract_chain!("BlockchainTests/bcWalletTest/wallet2outOf3txs"); let tester = EthTester::from_chain(&chain); // final account state let req_latest = r#"{ @@ -200,7 +201,7 @@ fn eth_get_balance() { #[test] fn eth_block_number() { - let chain = extract_chain!("BlockchainTests/bcRPC_API_Test"); + let chain = extract_chain!("BlockchainTests/bcGasPricerTest/RPC_API_Test"); let tester = EthTester::from_chain(&chain); let req_number = r#"{ "jsonrpc": "2.0", @@ -215,11 +216,11 @@ fn eth_block_number() { #[test] fn eth_get_block() { - let chain = extract_chain!("BlockchainTests/bcRPC_API_Test"); + let chain = extract_chain!("BlockchainTests/bcGasPricerTest/RPC_API_Test"); let tester = EthTester::from_chain(&chain); let req_block = r#"{"method":"eth_getBlockByNumber","params":["0x0",false],"id":1,"jsonrpc":"2.0"}"#; - let res_block = r#"{"jsonrpc":"2.0","result":{"author":"0x8888f1f195afa192cfee860698584c030f4c9db1","difficulty":"0x20000","extraData":"0x42","gasLimit":"0x2fefd8","gasUsed":"0x0","hash":"0x5a39ed1020c04d4d84539975b893a4e7c53eab6c2965db8bc3468093a31bc5ae","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","miner":"0x8888f1f195afa192cfee860698584c030f4c9db1","mixHash":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","nonce":"0x0102030405060708","number":"0x0","parentHash":"0x0000000000000000000000000000000000000000000000000000000000000000","receiptsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","sealFields":["0xa056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","0x880102030405060708"],"sha3Uncles":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","size":"0x1ff","stateRoot":"0x7dba07d6b448a186e9612e5f737d1c909dce473e53199901a302c00646d523c1","timestamp":"0x54c98c81","totalDifficulty":"0x20000","transactions":[],"transactionsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","uncles":[]},"id":1}"#.to_owned(); + let res_block = r#"{"jsonrpc":"2.0","result":{"author":"0x8888f1f195afa192cfee860698584c030f4c9db1","difficulty":"0x20000","extraData":"0x42","gasLimit":"0x1df5d44","gasUsed":"0x0","hash":"0xcded1bc807465a72e2d54697076ab858f28b15d4beaae8faa47339c8eee386a3","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","miner":"0x8888f1f195afa192cfee860698584c030f4c9db1","mixHash":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","nonce":"0x0102030405060708","number":"0x0","parentHash":"0x0000000000000000000000000000000000000000000000000000000000000000","receiptsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","sealFields":["0xa056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","0x880102030405060708"],"sha3Uncles":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","size":"0x200","stateRoot":"0x7dba07d6b448a186e9612e5f737d1c909dce473e53199901a302c00646d523c1","timestamp":"0x54c98c81","totalDifficulty":"0x20000","transactions":[],"transactionsRoot":"0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421","uncles":[]},"id":1}"#; assert_eq!(tester.handler.handle_request_sync(req_block).unwrap(), res_block); } @@ -465,6 +466,6 @@ fn starting_nonce_test() { assert_eq!(r#"{"jsonrpc":"2.0","result":"0x100","id":15}"#, &sample); } -register_test!(eth_transaction_count_1, verify_transaction_counts, "BlockchainTests/bcWalletTest"); -register_test!(eth_transaction_count_2, verify_transaction_counts, "BlockchainTests/bcTotalDifficultyTest"); -register_test!(eth_transaction_count_3, verify_transaction_counts, "BlockchainTests/bcGasPricerTest"); +register_test!(eth_transaction_count_1, verify_transaction_counts, "BlockchainTests/bcWalletTest/wallet2outOf3txs"); +register_test!(eth_transaction_count_2, verify_transaction_counts, "BlockchainTests/bcTotalDifficultyTest/sideChainWithMoreTransactions"); +register_test!(eth_transaction_count_3, verify_transaction_counts, "BlockchainTests/bcGasPricerTest/RPC_API_Test"); diff --git a/rpc/src/v1/tests/mod.rs b/rpc/src/v1/tests/mod.rs index a48727475..31ac1c541 100644 --- a/rpc/src/v1/tests/mod.rs +++ b/rpc/src/v1/tests/mod.rs @@ -19,19 +19,8 @@ macro_rules! extract_chain { ::ethjson::blockchain::Test::load(RAW_DATA).unwrap().into_iter() }}; - ($file:expr, $name:expr) => {{ - let mut chain = None; - for (name, c) in extract_chain!(iter $file) { - if name == $name { - chain = Some(c); - break; - } - } - chain.unwrap() - }}; - ($file:expr) => {{ - extract_chain!(iter $file).next().unwrap().1 + extract_chain!(iter $file).filter(|&(_, ref t)| t.network == ForkSpec::Frontier).next().unwrap().1 }}; } @@ -39,27 +28,7 @@ macro_rules! register_test { ($name:ident, $cb:expr, $file:expr) => { #[test] fn $name() { - for (name, chain) in extract_chain!(iter $file) { - $cb(name, chain); - } - } - }; - - (heavy $name:ident, $cb:expr, $file:expr) => { - #[test] - #[cfg(feature = "test-heavy")] - fn $name() { - for (name, chain) in extract_chain!(iter $file) { - $cb(name, chain); - } - } - }; - - (ignore $name:ident, $cb:expr, $file:expr) => { - #[test] - #[ignore] - fn $name() { - for (name, chain) in extract_chain!(iter $file) { + for (name, chain) in extract_chain!(iter $file).filter(|&(_, ref t)| t.network == ForkSpec::Frontier) { $cb(name, chain); } }