new ethabi (#9511)

* new ethabi migration in progress

* parity migrated to new ethabi

* migrated secred-store to new ethabi

* bump ethabi to 6.0

* fixed review suggestions
This commit is contained in:
Marek Kotewicz 2018-09-13 11:04:39 +02:00 committed by GitHub
parent 7dfb5ff5bd
commit ef4a61c769
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
23 changed files with 458 additions and 575 deletions

89
Cargo.lock generated
View File

@ -456,7 +456,7 @@ dependencies = [
[[package]] [[package]]
name = "ethabi" name = "ethabi"
version = "5.1.2" version = "6.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
@ -470,18 +470,18 @@ dependencies = [
[[package]] [[package]]
name = "ethabi-contract" name = "ethabi-contract"
version = "5.1.1" version = "6.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
name = "ethabi-derive" name = "ethabi-derive"
version = "5.1.3" version = "6.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [ dependencies = [
"ethabi 5.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "ethabi 6.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
"heck 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "heck 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 0.12.15 (registry+https://github.com/rust-lang/crates.io-index)", "syn 0.13.11 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]] [[package]]
@ -522,9 +522,9 @@ dependencies = [
"common-types 0.1.0", "common-types 0.1.0",
"crossbeam 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
"error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
"ethabi 5.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "ethabi 6.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
"ethabi-contract 5.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "ethabi-contract 6.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"ethabi-derive 5.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "ethabi-derive 6.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
"ethash 1.12.0", "ethash 1.12.0",
"ethcore-bloom-journal 0.1.0", "ethcore-bloom-journal 0.1.0",
"ethcore-io 1.12.0", "ethcore-io 1.12.0",
@ -747,9 +747,9 @@ name = "ethcore-private-tx"
version = "1.0.0" version = "1.0.0"
dependencies = [ dependencies = [
"error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
"ethabi 5.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "ethabi 6.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
"ethabi-contract 5.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "ethabi-contract 6.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"ethabi-derive 5.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "ethabi-derive 6.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
"ethcore 1.12.0", "ethcore 1.12.0",
"ethcore-io 1.12.0", "ethcore-io 1.12.0",
"ethcore-logger 1.12.0", "ethcore-logger 1.12.0",
@ -785,9 +785,9 @@ name = "ethcore-secretstore"
version = "1.0.0" version = "1.0.0"
dependencies = [ dependencies = [
"byteorder 1.2.6 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 1.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
"ethabi 5.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "ethabi 6.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
"ethabi-contract 5.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "ethabi-contract 6.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"ethabi-derive 5.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "ethabi-derive 6.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
"ethcore 1.12.0", "ethcore 1.12.0",
"ethcore-logger 1.12.0", "ethcore-logger 1.12.0",
"ethcore-sync 1.12.0", "ethcore-sync 1.12.0",
@ -1863,9 +1863,9 @@ dependencies = [
name = "node-filter" name = "node-filter"
version = "1.12.0" version = "1.12.0"
dependencies = [ dependencies = [
"ethabi 5.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "ethabi 6.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
"ethabi-contract 5.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "ethabi-contract 6.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"ethabi-derive 5.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "ethabi-derive 6.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
"ethcore 1.12.0", "ethcore 1.12.0",
"ethcore-io 1.12.0", "ethcore-io 1.12.0",
"ethcore-network 1.12.0", "ethcore-network 1.12.0",
@ -2097,9 +2097,9 @@ dependencies = [
name = "parity-hash-fetch" name = "parity-hash-fetch"
version = "1.12.0" version = "1.12.0"
dependencies = [ dependencies = [
"ethabi 5.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "ethabi 6.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
"ethabi-contract 5.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "ethabi-contract 6.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"ethabi-derive 5.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "ethabi-derive 6.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
"ethereum-types 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "ethereum-types 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"fake-fetch 0.0.1", "fake-fetch 0.0.1",
"fetch 0.1.0", "fetch 0.1.0",
@ -2313,9 +2313,9 @@ dependencies = [
name = "parity-updater" name = "parity-updater"
version = "1.12.0" version = "1.12.0"
dependencies = [ dependencies = [
"ethabi 5.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "ethabi 6.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
"ethabi-contract 5.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "ethabi-contract 6.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"ethabi-derive 5.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "ethabi-derive 6.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
"ethcore 1.12.0", "ethcore 1.12.0",
"ethcore-sync 1.12.0", "ethcore-sync 1.12.0",
"ethereum-types 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "ethereum-types 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
@ -2563,14 +2563,6 @@ dependencies = [
"smallvec 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]]
name = "proc-macro2"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]] [[package]]
name = "proc-macro2" name = "proc-macro2"
version = "0.3.8" version = "0.3.8"
@ -2631,14 +2623,6 @@ name = "quick-error"
version = "1.2.2" version = "1.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "quote"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"proc-macro2 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]] [[package]]
name = "quote" name = "quote"
version = "0.5.2" version = "0.5.2"
@ -2770,9 +2754,9 @@ dependencies = [
name = "registrar" name = "registrar"
version = "0.0.1" version = "0.0.1"
dependencies = [ dependencies = [
"ethabi 5.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "ethabi 6.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
"ethabi-contract 5.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "ethabi-contract 6.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"ethabi-derive 5.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "ethabi-derive 6.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
"futures 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)",
"keccak-hash 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "keccak-hash 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
@ -3103,16 +3087,6 @@ name = "strsim"
version = "0.7.0" version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "syn"
version = "0.12.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"proc-macro2 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
"unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]] [[package]]
name = "syn" name = "syn"
version = "0.13.11" version = "0.13.11"
@ -3960,9 +3934,9 @@ dependencies = [
"checksum error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ff511d5dc435d703f4971bc399647c9bc38e20cb41452e3b9feb4765419ed3f3" "checksum error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ff511d5dc435d703f4971bc399647c9bc38e20cb41452e3b9feb4765419ed3f3"
"checksum error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "07e791d3be96241c77c43846b665ef1384606da2cd2a48730abe606a12906e02" "checksum error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "07e791d3be96241c77c43846b665ef1384606da2cd2a48730abe606a12906e02"
"checksum eth-secp256k1 0.5.7 (git+https://github.com/paritytech/rust-secp256k1)" = "<none>" "checksum eth-secp256k1 0.5.7 (git+https://github.com/paritytech/rust-secp256k1)" = "<none>"
"checksum ethabi 5.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "cf28f7a4a82229af21a4b2233eb411c459034010ad524976c4fb4556c5969b5b" "checksum ethabi 6.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "36c7bf66bd7ff02c3bc512a276a0f95300e3abb87060704fddf588ae11b86d99"
"checksum ethabi-contract 5.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7311354f2a46a4b564004047bf8dce9a57cbd8d7ce30021a56bd1a975baaf2f9" "checksum ethabi-contract 6.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "795e25fd868e12a59ca235dbe1f6cc8f1eba8f67d6a39438b29535e0126e0c27"
"checksum ethabi-derive 5.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7caf91e5d37033970be4a66cdef1e5e267af1c999e48b78d6ba86564c1081fab" "checksum ethabi-derive 6.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6853ea4d3aa9ee8cda9252c7e3f3080e6af58796e9ae3d8cfd90d3f03f6c0fb9"
"checksum ethbloom 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1a93a43ce2e9f09071449da36bfa7a1b20b950ee344b6904ff23de493b03b386" "checksum ethbloom 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1a93a43ce2e9f09071449da36bfa7a1b20b950ee344b6904ff23de493b03b386"
"checksum ethereum-types 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "35b3c5a18bc5e73a32a110ac743ec04b02bbbcd3b71d3118d40a6113d509378a" "checksum ethereum-types 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "35b3c5a18bc5e73a32a110ac743ec04b02bbbcd3b71d3118d40a6113d509378a"
"checksum ethereum-types-serialize 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4ac59a21a9ce98e188f3dace9eb67a6c4a3c67ec7fbc7218cb827852679dc002" "checksum ethereum-types-serialize 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4ac59a21a9ce98e188f3dace9eb67a6c4a3c67ec7fbc7218cb827852679dc002"
@ -4084,14 +4058,12 @@ dependencies = [
"checksum primal-check 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8e65f96c0a171f887198c274392c99a116ef65aa7f53f3b6d4902f493965c2d1" "checksum primal-check 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8e65f96c0a171f887198c274392c99a116ef65aa7f53f3b6d4902f493965c2d1"
"checksum primal-estimate 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "56ea4531dde757b56906493c8604641da14607bf9cdaa80fb9c9cabd2429f8d5" "checksum primal-estimate 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "56ea4531dde757b56906493c8604641da14607bf9cdaa80fb9c9cabd2429f8d5"
"checksum primal-sieve 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)" = "da2d6ed369bb4b0273aeeb43f07c105c0117717cbae827b20719438eb2eb798c" "checksum primal-sieve 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)" = "da2d6ed369bb4b0273aeeb43f07c105c0117717cbae827b20719438eb2eb798c"
"checksum proc-macro2 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "cd07deb3c6d1d9ff827999c7f9b04cdfd66b1b17ae508e14fe47b620f2282ae0"
"checksum proc-macro2 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "1b06e2f335f48d24442b35a19df506a835fb3547bc3c06ef27340da9acf5cae7" "checksum proc-macro2 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "1b06e2f335f48d24442b35a19df506a835fb3547bc3c06ef27340da9acf5cae7"
"checksum proc-macro2 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)" = "ee5697238f0d893c7f0ecc59c0999f18d2af85e424de441178bcacc9f9e6cf67" "checksum proc-macro2 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)" = "ee5697238f0d893c7f0ecc59c0999f18d2af85e424de441178bcacc9f9e6cf67"
"checksum protobuf 1.7.4 (registry+https://github.com/rust-lang/crates.io-index)" = "52fbc45bf6709565e44ef31847eb7407b3c3c80af811ee884a04da071dcca12b" "checksum protobuf 1.7.4 (registry+https://github.com/rust-lang/crates.io-index)" = "52fbc45bf6709565e44ef31847eb7407b3c3c80af811ee884a04da071dcca12b"
"checksum pulldown-cmark 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8361e81576d2e02643b04950e487ec172b687180da65c731c03cf336784e6c07" "checksum pulldown-cmark 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8361e81576d2e02643b04950e487ec172b687180da65c731c03cf336784e6c07"
"checksum pwasm-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "90d2b3c5bf24275fc77db6b14ec00a7a085d8ff9d1c4215fb6f6263e8d7b01bc" "checksum pwasm-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "90d2b3c5bf24275fc77db6b14ec00a7a085d8ff9d1c4215fb6f6263e8d7b01bc"
"checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0" "checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0"
"checksum quote 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1eca14c727ad12702eb4b6bfb5a232287dcf8385cb8ca83a3eeaf6519c44c408"
"checksum quote 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9949cfe66888ffe1d53e6ec9d9f3b70714083854be20fd5e271b232a017401e8" "checksum quote 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9949cfe66888ffe1d53e6ec9d9f3b70714083854be20fd5e271b232a017401e8"
"checksum quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)" = "dd636425967c33af890042c483632d33fa7a18f19ad1d7ea72e8998c6ef8dea5" "checksum quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)" = "dd636425967c33af890042c483632d33fa7a18f19ad1d7ea72e8998c6ef8dea5"
"checksum rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)" = "15a732abf9d20f0ad8eeb6f909bf6868722d9a06e1e50802b6a70351f40b4eb1" "checksum rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)" = "15a732abf9d20f0ad8eeb6f909bf6868722d9a06e1e50802b6a70351f40b4eb1"
@ -4146,7 +4118,6 @@ dependencies = [
"checksum stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8" "checksum stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8"
"checksum strsim 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b4d15c810519a91cf877e7e36e63fe068815c678181439f2f29e2562147c3694" "checksum strsim 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b4d15c810519a91cf877e7e36e63fe068815c678181439f2f29e2562147c3694"
"checksum strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4f380125926a99e52bc279241539c018323fab05ad6368b56f93d9369ff550" "checksum strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4f380125926a99e52bc279241539c018323fab05ad6368b56f93d9369ff550"
"checksum syn 0.12.15 (registry+https://github.com/rust-lang/crates.io-index)" = "c97c05b8ebc34ddd6b967994d5c6e9852fa92f8b82b3858c39451f97346dcce5"
"checksum syn 0.13.11 (registry+https://github.com/rust-lang/crates.io-index)" = "14f9bf6292f3a61d2c716723fdb789a41bbe104168e6f496dc6497e531ea1b9b" "checksum syn 0.13.11 (registry+https://github.com/rust-lang/crates.io-index)" = "14f9bf6292f3a61d2c716723fdb789a41bbe104168e6f496dc6497e531ea1b9b"
"checksum syn 0.14.9 (registry+https://github.com/rust-lang/crates.io-index)" = "261ae9ecaa397c42b960649561949d69311f08eeaea86a65696e6e46517cf741" "checksum syn 0.14.9 (registry+https://github.com/rust-lang/crates.io-index)" = "261ae9ecaa397c42b960649561949d69311f08eeaea86a65696e6e46517cf741"
"checksum take 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b157868d8ac1f56b64604539990685fa7611d8fa9e5476cf0c02cf34d32917c5" "checksum take 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b157868d8ac1f56b64604539990685fa7611d8fa9e5476cf0c02cf34d32917c5"

View File

@ -29,9 +29,9 @@ ethcore-stratum = { path = "./stratum", optional = true }
ethcore-transaction = { path = "./transaction" } ethcore-transaction = { path = "./transaction" }
ethereum-types = "0.4" ethereum-types = "0.4"
memory-cache = { path = "../util/memory_cache" } memory-cache = { path = "../util/memory_cache" }
ethabi = "5.1.2" ethabi = "6.0"
ethabi-derive = "5.1.3" ethabi-derive = "6.0"
ethabi-contract = "5.1.1" ethabi-contract = "6.0"
ethjson = { path = "../json" } ethjson = { path = "../json" }
ethkey = { path = "../ethkey" } ethkey = { path = "../ethkey" }
ethstore = { path = "../ethstore" } ethstore = { path = "../ethstore" }

View File

@ -13,9 +13,9 @@ ethcore-network-devp2p = { path = "../../util/network-devp2p" }
ethereum-types = "0.4" ethereum-types = "0.4"
log = "0.4" log = "0.4"
parking_lot = "0.6" parking_lot = "0.6"
ethabi = "5.1.2" ethabi = "6.0"
ethabi-derive = "5.1.3" ethabi-derive = "6.0"
ethabi-contract = "5.1.1" ethabi-contract = "6.0"
lru-cache = "0.1" lru-cache = "0.1"
[dev-dependencies] [dev-dependencies]

View File

@ -44,16 +44,16 @@ use parking_lot::Mutex;
use ethcore::client::{BlockChainClient, BlockId}; use ethcore::client::{BlockChainClient, BlockId};
use ethereum_types::{H256, Address}; use ethereum_types::{H256, Address};
use ethabi::FunctionOutputDecoder;
use network::{ConnectionFilter, ConnectionDirection}; use network::{ConnectionFilter, ConnectionDirection};
use devp2p::NodeId; use devp2p::NodeId;
use_contract!(peer_set, "PeerSet", "res/peer_set.json"); use_contract!(peer_set, "res/peer_set.json");
const MAX_CACHE_SIZE: usize = 4096; const MAX_CACHE_SIZE: usize = 4096;
/// Connection filter that uses a contract to manage permissions. /// Connection filter that uses a contract to manage permissions.
pub struct NodeFilter { pub struct NodeFilter {
contract: peer_set::PeerSet,
client: Weak<BlockChainClient>, client: Weak<BlockChainClient>,
contract_address: Address, contract_address: Address,
permission_cache: Mutex<LruCache<(H256, NodeId), bool>>, permission_cache: Mutex<LruCache<(H256, NodeId), bool>>,
@ -63,7 +63,6 @@ impl NodeFilter {
/// Create a new instance. Accepts a contract address. /// Create a new instance. Accepts a contract address.
pub fn new(client: Weak<BlockChainClient>, contract_address: Address) -> NodeFilter { pub fn new(client: Weak<BlockChainClient>, contract_address: Address) -> NodeFilter {
NodeFilter { NodeFilter {
contract: peer_set::PeerSet::default(),
client, client,
contract_address, contract_address,
permission_cache: Mutex::new(LruCache::new(MAX_CACHE_SIZE)), permission_cache: Mutex::new(LruCache::new(MAX_CACHE_SIZE)),
@ -96,9 +95,9 @@ impl ConnectionFilter for NodeFilter {
let id_low = H256::from_slice(&connecting_id[0..32]); let id_low = H256::from_slice(&connecting_id[0..32]);
let id_high = H256::from_slice(&connecting_id[32..64]); let id_high = H256::from_slice(&connecting_id[32..64]);
let allowed = self.contract.functions() let (data, decoder) = peer_set::functions::connection_allowed::call(own_low, own_high, id_low, id_high);
.connection_allowed() let allowed = client.call_contract(BlockId::Latest, address, data)
.call(own_low, own_high, id_low, id_high, &|data| client.call_contract(BlockId::Latest, address, data)) .and_then(|value| decoder.decode(&value).map_err(|e| e.to_string()))
.unwrap_or_else(|e| { .unwrap_or_else(|e| {
debug!("Error callling peer set contract: {:?}", e); debug!("Error callling peer set contract: {:?}", e);
false false

View File

@ -7,9 +7,9 @@ authors = ["Parity Technologies <admin@parity.io>"]
[dependencies] [dependencies]
error-chain = { version = "0.12", default-features = false } error-chain = { version = "0.12", default-features = false }
ethabi = "5.1.2" ethabi = "6.0"
ethabi-derive = "5.1.3" ethabi-derive = "6.0"
ethabi-contract = "5.1.1" ethabi-contract = "6.0"
ethcore = { path = ".." } ethcore = { path = ".." }
parity-bytes = "0.1" parity-bytes = "0.1"
parity-crypto = "0.1" parity-crypto = "0.1"

View File

@ -89,11 +89,12 @@ use ethcore::miner::{self, Miner, MinerService, pool_client::NonceCache};
use ethcore::trace::{Tracer, VMTracer}; use ethcore::trace::{Tracer, VMTracer};
use rustc_hex::FromHex; use rustc_hex::FromHex;
use ethkey::Password; use ethkey::Password;
use ethabi::FunctionOutputDecoder;
// Source avaiable at https://github.com/parity-contracts/private-tx/blob/master/contracts/PrivateContract.sol // Source avaiable at https://github.com/parity-contracts/private-tx/blob/master/contracts/PrivateContract.sol
const DEFAULT_STUB_CONTRACT: &'static str = include_str!("../res/private.evm"); const DEFAULT_STUB_CONTRACT: &'static str = include_str!("../res/private.evm");
use_contract!(private, "PrivateContract", "res/private.json"); use_contract!(private_contract, "res/private.json");
/// Initialization vector length. /// Initialization vector length.
const INIT_VEC_LEN: usize = 16; const INIT_VEC_LEN: usize = 16;
@ -425,31 +426,23 @@ impl Provider where {
} }
fn get_decrypted_state(&self, address: &Address, block: BlockId) -> Result<Bytes, Error> { fn get_decrypted_state(&self, address: &Address, block: BlockId) -> Result<Bytes, Error> {
let contract = private::PrivateContract::default(); let (data, decoder) = private_contract::functions::state::call();
let state = contract.functions() let value = self.client.call_contract(block, *address, data)?;
.state() let state = decoder.decode(&value).map_err(|e| ErrorKind::Call(format!("Contract call failed {:?}", e)))?;
.call(&|data| self.client.call_contract(block, *address, data))
.map_err(|e| ErrorKind::Call(format!("Contract call failed {:?}", e)))?;
self.decrypt(address, &state) self.decrypt(address, &state)
} }
fn get_decrypted_code(&self, address: &Address, block: BlockId) -> Result<Bytes, Error> { fn get_decrypted_code(&self, address: &Address, block: BlockId) -> Result<Bytes, Error> {
let contract = private::PrivateContract::default(); let (data, decoder) = private_contract::functions::code::call();
let code = contract.functions() let value = self.client.call_contract(block, *address, data)?;
.code() let state = decoder.decode(&value).map_err(|e| ErrorKind::Call(format!("Contract call failed {:?}", e)))?;
.call(&|data| self.client.call_contract(block, *address, data)) self.decrypt(address, &state)
.map_err(|e| ErrorKind::Call(format!("Contract call failed {:?}", e)))?;
self.decrypt(address, &code)
} }
pub fn get_contract_nonce(&self, address: &Address, block: BlockId) -> Result<U256, Error> { pub fn get_contract_nonce(&self, address: &Address, block: BlockId) -> Result<U256, Error> {
let contract = private::PrivateContract::default(); let (data, decoder) = private_contract::functions::nonce::call();
Ok(contract.functions() let value = self.client.call_contract(block, *address, data)?;
.nonce() decoder.decode(&value).map_err(|e| ErrorKind::Call(format!("Contract call failed {:?}", e)).into())
.call(&|data| self.client.call_contract(block, *address, data))
.map_err(|e| ErrorKind::Call(format!("Contract call failed {:?}", e)))?)
} }
fn snapshot_to_storage(raw: Bytes) -> HashMap<H256, H256> { fn snapshot_to_storage(raw: Bytes) -> HashMap<H256, H256> {
@ -524,13 +517,11 @@ impl Provider where {
fn generate_constructor(validators: &[Address], code: Bytes, storage: Bytes) -> Bytes { fn generate_constructor(validators: &[Address], code: Bytes, storage: Bytes) -> Bytes {
let constructor_code = DEFAULT_STUB_CONTRACT.from_hex().expect("Default contract code is valid"); let constructor_code = DEFAULT_STUB_CONTRACT.from_hex().expect("Default contract code is valid");
let private = private::PrivateContract::default(); private_contract::constructor(constructor_code, validators.iter().map(|a| *a).collect::<Vec<Address>>(), code, storage)
private.constructor(constructor_code, validators.iter().map(|a| *a).collect::<Vec<Address>>(), code, storage)
} }
fn generate_set_state_call(signatures: &[Signature], storage: Bytes) -> Bytes { fn generate_set_state_call(signatures: &[Signature], storage: Bytes) -> Bytes {
let private = private::PrivateContract::default(); private_contract::functions::set_state::encode_input(
private.functions().set_state().input(
storage, storage,
signatures.iter().map(|s| { signatures.iter().map(|s| {
let mut v: [u8; 32] = [0; 32]; let mut v: [u8; 32] = [0; 32];
@ -604,11 +595,9 @@ impl Provider where {
/// Returns private validators for a contract. /// Returns private validators for a contract.
pub fn get_validators(&self, block: BlockId, address: &Address) -> Result<Vec<Address>, Error> { pub fn get_validators(&self, block: BlockId, address: &Address) -> Result<Vec<Address>, Error> {
let contract = private::PrivateContract::default(); let (data, decoder) = private_contract::functions::get_validators::call();
Ok(contract.functions() let value = self.client.call_contract(block, *address, data)?;
.get_validators() decoder.decode(&value).map_err(|e| ErrorKind::Call(format!("Contract call failed {:?}", e)).into())
.call(&|data| self.client.call_contract(block, *address, data))
.map_err(|e| ErrorKind::Call(format!("Contract call failed {:?}", e)))?)
} }
} }

View File

@ -86,7 +86,7 @@ pub use types::block_status::BlockStatus;
pub use blockchain::CacheSize as BlockChainCacheSize; pub use blockchain::CacheSize as BlockChainCacheSize;
pub use verification::QueueInfo as BlockQueueInfo; pub use verification::QueueInfo as BlockQueueInfo;
use_contract!(registry, "Registry", "res/contracts/registrar.json"); use_contract!(registry, "res/contracts/registrar.json");
const MAX_ANCIENT_BLOCKS_QUEUE_SIZE: usize = 4096; const MAX_ANCIENT_BLOCKS_QUEUE_SIZE: usize = 4096;
// Max number of blocks imported at once. // Max number of blocks imported at once.
@ -232,8 +232,6 @@ pub struct Client {
/// An action to be done if a mode/spec_name change happens /// An action to be done if a mode/spec_name change happens
on_user_defaults_change: Mutex<Option<Box<FnMut(Option<Mode>) + 'static + Send>>>, on_user_defaults_change: Mutex<Option<Box<FnMut(Option<Mode>) + 'static + Send>>>,
/// Link to a registry object useful for looking up names
registrar: registry::Registry,
registrar_address: Option<Address>, registrar_address: Option<Address>,
/// A closure to call when we want to restart the client /// A closure to call when we want to restart the client
@ -776,7 +774,6 @@ impl Client {
factories: factories, factories: factories,
history: history, history: history,
on_user_defaults_change: Mutex::new(None), on_user_defaults_change: Mutex::new(None),
registrar: registry::Registry::default(),
registrar_address, registrar_address,
exit_handler: Mutex::new(None), exit_handler: Mutex::new(None),
importer, importer,
@ -1365,17 +1362,17 @@ impl BlockChainTrait for Client {}
impl RegistryInfo for Client { impl RegistryInfo for Client {
fn registry_address(&self, name: String, block: BlockId) -> Option<Address> { fn registry_address(&self, name: String, block: BlockId) -> Option<Address> {
use ethabi::FunctionOutputDecoder;
let address = self.registrar_address?; let address = self.registrar_address?;
self.registrar.functions() let (data, decoder) = registry::functions::get_address::call(keccak(name.as_bytes()), "A");
.get_address() let value = decoder.decode(&self.call_contract(block, address, data).ok()?).ok()?;
.call(keccak(name.as_bytes()), "A", &|data| self.call_contract(block, address, data)) if value.is_zero() {
.ok() None
.and_then(|a| if a.is_zero() { } else {
None Some(value)
} else { }
Some(a)
})
} }
} }

View File

@ -30,7 +30,7 @@ use trace;
use types::BlockNumber; use types::BlockNumber;
use super::{SystemOrCodeCall, SystemOrCodeCallKind}; use super::{SystemOrCodeCall, SystemOrCodeCallKind};
use_contract!(block_reward_contract, "BlockReward", "res/contracts/block_reward.json"); use_contract!(block_reward_contract, "res/contracts/block_reward.json");
/// The kind of block reward. /// The kind of block reward.
/// Depending on the consensus engine the allocated block reward might have /// Depending on the consensus engine the allocated block reward might have
@ -81,7 +81,6 @@ impl Into<trace::RewardType> for RewardKind {
#[derive(PartialEq, Debug)] #[derive(PartialEq, Debug)]
pub struct BlockRewardContract { pub struct BlockRewardContract {
kind: SystemOrCodeCallKind, kind: SystemOrCodeCallKind,
block_reward_contract: block_reward_contract::BlockReward,
} }
impl BlockRewardContract { impl BlockRewardContract {
@ -89,7 +88,6 @@ impl BlockRewardContract {
pub fn new(kind: SystemOrCodeCallKind) -> BlockRewardContract { pub fn new(kind: SystemOrCodeCallKind) -> BlockRewardContract {
BlockRewardContract { BlockRewardContract {
kind, kind,
block_reward_contract: block_reward_contract::BlockReward::default(),
} }
} }
@ -114,9 +112,7 @@ impl BlockRewardContract {
beneficiaries: &[(Address, RewardKind)], beneficiaries: &[(Address, RewardKind)],
caller: &mut SystemOrCodeCall, caller: &mut SystemOrCodeCall,
) -> Result<Vec<(Address, U256)>, Error> { ) -> Result<Vec<(Address, U256)>, Error> {
let reward = self.block_reward_contract.functions().reward(); let input = block_reward_contract::functions::reward::encode_input(
let input = reward.input(
beneficiaries.iter().map(|&(address, _)| H160::from(address)), beneficiaries.iter().map(|&(address, _)| H160::from(address)),
beneficiaries.iter().map(|&(_, ref reward_kind)| u16::from(*reward_kind)), beneficiaries.iter().map(|&(_, ref reward_kind)| u16::from(*reward_kind)),
); );

View File

@ -30,13 +30,12 @@ use machine::{AuxiliaryData, Call, EthereumMachine};
use super::{ValidatorSet, SimpleList, SystemCall}; use super::{ValidatorSet, SimpleList, SystemCall};
use super::safe_contract::ValidatorSafeContract; use super::safe_contract::ValidatorSafeContract;
use_contract!(validator_report, "ValidatorReport", "res/contracts/validator_report.json"); use_contract!(validator_report, "res/contracts/validator_report.json");
/// A validator contract with reporting. /// A validator contract with reporting.
pub struct ValidatorContract { pub struct ValidatorContract {
contract_address: Address, contract_address: Address,
validators: ValidatorSafeContract, validators: ValidatorSafeContract,
provider: validator_report::ValidatorReport,
client: RwLock<Option<Weak<EngineClient>>>, // TODO [keorn]: remove client: RwLock<Option<Weak<EngineClient>>>, // TODO [keorn]: remove
} }
@ -45,7 +44,6 @@ impl ValidatorContract {
ValidatorContract { ValidatorContract {
contract_address, contract_address,
validators: ValidatorSafeContract::new(contract_address), validators: ValidatorSafeContract::new(contract_address),
provider: validator_report::ValidatorReport::default(),
client: RwLock::new(None), client: RwLock::new(None),
} }
} }
@ -111,7 +109,7 @@ impl ValidatorSet for ValidatorContract {
} }
fn report_malicious(&self, address: &Address, _set_block: BlockNumber, block: BlockNumber, proof: Bytes) { fn report_malicious(&self, address: &Address, _set_block: BlockNumber, block: BlockNumber, proof: Bytes) {
let data = self.provider.functions().report_malicious().input(*address, block, proof); let data = validator_report::functions::report_malicious::encode_input(*address, block, proof);
match self.transact(data) { match self.transact(data) {
Ok(_) => warn!(target: "engine", "Reported malicious validator {}", address), Ok(_) => warn!(target: "engine", "Reported malicious validator {}", address),
Err(s) => warn!(target: "engine", "Validator {} could not be reported {}", address, s), Err(s) => warn!(target: "engine", "Validator {} could not be reported {}", address, s),
@ -119,7 +117,7 @@ impl ValidatorSet for ValidatorContract {
} }
fn report_benign(&self, address: &Address, _set_block: BlockNumber, block: BlockNumber) { fn report_benign(&self, address: &Address, _set_block: BlockNumber, block: BlockNumber) {
let data = self.provider.functions().report_benign().input(*address, block); let data = validator_report::functions::report_benign::encode_input(*address, block);
match self.transact(data) { match self.transact(data) {
Ok(_) => warn!(target: "engine", "Reported benign validator misbehaviour {}", address), Ok(_) => warn!(target: "engine", "Reported benign validator misbehaviour {}", address),
Err(s) => warn!(target: "engine", "Validator {} could not be reported {}", address, s), Err(s) => warn!(target: "engine", "Validator {} could not be reported {}", address, s),

View File

@ -33,8 +33,9 @@ use std::sync::{Weak, Arc};
use super::{SystemCall, ValidatorSet}; use super::{SystemCall, ValidatorSet};
use super::simple_list::SimpleList; use super::simple_list::SimpleList;
use unexpected::Mismatch; use unexpected::Mismatch;
use ethabi::FunctionOutputDecoder;
use_contract!(validator_set, "ValidatorSet", "res/contracts/validator_set.json"); use_contract!(validator_set, "res/contracts/validator_set.json");
const MEMOIZE_CAPACITY: usize = 500; const MEMOIZE_CAPACITY: usize = 500;
@ -50,12 +51,11 @@ lazy_static! {
struct StateProof { struct StateProof {
contract_address: Address, contract_address: Address,
header: Header, header: Header,
provider: validator_set::ValidatorSet,
} }
impl ::engines::StateDependentProof<EthereumMachine> for StateProof { impl ::engines::StateDependentProof<EthereumMachine> for StateProof {
fn generate_proof(&self, caller: &Call) -> Result<Vec<u8>, String> { fn generate_proof(&self, caller: &Call) -> Result<Vec<u8>, String> {
prove_initial(&self.provider, self.contract_address, &self.header, caller) prove_initial(self.contract_address, &self.header, caller)
} }
fn check_proof(&self, machine: &EthereumMachine, proof: &[u8]) -> Result<(), String> { fn check_proof(&self, machine: &EthereumMachine, proof: &[u8]) -> Result<(), String> {
@ -65,7 +65,7 @@ impl ::engines::StateDependentProof<EthereumMachine> for StateProof {
return Err("wrong header in proof".into()); return Err("wrong header in proof".into());
} }
check_first_proof(machine, &self.provider, self.contract_address, header, &state_items).map(|_| ()) check_first_proof(machine, self.contract_address, header, &state_items).map(|_| ())
} }
} }
@ -73,7 +73,6 @@ impl ::engines::StateDependentProof<EthereumMachine> for StateProof {
pub struct ValidatorSafeContract { pub struct ValidatorSafeContract {
contract_address: Address, contract_address: Address,
validators: RwLock<MemoryLruCache<H256, SimpleList>>, validators: RwLock<MemoryLruCache<H256, SimpleList>>,
provider: validator_set::ValidatorSet,
client: RwLock<Option<Weak<EngineClient>>>, // TODO [keorn]: remove client: RwLock<Option<Weak<EngineClient>>>, // TODO [keorn]: remove
} }
@ -89,7 +88,7 @@ fn encode_first_proof(header: &Header, state_items: &[Vec<u8>]) -> Bytes {
} }
// check a first proof: fetch the validator set at the given block. // check a first proof: fetch the validator set at the given block.
fn check_first_proof(machine: &EthereumMachine, provider: &validator_set::ValidatorSet, contract_address: Address, old_header: Header, state_items: &[DBValue]) fn check_first_proof(machine: &EthereumMachine, contract_address: Address, old_header: Header, state_items: &[DBValue])
-> Result<Vec<Address>, String> -> Result<Vec<Address>, String>
{ {
use transaction::{Action, Transaction}; use transaction::{Action, Transaction};
@ -114,31 +113,31 @@ fn check_first_proof(machine: &EthereumMachine, provider: &validator_set::Valida
// check state proof using given machine. // check state proof using given machine.
let number = old_header.number(); let number = old_header.number();
provider.functions().get_validators().call(&|data| { let (data, decoder) = validator_set::functions::get_validators::call();
let from = Address::default();
let tx = Transaction {
nonce: machine.account_start_nonce(number),
action: Action::Call(contract_address),
gas: PROVIDED_GAS.into(),
gas_price: U256::default(),
value: U256::default(),
data,
}.fake_sign(from);
let res = ::state::check_proof( let from = Address::default();
state_items, let tx = Transaction {
*old_header.state_root(), nonce: machine.account_start_nonce(number),
&tx, action: Action::Call(contract_address),
machine, gas: PROVIDED_GAS.into(),
&env_info, gas_price: U256::default(),
); value: U256::default(),
data,
}.fake_sign(from);
match res { let res = ::state::check_proof(
::state::ProvedExecution::BadProof => Err("Bad proof".into()), state_items,
::state::ProvedExecution::Failed(e) => Err(format!("Failed call: {}", e)), *old_header.state_root(),
::state::ProvedExecution::Complete(e) => Ok(e.output), &tx,
} machine,
}).map_err(|err| err.to_string()) &env_info,
);
match res {
::state::ProvedExecution::BadProof => Err("Bad proof".into()),
::state::ProvedExecution::Failed(e) => Err(format!("Failed call: {}", e)),
::state::ProvedExecution::Complete(e) => decoder.decode(&e.output).map_err(|e| e.to_string()),
}
} }
fn decode_first_proof(rlp: &Rlp) -> Result<(Header, Vec<DBValue>), ::error::Error> { fn decode_first_proof(rlp: &Rlp) -> Result<(Header, Vec<DBValue>), ::error::Error> {
@ -167,32 +166,26 @@ fn decode_proof(rlp: &Rlp) -> Result<(Header, Vec<Receipt>), ::error::Error> {
// given a provider and caller, generate proof. this will just be a state proof // given a provider and caller, generate proof. this will just be a state proof
// of `getValidators`. // of `getValidators`.
fn prove_initial(provider: &validator_set::ValidatorSet, contract_address: Address, header: &Header, caller: &Call) -> Result<Vec<u8>, String> { fn prove_initial(contract_address: Address, header: &Header, caller: &Call) -> Result<Vec<u8>, String> {
use std::cell::RefCell; use std::cell::RefCell;
let epoch_proof = RefCell::new(None); let epoch_proof = RefCell::new(None);
let res = { let validators = {
let caller = |data| { let (data, decoder) = validator_set::functions::get_validators::call();
let (result, proof) = caller(contract_address, data)?; let (value, proof) = caller(contract_address, data)?;
*epoch_proof.borrow_mut() = Some(encode_first_proof(header, &proof)); *epoch_proof.borrow_mut() = Some(encode_first_proof(header, &proof));
Ok(result) decoder.decode(&value).map_err(|e| e.to_string())?
};
provider.functions().get_validators().call(&caller)
.map_err(|err| err.to_string())
}; };
res.map(|validators| { let proof = epoch_proof.into_inner().expect("epoch_proof always set after call; qed");
let proof = epoch_proof.into_inner().expect("epoch_proof always set after call; qed");
trace!(target: "engine", "obtained proof for initial set: {} validators, {} bytes", trace!(target: "engine", "obtained proof for initial set: {} validators, {} bytes",
validators.len(), proof.len()); validators.len(), proof.len());
info!(target: "engine", "Signal for switch to contract-based validator set."); info!(target: "engine", "Signal for switch to contract-based validator set.");
info!(target: "engine", "Initial contract validators: {:?}", validators); info!(target: "engine", "Initial contract validators: {:?}", validators);
proof Ok(proof)
})
} }
impl ValidatorSafeContract { impl ValidatorSafeContract {
@ -200,7 +193,6 @@ impl ValidatorSafeContract {
ValidatorSafeContract { ValidatorSafeContract {
contract_address, contract_address,
validators: RwLock::new(MemoryLruCache::new(MEMOIZE_CAPACITY)), validators: RwLock::new(MemoryLruCache::new(MEMOIZE_CAPACITY)),
provider: validator_set::ValidatorSet::default(),
client: RwLock::new(None), client: RwLock::new(None),
} }
} }
@ -208,8 +200,11 @@ impl ValidatorSafeContract {
/// Queries the state and gets the set of validators. /// Queries the state and gets the set of validators.
fn get_list(&self, caller: &Call) -> Option<SimpleList> { fn get_list(&self, caller: &Call) -> Option<SimpleList> {
let contract_address = self.contract_address; let contract_address = self.contract_address;
let caller = move |data| caller(contract_address, data).map(|x| x.0);
match self.provider.functions().get_validators().call(&caller) { let (data, decoder) = validator_set::functions::get_validators::call();
let value = caller(contract_address, data).and_then(|x| decoder.decode(&x.0).map_err(|e| e.to_string()));
match value {
Ok(new) => { Ok(new) => {
debug!(target: "engine", "Set of validators obtained: {:?}", new); debug!(target: "engine", "Set of validators obtained: {:?}", new);
Some(SimpleList::new(new)) Some(SimpleList::new(new))
@ -259,7 +254,6 @@ impl ValidatorSafeContract {
log.topics[1] == *header.parent_hash() log.topics[1] == *header.parent_hash()
}; };
let event = self.provider.events().initiate_change();
//// iterate in reverse because only the _last_ change in a given //// iterate in reverse because only the _last_ change in a given
//// block actually has any effect. //// block actually has any effect.
//// the contract should only increment the nonce once. //// the contract should only increment the nonce once.
@ -269,7 +263,7 @@ impl ValidatorSafeContract {
.flat_map(|r| r.logs.iter()) .flat_map(|r| r.logs.iter())
.filter(move |l| check_log(l)) .filter(move |l| check_log(l))
.filter_map(|log| { .filter_map(|log| {
event.parse_log((log.topics.clone(), log.data.clone()).into()).ok() validator_set::events::initiate_change::parse_log((log.topics.clone(), log.data.clone()).into()).ok()
}); });
// only last log is taken into account // only last log is taken into account
@ -296,7 +290,7 @@ impl ValidatorSet for ValidatorSafeContract {
} }
fn on_epoch_begin(&self, _first: bool, _header: &Header, caller: &mut SystemCall) -> Result<(), ::error::Error> { fn on_epoch_begin(&self, _first: bool, _header: &Header, caller: &mut SystemCall) -> Result<(), ::error::Error> {
let data = self.provider.functions().finalize_change().input(); let data = validator_set::functions::finalize_change::encode_input();
caller(self.contract_address, data) caller(self.contract_address, data)
.map(|_| ()) .map(|_| ())
.map_err(::engines::EngineError::FailedSystemCall) .map_err(::engines::EngineError::FailedSystemCall)
@ -304,7 +298,7 @@ impl ValidatorSet for ValidatorSafeContract {
} }
fn genesis_epoch_data(&self, header: &Header, call: &Call) -> Result<Vec<u8>, String> { fn genesis_epoch_data(&self, header: &Header, call: &Call) -> Result<Vec<u8>, String> {
prove_initial(&self.provider, self.contract_address, header, call) prove_initial(self.contract_address, header, call)
} }
fn is_epoch_end(&self, _first: bool, _chain_head: &Header) -> Option<Vec<u8>> { fn is_epoch_end(&self, _first: bool, _chain_head: &Header) -> Option<Vec<u8>> {
@ -322,7 +316,6 @@ impl ValidatorSet for ValidatorSafeContract {
let state_proof = Arc::new(StateProof { let state_proof = Arc::new(StateProof {
contract_address: self.contract_address, contract_address: self.contract_address,
header: header.clone(), header: header.clone(),
provider: validator_set::ValidatorSet::default(),
}); });
return ::engines::EpochChange::Yes(::engines::Proof::WithState(state_proof as Arc<_>)); return ::engines::EpochChange::Yes(::engines::Proof::WithState(state_proof as Arc<_>));
} }
@ -361,7 +354,7 @@ impl ValidatorSet for ValidatorSafeContract {
let (old_header, state_items) = decode_first_proof(&rlp)?; let (old_header, state_items) = decode_first_proof(&rlp)?;
let number = old_header.number(); let number = old_header.number();
let old_hash = old_header.hash(); let old_hash = old_header.hash();
let addresses = check_first_proof(machine, &self.provider, self.contract_address, old_header, &state_items) let addresses = check_first_proof(machine, self.contract_address, old_header, &state_items)
.map_err(::engines::EngineError::InsufficientProof)?; .map_err(::engines::EngineError::InsufficientProof)?;
trace!(target: "engine", "extracted epoch set at #{}: {} addresses", trace!(target: "engine", "extracted epoch set at #{}: {} addresses",

View File

@ -18,16 +18,15 @@
use client::{RegistryInfo, CallContract, BlockId}; use client::{RegistryInfo, CallContract, BlockId};
use transaction::SignedTransaction; use transaction::SignedTransaction;
use ethabi::FunctionOutputDecoder;
use_contract!(service_transaction, "ServiceTransaction", "res/contracts/service_transaction.json"); use_contract!(service_transaction, "res/contracts/service_transaction.json");
const SERVICE_TRANSACTION_CONTRACT_REGISTRY_NAME: &'static str = "service_transaction_checker"; const SERVICE_TRANSACTION_CONTRACT_REGISTRY_NAME: &'static str = "service_transaction_checker";
/// Service transactions checker. /// Service transactions checker.
#[derive(Default, Clone)] #[derive(Default, Clone)]
pub struct ServiceTransactionChecker { pub struct ServiceTransactionChecker;
contract: service_transaction::ServiceTransaction,
}
impl ServiceTransactionChecker { impl ServiceTransactionChecker {
/// Checks if given address is whitelisted to send service transactions. /// Checks if given address is whitelisted to send service transactions.
@ -45,9 +44,8 @@ impl ServiceTransactionChecker {
trace!(target: "txqueue", "[{:?}] Checking service transaction checker contract from {}", hash, sender); trace!(target: "txqueue", "[{:?}] Checking service transaction checker contract from {}", hash, sender);
self.contract.functions() let (data, decoder) = service_transaction::functions::certified::call(sender);
.certified() let value = client.call_contract(BlockId::Latest, address, data)?;
.call(sender, &|data| client.call_contract(BlockId::Latest, address, data)) decoder.decode(&value).map_err(|e| e.to_string())
.map_err(|e| e.to_string())
} }
} }

View File

@ -32,7 +32,7 @@ use tempdir::TempDir;
use ethereum_types::Address; use ethereum_types::Address;
use test_helpers; use test_helpers;
use_contract!(test_validator_set, "ValidatorSet", "res/contracts/test_validator_set.json"); use_contract!(test_validator_set, "res/contracts/test_validator_set.json");
const PASS: &'static str = ""; const PASS: &'static str = "";
const TRANSITION_BLOCK_1: usize = 2; // block at which the contract becomes activated. const TRANSITION_BLOCK_1: usize = 2; // block at which the contract becomes activated.
@ -135,8 +135,6 @@ fn make_chain(accounts: Arc<AccountProvider>, blocks_beyond: usize, transitions:
vec![transaction] vec![transaction]
}; };
let contract = test_validator_set::ValidatorSet::default();
// apply all transitions. // apply all transitions.
for transition in transitions { for transition in transitions {
let (num, manual, new_set) = match transition { let (num, manual, new_set) = match transition {
@ -163,7 +161,7 @@ fn make_chain(accounts: Arc<AccountProvider>, blocks_beyond: usize, transitions:
false => &CONTRACT_ADDR_1 as &Address, false => &CONTRACT_ADDR_1 as &Address,
}; };
let data = contract.functions().set_validators().input(new_set.clone()); let data = test_validator_set::functions::set_validators::encode_input(new_set.clone());
let mut nonce = nonce.borrow_mut(); let mut nonce = nonce.borrow_mut();
let transaction = Transaction { let transaction = Transaction {
nonce: *nonce, nonce: *nonce,

View File

@ -18,6 +18,7 @@
use ethereum_types::{H256, U256, Address}; use ethereum_types::{H256, U256, Address};
use lru_cache::LruCache; use lru_cache::LruCache;
use ethabi::FunctionOutputDecoder;
use client::{BlockInfo, CallContract, BlockId}; use client::{BlockInfo, CallContract, BlockId};
use parking_lot::Mutex; use parking_lot::Mutex;
@ -26,8 +27,8 @@ use transaction::{Action, SignedTransaction};
use types::BlockNumber; use types::BlockNumber;
use hash::KECCAK_EMPTY; use hash::KECCAK_EMPTY;
use_contract!(transact_acl_deprecated, "TransactAclDeprecated", "res/contracts/tx_acl_deprecated.json"); use_contract!(transact_acl_deprecated, "res/contracts/tx_acl_deprecated.json");
use_contract!(transact_acl, "TransactAcl", "res/contracts/tx_acl.json"); use_contract!(transact_acl, "res/contracts/tx_acl.json");
const MAX_CACHE_SIZE: usize = 4096; const MAX_CACHE_SIZE: usize = 4096;
@ -42,8 +43,6 @@ mod tx_permissions {
/// Connection filter that uses a contract to manage permissions. /// Connection filter that uses a contract to manage permissions.
pub struct TransactionFilter { pub struct TransactionFilter {
contract_deprecated: transact_acl_deprecated::TransactAclDeprecated,
contract: transact_acl::TransactAcl,
contract_address: Address, contract_address: Address,
transition_block: BlockNumber, transition_block: BlockNumber,
permission_cache: Mutex<LruCache<(H256, Address), u32>>, permission_cache: Mutex<LruCache<(H256, Address), u32>>,
@ -55,8 +54,6 @@ impl TransactionFilter {
pub fn from_params(params: &CommonParams) -> Option<TransactionFilter> { pub fn from_params(params: &CommonParams) -> Option<TransactionFilter> {
params.transaction_permission_contract.map(|address| params.transaction_permission_contract.map(|address|
TransactionFilter { TransactionFilter {
contract_deprecated: transact_acl_deprecated::TransactAclDeprecated::default(),
contract: transact_acl::TransactAcl::default(),
contract_address: address, contract_address: address,
transition_block: params.transaction_permission_contract_transition, transition_block: params.transaction_permission_contract_transition,
permission_cache: Mutex::new(LruCache::new(MAX_CACHE_SIZE)), permission_cache: Mutex::new(LruCache::new(MAX_CACHE_SIZE)),
@ -91,10 +88,8 @@ impl TransactionFilter {
let contract_address = self.contract_address; let contract_address = self.contract_address;
let contract_version = contract_version_cache.get_mut(parent_hash).and_then(|v| *v).or_else(|| { let contract_version = contract_version_cache.get_mut(parent_hash).and_then(|v| *v).or_else(|| {
self.contract.functions() let (data, decoder) = transact_acl::functions::contract_version::call();
.contract_version() decoder.decode(&client.call_contract(BlockId::Hash(*parent_hash), contract_address, data).ok()?).ok()
.call(&|data| client.call_contract(BlockId::Hash(*parent_hash), contract_address, data))
.ok()
}); });
contract_version_cache.insert(*parent_hash, contract_version); contract_version_cache.insert(*parent_hash, contract_version);
@ -104,14 +99,16 @@ impl TransactionFilter {
let version_u64 = version.low_u64(); let version_u64 = version.low_u64();
trace!(target: "tx_filter", "Version of tx permission contract: {}", version); trace!(target: "tx_filter", "Version of tx permission contract: {}", version);
match version_u64 { match version_u64 {
2 => self.contract.functions() 2 => {
.allowed_tx_types() let (data, decoder) = transact_acl::functions::allowed_tx_types::call(sender, to, value);
.call(sender, to, value, &|data| client.call_contract(BlockId::Hash(*parent_hash), contract_address, data)) client.call_contract(BlockId::Hash(*parent_hash), contract_address, data)
.map(|(p, f)| (p.low_u32(), f)) .and_then(|value| decoder.decode(&value).map_err(|e| e.to_string()))
.unwrap_or_else(|e| { .map(|(p, f)| (p.low_u32(), f))
error!(target: "tx_filter", "Error calling tx permissions contract: {:?}", e); .unwrap_or_else(|e| {
(tx_permissions::NONE, true) error!(target: "tx_filter", "Error calling tx permissions contract: {:?}", e);
}), (tx_permissions::NONE, true)
})
},
_ => { _ => {
error!(target: "tx_filter", "Unknown version of tx permissions contract is used"); error!(target: "tx_filter", "Unknown version of tx permissions contract is used");
(tx_permissions::NONE, true) (tx_permissions::NONE, true)
@ -120,14 +117,14 @@ impl TransactionFilter {
}, },
None => { None => {
trace!(target: "tx_filter", "Fallback to the deprecated version of tx permission contract"); trace!(target: "tx_filter", "Fallback to the deprecated version of tx permission contract");
(self.contract_deprecated.functions() let (data, decoder) = transact_acl_deprecated::functions::allowed_tx_types::call(sender);
.allowed_tx_types() (client.call_contract(BlockId::Hash(*parent_hash), contract_address, data)
.call(sender, &|data| client.call_contract(BlockId::Hash(*parent_hash), contract_address, data)) .and_then(|value| decoder.decode(&value).map_err(|e| e.to_string()))
.map(|p| p.low_u32()) .map(|p| p.low_u32())
.unwrap_or_else(|e| { .unwrap_or_else(|e| {
error!(target: "tx_filter", "Error calling tx permissions contract: {:?}", e); error!(target: "tx_filter", "Error calling tx permissions contract: {:?}", e);
tx_permissions::NONE tx_permissions::NONE
}), true) }), true)
} }
}; };

View File

@ -21,9 +21,9 @@ parity-reactor = { path = "../util/reactor" }
keccak-hash = "0.1" keccak-hash = "0.1"
registrar = { path = "../registrar" } registrar = { path = "../registrar" }
ethabi = "5.1.2" ethabi = "6.0"
ethabi-derive = "5.1.3" ethabi-derive = "6.0"
ethabi-contract = "5.1.1" ethabi-contract = "6.0"
[dev-dependencies] [dev-dependencies]
hyper = "0.11" hyper = "0.11"

View File

@ -26,7 +26,7 @@ use futures::future::Either;
use ethereum_types::{H256, Address}; use ethereum_types::{H256, Address};
use registrar::{Registrar, RegistrarClient, Asynchronous}; use registrar::{Registrar, RegistrarClient, Asynchronous};
use_contract!(urlhint, "Urlhint", "res/urlhint.json"); use_contract!(urlhint, "res/urlhint.json");
const COMMIT_LEN: usize = 20; const COMMIT_LEN: usize = 20;
const GITHUB_HINT: &'static str = "githubhint"; const GITHUB_HINT: &'static str = "githubhint";
@ -100,16 +100,14 @@ pub trait URLHint: Send + Sync {
/// `URLHintContract` API /// `URLHintContract` API
pub struct URLHintContract { pub struct URLHintContract {
urlhint: urlhint::Urlhint,
registrar: Registrar, registrar: Registrar,
client: Arc<RegistrarClient<Call=Asynchronous>>, client: Arc<RegistrarClient<Call=Asynchronous>>,
} }
impl URLHintContract { impl URLHintContract {
/// Creates new `URLHintContract` /// Creates new `URLHintContract`
pub fn new(client: Arc<RegistrarClient<Call=Asynchronous>>) -> Self { pub fn new(client: Arc<RegistrarClient<Call=Asynchronous>>) -> Self {
URLHintContract { URLHintContract {
urlhint: urlhint::Urlhint::default(),
registrar: Registrar::new(client.clone()), registrar: Registrar::new(client.clone()),
client: client, client: client,
} }
@ -162,14 +160,13 @@ fn decode_urlhint_output(output: (String, [u8; 20], Address)) -> Option<URLHintR
impl URLHint for URLHintContract { impl URLHint for URLHintContract {
fn resolve(&self, id: H256) -> Box<Future<Item = Option<URLHintResult>, Error = String> + Send> { fn resolve(&self, id: H256) -> Box<Future<Item = Option<URLHintResult>, Error = String> + Send> {
let entries = self.urlhint.functions().entries();
let client = self.client.clone(); let client = self.client.clone();
let future = self.registrar.get_address(GITHUB_HINT) let future = self.registrar.get_address(GITHUB_HINT)
.and_then(move |addr| if !addr.is_zero() { .and_then(move |addr| if !addr.is_zero() {
let data = entries.input(id); let data = urlhint::functions::entries::encode_input(id);
let result = client.call_contract(addr, data) let result = client.call_contract(addr, data)
.and_then(move |output| entries.output(&output).map_err(|e| e.to_string())) .and_then(move |output| urlhint::functions::entries::decode_output(&output).map_err(|e| e.to_string()))
.map(decode_urlhint_output); .map(decode_urlhint_output);
Either::B(result) Either::B(result)
} else { } else {

View File

@ -7,7 +7,7 @@ authors = ["Parity Technologies <admin@parity.io>"]
[dependencies] [dependencies]
futures = "0.1" futures = "0.1"
ethabi = "5.1.2" ethabi = "6.0"
ethabi-derive = "5.1.3" ethabi-derive = "6.0"
ethabi-contract = "5.1.1" ethabi-contract = "6.0"
keccak-hash = "0.1" keccak-hash = "0.1"

View File

@ -19,7 +19,7 @@ use ethabi::{Address, Bytes};
use std::sync::Arc; use std::sync::Arc;
use keccak_hash::keccak; use keccak_hash::keccak;
use_contract!(registry, "Registry", "res/registrar.json"); use_contract!(registrar, "res/registrar.json");
// Maps a domain name to an Ethereum address // Maps a domain name to an Ethereum address
const DNS_A_RECORD: &'static str = "A"; const DNS_A_RECORD: &'static str = "A";
@ -30,7 +30,6 @@ pub type Synchronous = Result<Bytes, String>;
/// Registrar is dedicated interface to access the registrar contract /// Registrar is dedicated interface to access the registrar contract
/// which in turn generates an address when a client requests one /// which in turn generates an address when a client requests one
pub struct Registrar { pub struct Registrar {
registrar: registry::Registry,
client: Arc<RegistrarClient<Call=Asynchronous>>, client: Arc<RegistrarClient<Call=Asynchronous>>,
} }
@ -38,7 +37,6 @@ impl Registrar {
/// Registrar constructor /// Registrar constructor
pub fn new(client: Arc<RegistrarClient<Call=Asynchronous>>) -> Self { pub fn new(client: Arc<RegistrarClient<Call=Asynchronous>>) -> Self {
Self { Self {
registrar: registry::Registry::default(),
client: client, client: client,
} }
} }
@ -51,14 +49,11 @@ impl Registrar {
Err(e) => return Box::new(future::err(e)), Err(e) => return Box::new(future::err(e)),
}; };
let address_fetcher = self.registrar.functions().get_address();
let hashed_key: [u8; 32] = keccak(key).into(); let hashed_key: [u8; 32] = keccak(key).into();
let id = address_fetcher.input(hashed_key, DNS_A_RECORD); let id = registrar::functions::get_address::encode_input(hashed_key, DNS_A_RECORD);
let future = self.client.call_contract(registrar_address, id).and_then(move |address| { let future = self.client.call_contract(registrar_address, id)
address_fetcher.output(&address) .and_then(move |address| registrar::functions::get_address::decode_output(&address).map_err(|e| e.to_string()));
}
.map_err(|e| e.to_string()));
Box::new(future) Box::new(future)
} }

View File

@ -34,9 +34,9 @@ kvdb = "0.1"
keccak-hash = "0.1" keccak-hash = "0.1"
ethkey = { path = "../ethkey" } ethkey = { path = "../ethkey" }
lazy_static = "1.0" lazy_static = "1.0"
ethabi = "5.1.2" ethabi = "6.0"
ethabi-derive = "5.1.3" ethabi-derive = "6.0"
ethabi-contract = "5.1.1" ethabi-contract = "6.0"
[dev-dependencies] [dev-dependencies]
ethcore = { path = "../ethcore", features = ["test-helpers"] } ethcore = { path = "../ethcore", features = ["test-helpers"] }

View File

@ -20,11 +20,12 @@ use std::time::Duration;
use parking_lot::{Mutex, RwLock}; use parking_lot::{Mutex, RwLock};
use ethcore::client::{BlockId, ChainNotify, ChainRoute, CallContract}; use ethcore::client::{BlockId, ChainNotify, ChainRoute, CallContract};
use ethereum_types::{H256, Address}; use ethereum_types::{H256, Address};
use ethabi::FunctionOutputDecoder;
use bytes::Bytes; use bytes::Bytes;
use trusted_client::TrustedClient; use trusted_client::TrustedClient;
use types::{Error, ServerKeyId, ContractAddress}; use types::{Error, ServerKeyId, ContractAddress};
use_contract!(acl_storage, "AclStorage", "res/acl_storage.json"); use_contract!(acl_storage, "res/acl_storage.json");
const ACL_CHECKER_CONTRACT_REGISTRY_NAME: &'static str = "secretstore_acl_checker"; const ACL_CHECKER_CONTRACT_REGISTRY_NAME: &'static str = "secretstore_acl_checker";
@ -48,8 +49,6 @@ struct CachedContract {
address_source: ContractAddress, address_source: ContractAddress,
/// Current contract address. /// Current contract address.
contract_address: Option<Address>, contract_address: Option<Address>,
/// Contract at given address.
contract: acl_storage::AclStorage,
} }
/// Dummy ACL storage implementation (check always passed). /// Dummy ACL storage implementation (check always passed).
@ -91,7 +90,6 @@ impl CachedContract {
client, client,
address_source, address_source,
contract_address: None, contract_address: None,
contract: acl_storage::AclStorage::default(),
}; };
contract.update_contract_address(); contract.update_contract_address();
contract contract
@ -112,10 +110,10 @@ impl CachedContract {
// call contract to check accesss // call contract to check accesss
match self.contract_address { match self.contract_address {
Some(contract_address) => { Some(contract_address) => {
let do_call = |data| client.call_contract(BlockId::Latest, contract_address, data); let (encoded, decoder) = acl_storage::functions::check_permissions::call(requester, document.clone());
self.contract.functions() let d = client.call_contract(BlockId::Latest, contract_address, encoded)
.check_permissions() .map_err(|e| Error::Internal(format!("ACL checker call error: {}", e.to_string())))?;
.call(requester, document.clone(), &do_call) decoder.decode(&d)
.map_err(|e| Error::Internal(format!("ACL checker call error: {}", e.to_string()))) .map_err(|e| Error::Internal(format!("ACL checker call error: {}", e.to_string())))
}, },
None => Err(Error::Internal("ACL checker contract is not configured".to_owned())), None => Err(Error::Internal("ACL checker contract is not configured".to_owned())),

View File

@ -19,15 +19,16 @@ use std::net::SocketAddr;
use std::collections::{BTreeMap, HashSet}; use std::collections::{BTreeMap, HashSet};
use std::time::Duration; use std::time::Duration;
use parking_lot::Mutex; use parking_lot::Mutex;
use ethabi::FunctionOutputDecoder;
use ethcore::client::{Client, BlockChainClient, BlockId, ChainNotify, ChainRoute, CallContract}; use ethcore::client::{Client, BlockChainClient, BlockId, ChainNotify, ChainRoute, CallContract};
use ethkey::public_to_address;
use ethereum_types::{H256, Address}; use ethereum_types::{H256, Address};
use ethkey::public_to_address;
use bytes::Bytes; use bytes::Bytes;
use types::{Error, Public, NodeAddress, NodeId}; use types::{Error, Public, NodeAddress, NodeId};
use trusted_client::TrustedClient; use trusted_client::TrustedClient;
use {NodeKeyPair, ContractAddress}; use {NodeKeyPair, ContractAddress};
use_contract!(key_server, "KeyServerSet", "res/key_server_set.json"); use_contract!(key_server, "res/key_server_set.json");
/// Name of KeyServerSet contract in registry. /// Name of KeyServerSet contract in registry.
const KEY_SERVER_SET_CONTRACT_REGISTRY_NAME: &'static str = "secretstore_server_set"; const KEY_SERVER_SET_CONTRACT_REGISTRY_NAME: &'static str = "secretstore_server_set";
@ -104,8 +105,6 @@ struct CachedContract {
contract_address_source: Option<ContractAddress>, contract_address_source: Option<ContractAddress>,
/// Current contract address. /// Current contract address.
contract_address: Option<Address>, contract_address: Option<Address>,
/// Contract interface.
contract: key_server::KeyServerSet,
/// Is auto-migrate enabled? /// Is auto-migrate enabled?
auto_migrate_enabled: bool, auto_migrate_enabled: bool,
/// Current contract state. /// Current contract state.
@ -169,66 +168,60 @@ trait KeyServerSubset<F: Fn(Vec<u8>) -> Result<Vec<u8>, String>> {
fn read_address(&self, address: Address, f: &F) -> Result<String, String>; fn read_address(&self, address: Address, f: &F) -> Result<String, String>;
} }
#[derive(Default)] struct CurrentKeyServerSubset;
struct CurrentKeyServerSubset {
read_list: key_server::functions::GetCurrentKeyServers,
read_public: key_server::functions::GetCurrentKeyServerPublic,
read_address: key_server::functions::GetCurrentKeyServerAddress,
}
impl <F: Fn(Vec<u8>) -> Result<Vec<u8>, String>> KeyServerSubset<F> for CurrentKeyServerSubset { impl <F: Fn(Vec<u8>) -> Result<Vec<u8>, String>> KeyServerSubset<F> for CurrentKeyServerSubset {
fn read_list(&self, f: &F) -> Result<Vec<Address>, String> { fn read_list(&self, f: &F) -> Result<Vec<Address>, String> {
self.read_list.call(f).map_err(|e| e.to_string()) let (encoded, decoder) = key_server::functions::get_current_key_servers::call();
decoder.decode(&f(encoded)?).map_err(|e| e.to_string())
} }
fn read_public(&self, address: Address, f: &F) -> Result<Bytes, String> { fn read_public(&self, address: Address, f: &F) -> Result<Bytes, String> {
self.read_public.call(address, f).map_err(|e| e.to_string()) let (encoded, decoder) = key_server::functions::get_current_key_server_public::call(address);
decoder.decode(&f(encoded)?).map_err(|e| e.to_string())
} }
fn read_address(&self, address: Address, f: &F) -> Result<String, String> { fn read_address(&self, address: Address, f: &F) -> Result<String, String> {
self.read_address.call(address, f).map_err(|e| e.to_string()) let (encoded, decoder) = key_server::functions::get_current_key_server_address::call(address);
decoder.decode(&f(encoded)?).map_err(|e| e.to_string())
} }
} }
#[derive(Default)] struct MigrationKeyServerSubset;
struct MigrationKeyServerSubset {
read_list: key_server::functions::GetMigrationKeyServers,
read_public: key_server::functions::GetMigrationKeyServerPublic,
read_address: key_server::functions::GetMigrationKeyServerAddress,
}
impl <F: Fn(Vec<u8>) -> Result<Vec<u8>, String>> KeyServerSubset<F> for MigrationKeyServerSubset { impl <F: Fn(Vec<u8>) -> Result<Vec<u8>, String>> KeyServerSubset<F> for MigrationKeyServerSubset {
fn read_list(&self, f: &F) -> Result<Vec<Address>, String> { fn read_list(&self, f: &F) -> Result<Vec<Address>, String> {
self.read_list.call(f).map_err(|e| e.to_string()) let (encoded, decoder) = key_server::functions::get_migration_key_servers::call();
decoder.decode(&f(encoded)?).map_err(|e| e.to_string())
} }
fn read_public(&self, address: Address, f: &F) -> Result<Bytes, String> { fn read_public(&self, address: Address, f: &F) -> Result<Bytes, String> {
self.read_public.call(address, f).map_err(|e| e.to_string()) let (encoded, decoder) = key_server::functions::get_migration_key_server_public::call(address);
decoder.decode(&f(encoded)?).map_err(|e| e.to_string())
} }
fn read_address(&self, address: Address, f: &F) -> Result<String, String> { fn read_address(&self, address: Address, f: &F) -> Result<String, String> {
self.read_address.call(address, f).map_err(|e| e.to_string()) let (encoded, decoder) = key_server::functions::get_migration_key_server_address::call(address);
decoder.decode(&f(encoded)?).map_err(|e| e.to_string())
} }
} }
#[derive(Default)] struct NewKeyServerSubset;
struct NewKeyServerSubset {
read_list: key_server::functions::GetNewKeyServers,
read_public: key_server::functions::GetNewKeyServerPublic,
read_address: key_server::functions::GetNewKeyServerAddress,
}
impl <F: Fn(Vec<u8>) -> Result<Vec<u8>, String>> KeyServerSubset<F> for NewKeyServerSubset { impl <F: Fn(Vec<u8>) -> Result<Vec<u8>, String>> KeyServerSubset<F> for NewKeyServerSubset {
fn read_list(&self, f: &F) -> Result<Vec<Address>, String> { fn read_list(&self, f: &F) -> Result<Vec<Address>, String> {
self.read_list.call(f).map_err(|e| e.to_string()) let (encoded, decoder) = key_server::functions::get_new_key_servers::call();
decoder.decode(&f(encoded)?).map_err(|e| e.to_string())
} }
fn read_public(&self, address: Address, f: &F) -> Result<Bytes, String> { fn read_public(&self, address: Address, f: &F) -> Result<Bytes, String> {
self.read_public.call(address, f).map_err(|e| e.to_string()) let (encoded, decoder) = key_server::functions::get_new_key_server_public::call(address);
decoder.decode(&f(encoded)?).map_err(|e| e.to_string())
} }
fn read_address(&self, address: Address, f: &F) -> Result<String, String> { fn read_address(&self, address: Address, f: &F) -> Result<String, String> {
self.read_address.call(address, f).map_err(|e| e.to_string()) let (encoded, decoder) = key_server::functions::get_new_key_server_address::call(address);
decoder.decode(&f(encoded)?).map_err(|e| e.to_string())
} }
} }
@ -249,7 +242,6 @@ impl CachedContract {
client: client, client: client,
contract_address_source: contract_address_source, contract_address_source: contract_address_source,
contract_address: None, contract_address: None,
contract: key_server::KeyServerSet::default(),
auto_migrate_enabled: auto_migrate_enabled, auto_migrate_enabled: auto_migrate_enabled,
future_new_set: None, future_new_set: None,
confirm_migration_tx: None, confirm_migration_tx: None,
@ -313,7 +305,7 @@ impl CachedContract {
} }
// prepare transaction data // prepare transaction data
let transaction_data = self.contract.functions().start_migration().input(migration_id); let transaction_data = key_server::functions::start_migration::encode_input(migration_id);
// send transaction // send transaction
match self.client.transact_contract(*contract_address, transaction_data) { match self.client.transact_contract(*contract_address, transaction_data) {
@ -334,7 +326,7 @@ impl CachedContract {
} }
// prepare transaction data // prepare transaction data
let transaction_data = self.contract.functions().confirm_migration().input(migration_id); let transaction_data = key_server::functions::confirm_migration::encode_input(migration_id);
// send transaction // send transaction
match self.client.transact_contract(contract_address, transaction_data) { match self.client.transact_contract(contract_address, transaction_data) {
@ -362,36 +354,50 @@ impl CachedContract {
let do_call = |data| client.call_contract(BlockId::Latest, contract_address, data); let do_call = |data| client.call_contract(BlockId::Latest, contract_address, data);
let current_set = Self::read_key_server_set(CurrentKeyServerSubset::default(), &do_call); let current_set = Self::read_key_server_set(CurrentKeyServerSubset, &do_call);
// read migration-related data if auto migration is enabled // read migration-related data if auto migration is enabled
let (new_set, migration) = match self.auto_migrate_enabled { let (new_set, migration) = match self.auto_migrate_enabled {
true => { true => {
let new_set = Self::read_key_server_set(NewKeyServerSubset::default(), &do_call); let new_set = Self::read_key_server_set(NewKeyServerSubset, &do_call);
let migration_set = Self::read_key_server_set(MigrationKeyServerSubset::default(), &do_call); let migration_set = Self::read_key_server_set(MigrationKeyServerSubset, &do_call);
let migration_id = match migration_set.is_empty() { let migration_id = match migration_set.is_empty() {
false => self.contract.functions().get_migration_id().call(&do_call) false => {
.map_err(|err| { trace!(target: "secretstore", "Error {} reading migration id from contract", err); err }) let (encoded, decoder) = key_server::functions::get_migration_id::call();
.ok(), do_call(encoded)
.map_err(|e| e.to_string())
.and_then(|data| decoder.decode(&data).map_err(|e| e.to_string()))
.map_err(|err| { trace!(target: "secretstore", "Error {} reading migration id from contract", err); err })
.ok()
},
true => None, true => None,
}; };
let migration_master = match migration_set.is_empty() { let migration_master = match migration_set.is_empty() {
false => self.contract.functions().get_migration_master().call(&do_call) false => {
.map_err(|err| { trace!(target: "secretstore", "Error {} reading migration master from contract", err); err }) let (encoded, decoder) = key_server::functions::get_migration_master::call();
.ok() do_call(encoded)
.and_then(|address| current_set.keys().chain(migration_set.keys()) .map_err(|e| e.to_string())
.find(|public| public_to_address(public) == address) .and_then(|data| decoder.decode(&data).map_err(|e| e.to_string()))
.cloned()), .map_err(|err| { trace!(target: "secretstore", "Error {} reading migration master from contract", err); err })
.ok()
.and_then(|address| current_set.keys().chain(migration_set.keys())
.find(|public| public_to_address(public) == address)
.cloned())
},
true => None, true => None,
}; };
let is_migration_confirmed = match migration_set.is_empty() { let is_migration_confirmed = match migration_set.is_empty() {
false if current_set.contains_key(self.self_key_pair.public()) || migration_set.contains_key(self.self_key_pair.public()) => false if current_set.contains_key(self.self_key_pair.public()) || migration_set.contains_key(self.self_key_pair.public()) => {
self.contract.functions().is_migration_confirmed().call(self.self_key_pair.address(), &do_call) let (encoded, decoder) = key_server::functions::is_migration_confirmed::call(self.self_key_pair.address());
do_call(encoded)
.map_err(|e| e.to_string())
.and_then(|data| decoder.decode(&data).map_err(|e| e.to_string()))
.map_err(|err| { trace!(target: "secretstore", "Error {} reading migration confirmation from contract", err); err }) .map_err(|err| { trace!(target: "secretstore", "Error {} reading migration confirmation from contract", err); err })
.ok(), .ok()
},
_ => None, _ => None,
}; };

View File

@ -17,8 +17,9 @@
use std::sync::Arc; use std::sync::Arc;
use parking_lot::RwLock; use parking_lot::RwLock;
use ethabi::RawLog; use ethabi::RawLog;
use ethcore::filter::Filter; use ethabi::FunctionOutputDecoder;
use ethcore::client::{Client, BlockChainClient, BlockId, CallContract}; use ethcore::client::{Client, BlockChainClient, BlockId, CallContract};
use ethcore::filter::Filter;
use ethkey::{Public, public_to_address}; use ethkey::{Public, public_to_address};
use hash::keccak; use hash::keccak;
use bytes::Bytes; use bytes::Bytes;
@ -29,7 +30,7 @@ use trusted_client::TrustedClient;
use helpers::{get_confirmed_block_hash, REQUEST_CONFIRMATIONS_REQUIRED}; use helpers::{get_confirmed_block_hash, REQUEST_CONFIRMATIONS_REQUIRED};
use {ServerKeyId, NodeKeyPair, ContractAddress}; use {ServerKeyId, NodeKeyPair, ContractAddress};
use_contract!(service, "Service", "res/service.json"); use_contract!(service, "res/service.json");
/// Name of the general SecretStore contract in the registry. /// Name of the general SecretStore contract in the registry.
pub const SERVICE_CONTRACT_REGISTRY_NAME: &'static str = "secretstore_service"; pub const SERVICE_CONTRACT_REGISTRY_NAME: &'static str = "secretstore_service";
@ -102,8 +103,6 @@ pub struct OnChainServiceContract {
/// Contract address source. /// Contract address source.
address_source: ContractAddress, address_source: ContractAddress,
/// Contract. /// Contract.
contract: service::Service,
/// Contract.
data: RwLock<ServiceData>, data: RwLock<ServiceData>,
} }
@ -143,7 +142,6 @@ impl OnChainServiceContract {
self_key_pair: self_key_pair, self_key_pair: self_key_pair,
name: name, name: name,
address_source: address_source, address_source: address_source,
contract: service::Service::default(),
data: RwLock::new(ServiceData { data: RwLock::new(ServiceData {
contract_address: None, contract_address: None,
last_log_block: None, last_log_block: None,
@ -156,8 +154,8 @@ impl OnChainServiceContract {
/// Send transaction to the service contract. /// Send transaction to the service contract.
fn send_contract_transaction<C, P>(&self, tx_name: &str, origin: &Address, server_key_id: &ServerKeyId, is_response_required: C, prepare_tx: P) -> Result<(), String> fn send_contract_transaction<C, P>(&self, tx_name: &str, origin: &Address, server_key_id: &ServerKeyId, is_response_required: C, prepare_tx: P) -> Result<(), String>
where C: FnOnce(&Client, &Address, &service::Service, &ServerKeyId, &Address) -> bool, where C: FnOnce(&Client, &Address, &ServerKeyId, &Address) -> bool,
P: FnOnce(&Client, &Address, &service::Service) -> Result<Bytes, String> { P: FnOnce(&Client, &Address) -> Result<Bytes, String> {
// only publish if contract address is set && client is online // only publish if contract address is set && client is online
let client = match self.client.get() { let client = match self.client.get() {
Some(client) => client, Some(client) => client,
@ -168,12 +166,12 @@ impl OnChainServiceContract {
// failing is ok here - it could be that enough confirmations have been recevied // failing is ok here - it could be that enough confirmations have been recevied
// or key has been requested using HTTP API // or key has been requested using HTTP API
let self_address = public_to_address(self.self_key_pair.public()); let self_address = public_to_address(self.self_key_pair.public());
if !is_response_required(&*client, origin, &self.contract, server_key_id, &self_address) { if !is_response_required(&*client, origin, server_key_id, &self_address) {
return Ok(()); return Ok(());
} }
// prepare transaction data // prepare transaction data
let transaction_data = prepare_tx(&*client, origin, &self.contract)?; let transaction_data = prepare_tx(&*client, origin)?;
// send transaction // send transaction
self.client.transact_contract( self.client.transact_contract(
@ -189,18 +187,17 @@ impl OnChainServiceContract {
/// Create task-specific pending requests iterator. /// Create task-specific pending requests iterator.
fn create_pending_requests_iterator< fn create_pending_requests_iterator<
C: 'static + Fn(&Client, &Address, &service::Service, &BlockId) -> Result<U256, String>, C: 'static + Fn(&Client, &Address, &BlockId) -> Result<U256, String>,
R: 'static + Fn(&NodeKeyPair, &Client, &Address, &service::Service, &BlockId, U256) -> Result<(bool, ServiceTask), String> R: 'static + Fn(&NodeKeyPair, &Client, &Address, &BlockId, U256) -> Result<(bool, ServiceTask), String>
>(&self, client: Arc<Client>, contract_address: &Address, block: &BlockId, get_count: C, read_item: R) -> Box<Iterator<Item=(bool, ServiceTask)>> { >(&self, client: Arc<Client>, contract_address: &Address, block: &BlockId, get_count: C, read_item: R) -> Box<Iterator<Item=(bool, ServiceTask)>> {
let contract = service::Service::default(); get_count(&*client, contract_address, block)
get_count(&*client, contract_address, &contract, block)
.map(|count| { .map(|count| {
let client = client.clone(); let client = client.clone();
let self_key_pair = self.self_key_pair.clone(); let self_key_pair = self.self_key_pair.clone();
let contract_address = contract_address.clone(); let contract_address = contract_address.clone();
let block = block.clone(); let block = block.clone();
Box::new(PendingRequestsIterator { Box::new(PendingRequestsIterator {
read_request: move |index| read_item(&*self_key_pair, &*client, &contract_address, &contract, &block, index) read_request: move |index| read_item(&*self_key_pair, &*client, &contract_address, &block, index)
.map_err(|error| { .map_err(|error| {
warn!(target: "secretstore", "{}: reading pending request failed: {}", warn!(target: "secretstore", "{}: reading pending request failed: {}",
self_key_pair.public(), error); self_key_pair.public(), error);
@ -289,15 +286,15 @@ impl ServiceContract for OnChainServiceContract {
.filter_map(|log| { .filter_map(|log| {
let raw_log: RawLog = (log.entry.topics.into_iter().map(|t| t.0.into()).collect(), log.entry.data).into(); let raw_log: RawLog = (log.entry.topics.into_iter().map(|t| t.0.into()).collect(), log.entry.data).into();
if raw_log.topics[0] == *SERVER_KEY_GENERATION_REQUESTED_EVENT_NAME_HASH { if raw_log.topics[0] == *SERVER_KEY_GENERATION_REQUESTED_EVENT_NAME_HASH {
ServerKeyGenerationService::parse_log(&address, &self.contract, raw_log) ServerKeyGenerationService::parse_log(&address, raw_log)
} else if raw_log.topics[0] == *SERVER_KEY_RETRIEVAL_REQUESTED_EVENT_NAME_HASH { } else if raw_log.topics[0] == *SERVER_KEY_RETRIEVAL_REQUESTED_EVENT_NAME_HASH {
ServerKeyRetrievalService::parse_log(&address, &self.contract, raw_log) ServerKeyRetrievalService::parse_log(&address, raw_log)
} else if raw_log.topics[0] == *DOCUMENT_KEY_STORE_REQUESTED_EVENT_NAME_HASH { } else if raw_log.topics[0] == *DOCUMENT_KEY_STORE_REQUESTED_EVENT_NAME_HASH {
DocumentKeyStoreService::parse_log(&address, &self.contract, raw_log) DocumentKeyStoreService::parse_log(&address, raw_log)
} else if raw_log.topics[0] == *DOCUMENT_KEY_COMMON_PART_RETRIEVAL_REQUESTED_EVENT_NAME_HASH { } else if raw_log.topics[0] == *DOCUMENT_KEY_COMMON_PART_RETRIEVAL_REQUESTED_EVENT_NAME_HASH {
DocumentKeyShadowRetrievalService::parse_common_request_log(&address, &self.contract, raw_log) DocumentKeyShadowRetrievalService::parse_common_request_log(&address, raw_log)
} else if raw_log.topics[0] == *DOCUMENT_KEY_PERSONAL_PART_RETRIEVAL_REQUESTED_EVENT_NAME_HASH { } else if raw_log.topics[0] == *DOCUMENT_KEY_PERSONAL_PART_RETRIEVAL_REQUESTED_EVENT_NAME_HASH {
DocumentKeyShadowRetrievalService::parse_personal_request_log(&address, &self.contract, raw_log) DocumentKeyShadowRetrievalService::parse_personal_request_log(&address, raw_log)
} else { } else {
Err("unknown type of log entry".into()) Err("unknown type of log entry".into())
} }
@ -357,58 +354,58 @@ impl ServiceContract for OnChainServiceContract {
fn publish_generated_server_key(&self, origin: &Address, server_key_id: &ServerKeyId, server_key: Public) -> Result<(), String> { fn publish_generated_server_key(&self, origin: &Address, server_key_id: &ServerKeyId, server_key: Public) -> Result<(), String> {
self.send_contract_transaction("publish_generated_server_key", origin, server_key_id, ServerKeyGenerationService::is_response_required, self.send_contract_transaction("publish_generated_server_key", origin, server_key_id, ServerKeyGenerationService::is_response_required,
|_, _, service| Ok(ServerKeyGenerationService::prepare_pubish_tx_data(service, server_key_id, &server_key))) |_, _| Ok(ServerKeyGenerationService::prepare_pubish_tx_data(server_key_id, &server_key)))
} }
fn publish_server_key_generation_error(&self, origin: &Address, server_key_id: &ServerKeyId) -> Result<(), String> { fn publish_server_key_generation_error(&self, origin: &Address, server_key_id: &ServerKeyId) -> Result<(), String> {
self.send_contract_transaction("publish_server_key_generation_error", origin, server_key_id, ServerKeyGenerationService::is_response_required, self.send_contract_transaction("publish_server_key_generation_error", origin, server_key_id, ServerKeyGenerationService::is_response_required,
|_, _, service| Ok(ServerKeyGenerationService::prepare_error_tx_data(service, server_key_id))) |_, _| Ok(ServerKeyGenerationService::prepare_error_tx_data(server_key_id)))
} }
fn publish_retrieved_server_key(&self, origin: &Address, server_key_id: &ServerKeyId, server_key: Public, threshold: usize) -> Result<(), String> { fn publish_retrieved_server_key(&self, origin: &Address, server_key_id: &ServerKeyId, server_key: Public, threshold: usize) -> Result<(), String> {
let threshold = serialize_threshold(threshold)?; let threshold = serialize_threshold(threshold)?;
self.send_contract_transaction("publish_retrieved_server_key", origin, server_key_id, ServerKeyRetrievalService::is_response_required, self.send_contract_transaction("publish_retrieved_server_key", origin, server_key_id, ServerKeyRetrievalService::is_response_required,
|_, _, service| Ok(ServerKeyRetrievalService::prepare_pubish_tx_data(service, server_key_id, server_key, threshold))) |_, _| Ok(ServerKeyRetrievalService::prepare_pubish_tx_data(server_key_id, server_key, threshold)))
} }
fn publish_server_key_retrieval_error(&self, origin: &Address, server_key_id: &ServerKeyId) -> Result<(), String> { fn publish_server_key_retrieval_error(&self, origin: &Address, server_key_id: &ServerKeyId) -> Result<(), String> {
self.send_contract_transaction("publish_server_key_retrieval_error", origin, server_key_id, ServerKeyRetrievalService::is_response_required, self.send_contract_transaction("publish_server_key_retrieval_error", origin, server_key_id, ServerKeyRetrievalService::is_response_required,
|_, _, service| Ok(ServerKeyRetrievalService::prepare_error_tx_data(service, server_key_id))) |_, _| Ok(ServerKeyRetrievalService::prepare_error_tx_data(server_key_id)))
} }
fn publish_stored_document_key(&self, origin: &Address, server_key_id: &ServerKeyId) -> Result<(), String> { fn publish_stored_document_key(&self, origin: &Address, server_key_id: &ServerKeyId) -> Result<(), String> {
self.send_contract_transaction("publish_stored_document_key", origin, server_key_id, DocumentKeyStoreService::is_response_required, self.send_contract_transaction("publish_stored_document_key", origin, server_key_id, DocumentKeyStoreService::is_response_required,
|_, _, service| Ok(DocumentKeyStoreService::prepare_pubish_tx_data(service, server_key_id))) |_, _| Ok(DocumentKeyStoreService::prepare_pubish_tx_data(server_key_id)))
} }
fn publish_document_key_store_error(&self, origin: &Address, server_key_id: &ServerKeyId) -> Result<(), String> { fn publish_document_key_store_error(&self, origin: &Address, server_key_id: &ServerKeyId) -> Result<(), String> {
self.send_contract_transaction("publish_document_key_store_error", origin, server_key_id, DocumentKeyStoreService::is_response_required, self.send_contract_transaction("publish_document_key_store_error", origin, server_key_id, DocumentKeyStoreService::is_response_required,
|_, _, service| Ok(DocumentKeyStoreService::prepare_error_tx_data(service, server_key_id))) |_, _| Ok(DocumentKeyStoreService::prepare_error_tx_data(server_key_id)))
} }
fn publish_retrieved_document_key_common(&self, origin: &Address, server_key_id: &ServerKeyId, requester: &Address, common_point: Public, threshold: usize) -> Result<(), String> { fn publish_retrieved_document_key_common(&self, origin: &Address, server_key_id: &ServerKeyId, requester: &Address, common_point: Public, threshold: usize) -> Result<(), String> {
let threshold = serialize_threshold(threshold)?; let threshold = serialize_threshold(threshold)?;
self.send_contract_transaction("publish_retrieved_document_key_common", origin, server_key_id, self.send_contract_transaction("publish_retrieved_document_key_common", origin, server_key_id,
|client, contract_address, contract, server_key_id, key_server| |client, contract_address, server_key_id, key_server|
DocumentKeyShadowRetrievalService::is_response_required(client, contract_address, contract, server_key_id, requester, key_server), DocumentKeyShadowRetrievalService::is_response_required(client, contract_address, server_key_id, requester, key_server),
|_, _, service| |_, _|
Ok(DocumentKeyShadowRetrievalService::prepare_pubish_common_tx_data(service, server_key_id, requester, common_point, threshold)) Ok(DocumentKeyShadowRetrievalService::prepare_pubish_common_tx_data(server_key_id, requester, common_point, threshold))
) )
} }
fn publish_retrieved_document_key_personal(&self, origin: &Address, server_key_id: &ServerKeyId, requester: &Address, participants: &[Address], decrypted_secret: Public, shadow: Bytes) -> Result<(), String> { fn publish_retrieved_document_key_personal(&self, origin: &Address, server_key_id: &ServerKeyId, requester: &Address, participants: &[Address], decrypted_secret: Public, shadow: Bytes) -> Result<(), String> {
self.send_contract_transaction("publish_retrieved_document_key_personal", origin, server_key_id, |_, _, _, _, _| true, self.send_contract_transaction("publish_retrieved_document_key_personal", origin, server_key_id, |_, _, _, _| true,
move |client, address, service| move |client, address|
DocumentKeyShadowRetrievalService::prepare_pubish_personal_tx_data(client, address, service, server_key_id, requester, participants, decrypted_secret, shadow) DocumentKeyShadowRetrievalService::prepare_pubish_personal_tx_data(client, address, server_key_id, requester, participants, decrypted_secret, shadow)
) )
} }
fn publish_document_key_retrieval_error(&self, origin: &Address, server_key_id: &ServerKeyId, requester: &Address) -> Result<(), String> { fn publish_document_key_retrieval_error(&self, origin: &Address, server_key_id: &ServerKeyId, requester: &Address) -> Result<(), String> {
self.send_contract_transaction("publish_document_key_retrieval_error", origin, server_key_id, self.send_contract_transaction("publish_document_key_retrieval_error", origin, server_key_id,
|client, contract_address, contract, server_key_id, key_server| |client, contract_address, server_key_id, key_server|
DocumentKeyShadowRetrievalService::is_response_required(client, contract_address, contract, server_key_id, requester, key_server), DocumentKeyShadowRetrievalService::is_response_required(client, contract_address, server_key_id, requester, key_server),
|_, _, service| |_, _|
Ok(DocumentKeyShadowRetrievalService::prepare_error_tx_data(service, server_key_id, requester)) Ok(DocumentKeyShadowRetrievalService::prepare_error_tx_data(server_key_id, requester))
) )
} }
} }
@ -449,318 +446,280 @@ pub fn mask_topics(mask: &ApiMask) -> Vec<H256> {
impl ServerKeyGenerationService { impl ServerKeyGenerationService {
/// Parse request log entry. /// Parse request log entry.
pub fn parse_log(origin: &Address, contract: &service::Service, raw_log: RawLog) -> Result<ServiceTask, String> { pub fn parse_log(origin: &Address, raw_log: RawLog) -> Result<ServiceTask, String> {
let event = contract.events().server_key_generation_requested(); match service::events::server_key_generation_requested::parse_log(raw_log) {
match event.parse_log(raw_log) {
Ok(l) => Ok(ServiceTask::GenerateServerKey(origin.clone(), l.server_key_id, l.author, parse_threshold(l.threshold)?)), Ok(l) => Ok(ServiceTask::GenerateServerKey(origin.clone(), l.server_key_id, l.author, parse_threshold(l.threshold)?)),
Err(e) => Err(format!("{}", e)), Err(e) => Err(format!("{}", e)),
} }
} }
/// Check if response from key server is required. /// Check if response from key server is required.
pub fn is_response_required(client: &Client, contract_address: &Address, contract: &service::Service, server_key_id: &ServerKeyId, key_server: &Address) -> bool { pub fn is_response_required(client: &Client, contract_address: &Address, server_key_id: &ServerKeyId, key_server: &Address) -> bool {
// we're checking confirmation in Latest block, because we're interested in latest contract state here // we're checking confirmation in Latest block, because we're interested in latest contract state here
let do_call = |data| client.call_contract(BlockId::Latest, *contract_address, data); let (encoded, decoder) = service::functions::is_server_key_generation_response_required::call(*server_key_id, *key_server);
contract.functions() match client.call_contract(BlockId::Latest, *contract_address, encoded) {
.is_server_key_generation_response_required() Err(_) => true,
.call(*server_key_id, key_server.clone(), &do_call) Ok(data) => decoder.decode(&data).unwrap_or(true)
.unwrap_or(true) }
} }
/// Prepare publish key transaction data. /// Prepare publish key transaction data.
pub fn prepare_pubish_tx_data(contract: &service::Service, server_key_id: &ServerKeyId, server_key_public: &Public) -> Bytes { pub fn prepare_pubish_tx_data(server_key_id: &ServerKeyId, server_key_public: &Public) -> Bytes {
contract.functions() service::functions::server_key_generated::encode_input(*server_key_id, server_key_public.to_vec())
.server_key_generated()
.input(*server_key_id, server_key_public.to_vec())
} }
/// Prepare error transaction data. /// Prepare error transaction data.
pub fn prepare_error_tx_data(contract: &service::Service, server_key_id: &ServerKeyId) -> Bytes { pub fn prepare_error_tx_data(server_key_id: &ServerKeyId) -> Bytes {
contract.functions() service::functions::server_key_generation_error::encode_input(*server_key_id)
.server_key_generation_error()
.input(*server_key_id)
} }
/// Read pending requests count. /// Read pending requests count.
fn read_pending_requests_count(client: &Client, contract_address: &Address, _contract: &service::Service, block: &BlockId) -> Result<U256, String> { fn read_pending_requests_count(client: &Client, contract_address: &Address, block: &BlockId) -> Result<U256, String> {
let do_call = |data| client.call_contract(block.clone(), contract_address.clone(), data); let (encoded, decoder) = service::functions::server_key_generation_requests_count::call();
let contract = service::Service::default(); decoder.decode(&client.call_contract(*block, *contract_address, encoded)?)
contract.functions() .map_err(|e| e.to_string())
.server_key_generation_requests_count()
.call(&do_call)
.map_err(|error| format!("{}", error))
} }
/// Read pending request. /// Read pending request.
fn read_pending_request(self_key_pair: &NodeKeyPair, client: &Client, contract_address: &Address, contract: &service::Service, block: &BlockId, index: U256) -> Result<(bool, ServiceTask), String> { fn read_pending_request(self_key_pair: &NodeKeyPair, client: &Client, contract_address: &Address, block: &BlockId, index: U256) -> Result<(bool, ServiceTask), String> {
let self_address = public_to_address(self_key_pair.public()); let self_address = public_to_address(self_key_pair.public());
let do_call = |d| client.call_contract(block.clone(), contract_address.clone(), d);
contract.functions() let (encoded, decoder) = service::functions::get_server_key_generation_request::call(index);
.get_server_key_generation_request() let (server_key_id, author, threshold) = decoder.decode(&client.call_contract(*block, *contract_address, encoded)?)
.call(index, &do_call) .map_err(|e| e.to_string())?;
.map_err(|error| format!("{}", error)) let threshold = parse_threshold(threshold)?;
.and_then(|(server_key_id, author, threshold)| parse_threshold(threshold)
.map(|threshold| (server_key_id, author, threshold))) let (encoded, decoder) = service::functions::is_server_key_generation_response_required::call(server_key_id, self_address);
.and_then(|(server_key_id, author, threshold)| contract.functions() let not_confirmed = decoder.decode(&client.call_contract(*block, *contract_address, encoded)?)
.is_server_key_generation_response_required() .map_err(|e| e.to_string())?;
.call(server_key_id.clone(), self_address, &do_call)
.map(|not_confirmed| ( let task = ServiceTask::GenerateServerKey(
not_confirmed, contract_address.clone(),
ServiceTask::GenerateServerKey( server_key_id,
contract_address.clone(), author,
server_key_id, threshold,
author, );
threshold,
))) Ok((not_confirmed, task))
.map_err(|error| format!("{}", error)))
} }
} }
impl ServerKeyRetrievalService { impl ServerKeyRetrievalService {
/// Parse request log entry. /// Parse request log entry.
pub fn parse_log(origin: &Address, contract: &service::Service, raw_log: RawLog) -> Result<ServiceTask, String> { pub fn parse_log(origin: &Address, raw_log: RawLog) -> Result<ServiceTask, String> {
let event = contract.events().server_key_retrieval_requested(); match service::events::server_key_retrieval_requested::parse_log(raw_log) {
match event.parse_log(raw_log) { Ok(l) => Ok(ServiceTask::RetrieveServerKey(*origin, l.server_key_id)),
Ok(l) => Ok(ServiceTask::RetrieveServerKey(origin.clone(), l.server_key_id)), Err(e) => Err(e.to_string())
Err(e) => Err(format!("{}", e)),
} }
} }
/// Check if response from key server is required. /// Check if response from key server is required.
pub fn is_response_required(client: &Client, contract_address: &Address, contract: &service::Service, server_key_id: &ServerKeyId, key_server: &Address) -> bool { pub fn is_response_required(client: &Client, contract_address: &Address, server_key_id: &ServerKeyId, key_server: &Address) -> bool {
// we're checking confirmation in Latest block, because we're interested in latest contract state here // we're checking confirmation in Latest block, because we're interested in latest contract state here
let do_call = |data| client.call_contract(BlockId::Latest, *contract_address, data); let (encoded, decoder) = service::functions::is_server_key_retrieval_response_required::call(*server_key_id, *key_server);
contract.functions() match client.call_contract(BlockId::Latest, *contract_address, encoded) {
.is_server_key_retrieval_response_required() Err(_) => true,
.call(*server_key_id, key_server.clone(), &do_call) Ok(data) => decoder.decode(&data).unwrap_or(true)
.unwrap_or(true) }
} }
/// Prepare publish key transaction data. /// Prepare publish key transaction data.
pub fn prepare_pubish_tx_data(contract: &service::Service, server_key_id: &ServerKeyId, server_key_public: Public, threshold: U256) -> Bytes { pub fn prepare_pubish_tx_data(server_key_id: &ServerKeyId, server_key_public: Public, threshold: U256) -> Bytes {
contract.functions() service::functions::server_key_retrieved::encode_input(*server_key_id, server_key_public.to_vec(), threshold)
.server_key_retrieved()
.input(*server_key_id, server_key_public.to_vec(), threshold)
} }
/// Prepare error transaction data. /// Prepare error transaction data.
pub fn prepare_error_tx_data(contract: &service::Service, server_key_id: &ServerKeyId) -> Bytes { pub fn prepare_error_tx_data(server_key_id: &ServerKeyId) -> Bytes {
contract.functions() service::functions::server_key_retrieval_error::encode_input(*server_key_id)
.server_key_retrieval_error()
.input(*server_key_id)
} }
/// Read pending requests count. /// Read pending requests count.
fn read_pending_requests_count(client: &Client, contract_address: &Address, _contract: &service::Service, block: &BlockId) -> Result<U256, String> { fn read_pending_requests_count(client: &Client, contract_address: &Address, block: &BlockId) -> Result<U256, String> {
let do_call = |data| client.call_contract(block.clone(), contract_address.clone(), data); let (encoded, decoder) = service::functions::server_key_retrieval_requests_count::call();
let contract = service::Service::default(); decoder.decode(&client.call_contract(*block, *contract_address, encoded)?)
contract.functions() .map_err(|e| e.to_string())
.server_key_retrieval_requests_count()
.call(&do_call)
.map_err(|error| format!("{}", error))
} }
/// Read pending request. /// Read pending request.
fn read_pending_request(self_key_pair: &NodeKeyPair, client: &Client, contract_address: &Address, contract: &service::Service, block: &BlockId, index: U256) -> Result<(bool, ServiceTask), String> { fn read_pending_request(self_key_pair: &NodeKeyPair, client: &Client, contract_address: &Address, block: &BlockId, index: U256) -> Result<(bool, ServiceTask), String> {
let self_address = public_to_address(self_key_pair.public()); let self_address = public_to_address(self_key_pair.public());
let do_call = |d| client.call_contract(block.clone(), contract_address.clone(), d);
contract.functions() let (encoded, decoder) = service::functions::get_server_key_retrieval_request::call(index);
.get_server_key_retrieval_request() let server_key_id = decoder.decode(&client.call_contract(*block, *contract_address, encoded)?)
.call(index, &do_call) .map_err(|e| e.to_string())?;
.map_err(|error| format!("{}", error))
.and_then(|server_key_id| contract.functions() let (encoded, decoder) = service::functions::is_server_key_retrieval_response_required::call(server_key_id, self_address);
.is_server_key_retrieval_response_required() let not_confirmed = decoder.decode(&client.call_contract(*block, *contract_address, encoded)?)
.call(server_key_id.clone(), self_address, &do_call) .map_err(|e| e.to_string())?;
.map(|not_confirmed| (
not_confirmed, let task = ServiceTask::RetrieveServerKey(
ServiceTask::RetrieveServerKey( *contract_address,
contract_address.clone(), server_key_id,
server_key_id, );
)))
.map_err(|error| format!("{}", error))) Ok((not_confirmed, task))
} }
} }
impl DocumentKeyStoreService { impl DocumentKeyStoreService {
/// Parse request log entry. /// Parse request log entry.
pub fn parse_log(origin: &Address, contract: &service::Service, raw_log: RawLog) -> Result<ServiceTask, String> { pub fn parse_log(origin: &Address, raw_log: RawLog) -> Result<ServiceTask, String> {
let event = contract.events().document_key_store_requested(); match service::events::document_key_store_requested::parse_log(raw_log) {
match event.parse_log(raw_log) {
Ok(l) => Ok(ServiceTask::StoreDocumentKey(origin.clone(), l.server_key_id, l.author, (*l.common_point).into(), (*l.encrypted_point).into())), Ok(l) => Ok(ServiceTask::StoreDocumentKey(origin.clone(), l.server_key_id, l.author, (*l.common_point).into(), (*l.encrypted_point).into())),
Err(e) => Err(format!("{}", e)), Err(e) => Err(format!("{}", e)),
} }
} }
/// Check if response from key server is required. /// Check if response from key server is required.
pub fn is_response_required(client: &Client, contract_address: &Address, contract: &service::Service, server_key_id: &ServerKeyId, key_server: &Address) -> bool { pub fn is_response_required(client: &Client, contract_address: &Address, server_key_id: &ServerKeyId, key_server: &Address) -> bool {
// we're checking confirmation in Latest block, because we're interested in latest contract state here // we're checking confirmation in Latest block, because we're interested in latest contract state here
let do_call = |data| client.call_contract(BlockId::Latest, *contract_address, data); let (encoded, decoder) = service::functions::is_document_key_store_response_required::call(*server_key_id, *key_server);
contract.functions() match client.call_contract(BlockId::Latest, *contract_address, encoded) {
.is_document_key_store_response_required() Err(_) => true,
.call(*server_key_id, key_server.clone(), &do_call) Ok(data) => decoder.decode(&data).unwrap_or(true)
.unwrap_or(true) }
} }
/// Prepare publish key transaction data. /// Prepare publish key transaction data.
pub fn prepare_pubish_tx_data(contract: &service::Service, server_key_id: &ServerKeyId) -> Bytes { pub fn prepare_pubish_tx_data(server_key_id: &ServerKeyId) -> Bytes {
contract.functions() service::functions::document_key_stored::encode_input(*server_key_id)
.document_key_stored()
.input(*server_key_id)
} }
/// Prepare error transaction data. /// Prepare error transaction data.
pub fn prepare_error_tx_data(contract: &service::Service, server_key_id: &ServerKeyId) -> Bytes { pub fn prepare_error_tx_data(server_key_id: &ServerKeyId) -> Bytes {
contract.functions() service::functions::document_key_store_error::encode_input(*server_key_id)
.document_key_store_error()
.input(*server_key_id)
} }
/// Read pending requests count. /// Read pending requests count.
fn read_pending_requests_count(client: &Client, contract_address: &Address, _contract: &service::Service, block: &BlockId) -> Result<U256, String> { fn read_pending_requests_count(client: &Client, contract_address: &Address, block: &BlockId) -> Result<U256, String> {
let do_call = |data| client.call_contract(block.clone(), contract_address.clone(), data); let (encoded, decoder) = service::functions::document_key_store_requests_count::call();
let contract = service::Service::default(); decoder.decode(&client.call_contract(*block, *contract_address, encoded)?)
contract.functions() .map_err(|e| e.to_string())
.document_key_store_requests_count()
.call(&do_call)
.map_err(|error| format!("{}", error))
} }
/// Read pending request. /// Read pending request.
fn read_pending_request(self_key_pair: &NodeKeyPair, client: &Client, contract_address: &Address, contract: &service::Service, block: &BlockId, index: U256) -> Result<(bool, ServiceTask), String> { fn read_pending_request(self_key_pair: &NodeKeyPair, client: &Client, contract_address: &Address, block: &BlockId, index: U256) -> Result<(bool, ServiceTask), String> {
let self_address = public_to_address(self_key_pair.public()); let self_address = public_to_address(self_key_pair.public());
let do_call = |d| client.call_contract(block.clone(), contract_address.clone(), d); let (encoded, decoder) = service::functions::get_document_key_store_request::call(index);
contract.functions() let (server_key_id, author, common_point, encrypted_point) = decoder.decode(&client.call_contract(*block, *contract_address, encoded)?)
.get_document_key_store_request() .map_err(|e| e.to_string())?;
.call(index, &do_call)
.map_err(|error| format!("{}", error)) let (encoded, decoder) = service::functions::is_document_key_store_response_required::call(server_key_id, self_address);
.and_then(|(server_key_id, author, common_point, encrypted_point)| contract.functions() let not_confirmed = decoder.decode(&client.call_contract(*block, *contract_address, encoded)?)
.is_document_key_store_response_required() .map_err(|e| e.to_string())?;
.call(server_key_id.clone(), self_address, &do_call)
.map(|not_confirmed| ( let task = ServiceTask::StoreDocumentKey(
not_confirmed, *contract_address,
ServiceTask::StoreDocumentKey( server_key_id,
contract_address.clone(), author,
server_key_id, Public::from_slice(&common_point),
author, Public::from_slice(&encrypted_point),
Public::from_slice(&common_point), );
Public::from_slice(&encrypted_point),
))) Ok((not_confirmed, task))
.map_err(|error| format!("{}", error)))
} }
} }
impl DocumentKeyShadowRetrievalService { impl DocumentKeyShadowRetrievalService {
/// Parse common request log entry. /// Parse common request log entry.
pub fn parse_common_request_log(origin: &Address, contract: &service::Service, raw_log: RawLog) -> Result<ServiceTask, String> { pub fn parse_common_request_log(origin: &Address, raw_log: RawLog) -> Result<ServiceTask, String> {
let event = contract.events().document_key_common_retrieval_requested(); match service::events::document_key_common_retrieval_requested::parse_log(raw_log) {
match event.parse_log(raw_log) {
Ok(l) => Ok(ServiceTask::RetrieveShadowDocumentKeyCommon(origin.clone(), l.server_key_id, l.requester)), Ok(l) => Ok(ServiceTask::RetrieveShadowDocumentKeyCommon(origin.clone(), l.server_key_id, l.requester)),
Err(e) => Err(format!("{}", e)), Err(e) => Err(e.to_string())
} }
} }
/// Parse personal request log entry. /// Parse personal request log entry.
pub fn parse_personal_request_log(origin: &Address, contract: &service::Service, raw_log: RawLog) -> Result<ServiceTask, String> { pub fn parse_personal_request_log(origin: &Address, raw_log: RawLog) -> Result<ServiceTask, String> {
let event = contract.events().document_key_personal_retrieval_requested(); match service::events::document_key_personal_retrieval_requested::parse_log(raw_log) {
match event.parse_log(raw_log) {
Ok(l) => Ok(ServiceTask::RetrieveShadowDocumentKeyPersonal(origin.clone(), l.server_key_id, (*l.requester_public).into())), Ok(l) => Ok(ServiceTask::RetrieveShadowDocumentKeyPersonal(origin.clone(), l.server_key_id, (*l.requester_public).into())),
Err(e) => Err(format!("{}", e)), Err(e) => Err(e.to_string())
} }
} }
/// Check if response from key server is required. /// Check if response from key server is required.
pub fn is_response_required(client: &Client, contract_address: &Address, contract: &service::Service, server_key_id: &ServerKeyId, requester: &Address, key_server: &Address) -> bool { pub fn is_response_required(client: &Client, contract_address: &Address, server_key_id: &ServerKeyId, requester: &Address, key_server: &Address) -> bool {
// we're checking confirmation in Latest block, because we're interested in latest contract state here // we're checking confirmation in Latest block, because we're interested in latest contract state here
let do_call = |data| client.call_contract(BlockId::Latest, *contract_address, data); let (encoded, decoder) = service::functions::is_document_key_shadow_retrieval_response_required::call(*server_key_id, *requester, *key_server);
contract.functions() match client.call_contract(BlockId::Latest, *contract_address, encoded) {
.is_document_key_shadow_retrieval_response_required() Err(_) => true,
.call(*server_key_id, *requester, key_server.clone(), &do_call) Ok(data) => decoder.decode(&data).unwrap_or(true)
.unwrap_or(true) }
} }
/// Prepare publish common key transaction data. /// Prepare publish common key transaction data.
pub fn prepare_pubish_common_tx_data(contract: &service::Service, server_key_id: &ServerKeyId, requester: &Address, common_point: Public, threshold: U256) -> Bytes { pub fn prepare_pubish_common_tx_data(server_key_id: &ServerKeyId, requester: &Address, common_point: Public, threshold: U256) -> Bytes {
contract.functions() service::functions::document_key_common_retrieved::encode_input(*server_key_id, *requester, common_point.to_vec(), threshold)
.document_key_common_retrieved()
.input(*server_key_id, *requester, common_point.to_vec(), threshold)
} }
/// Prepare publish personal key transaction data. /// Prepare publish personal key transaction data.
pub fn prepare_pubish_personal_tx_data(client: &Client, contract_address: &Address, contract: &service::Service, server_key_id: &ServerKeyId, requester: &Address, participants: &[Address], decrypted_secret: Public, shadow: Bytes) -> Result<Bytes, String> { pub fn prepare_pubish_personal_tx_data(client: &Client, contract_address: &Address, server_key_id: &ServerKeyId, requester: &Address, participants: &[Address], decrypted_secret: Public, shadow: Bytes) -> Result<Bytes, String> {
let mut participants_mask = U256::default(); let mut participants_mask = U256::default();
for participant in participants { for participant in participants {
let participant_index = Self::map_key_server_address(client, contract_address, contract, participant.clone()) let participant_index = Self::map_key_server_address(client, contract_address, participant.clone())
.map_err(|e| format!("Error searching for {} participant: {}", participant, e))?; .map_err(|e| format!("Error searching for {} participant: {}", participant, e))?;
participants_mask = participants_mask | (U256::one() << participant_index); participants_mask = participants_mask | (U256::one() << participant_index);
} }
Ok(contract.functions() Ok(service::functions::document_key_personal_retrieved::encode_input(
.document_key_personal_retrieved() *server_key_id, *requester, participants_mask, decrypted_secret.to_vec(), shadow
.input(*server_key_id, *requester, participants_mask, decrypted_secret.to_vec(), shadow)) ))
} }
/// Prepare error transaction data. /// Prepare error transaction data.
pub fn prepare_error_tx_data(contract: &service::Service, server_key_id: &ServerKeyId, requester: &Address) -> Bytes { pub fn prepare_error_tx_data(server_key_id: &ServerKeyId, requester: &Address) -> Bytes {
contract.functions() service::functions::document_key_shadow_retrieval_error::encode_input(*server_key_id, *requester)
.document_key_shadow_retrieval_error()
.input(*server_key_id, *requester)
} }
/// Read pending requests count. /// Read pending requests count.
fn read_pending_requests_count(client: &Client, contract_address: &Address, _contract: &service::Service, block: &BlockId) -> Result<U256, String> { fn read_pending_requests_count(client: &Client, contract_address: &Address, block: &BlockId) -> Result<U256, String> {
let do_call = |data| client.call_contract(block.clone(), contract_address.clone(), data); let (encoded, decoder) = service::functions::document_key_shadow_retrieval_requests_count::call();
let contract = service::Service::default(); decoder.decode(&client.call_contract(*block, *contract_address, encoded)?)
contract.functions() .map_err(|e| e.to_string())
.document_key_shadow_retrieval_requests_count()
.call(&do_call)
.map_err(|error| format!("{}", error))
} }
/// Read pending request. /// Read pending request.
fn read_pending_request(self_key_pair: &NodeKeyPair, client: &Client, contract_address: &Address, contract: &service::Service, block: &BlockId, index: U256) -> Result<(bool, ServiceTask), String> { fn read_pending_request(self_key_pair: &NodeKeyPair, client: &Client, contract_address: &Address, block: &BlockId, index: U256) -> Result<(bool, ServiceTask), String> {
let self_address = public_to_address(self_key_pair.public()); let self_address = public_to_address(self_key_pair.public());
let do_call = |d| client.call_contract(block.clone(), contract_address.clone(), d);
contract.functions() let (encoded, decoder) = service::functions::get_document_key_shadow_retrieval_request::call(index);
.get_document_key_shadow_retrieval_request() let (server_key_id, requester, is_common_retrieval_completed) =
.call(index, &do_call) decoder.decode(&client.call_contract(*block, *contract_address, encoded)?)
.map_err(|error| format!("{}", error)) .map_err(|e| e.to_string())?;
.and_then(|(server_key_id, requester, is_common_retrieval_completed)| {
let requester = Public::from_slice(&requester); let requester = Public::from_slice(&requester);
contract.functions() let (encoded, decoder) = service::functions::is_document_key_shadow_retrieval_response_required::call(server_key_id, public_to_address(&requester), self_address);
.is_document_key_shadow_retrieval_response_required() let not_confirmed = decoder.decode(&client.call_contract(*block, *contract_address, encoded)?)
.call(server_key_id.clone(), public_to_address(&requester), self_address, &do_call) .map_err(|e| e.to_string())?;
.map(|not_confirmed| (
not_confirmed, let task = match is_common_retrieval_completed {
match is_common_retrieval_completed { true => ServiceTask::RetrieveShadowDocumentKeyPersonal(
true => ServiceTask::RetrieveShadowDocumentKeyPersonal( *contract_address,
contract_address.clone(), server_key_id,
server_key_id, requester,
requester, ),
), false => ServiceTask::RetrieveShadowDocumentKeyCommon(
false => ServiceTask::RetrieveShadowDocumentKeyCommon( *contract_address,
contract_address.clone(), server_key_id,
server_key_id, public_to_address(&requester),
public_to_address(&requester), ),
), };
},
)) Ok((not_confirmed, task))
.map_err(|error| format!("{}", error))
})
} }
/// Map from key server address to key server index. /// Map from key server address to key server index.
fn map_key_server_address(client: &Client, contract_address: &Address, contract: &service::Service, key_server: Address) -> Result<u8, String> { fn map_key_server_address(client: &Client, contract_address: &Address, key_server: Address) -> Result<u8, String> {
// we're checking confirmation in Latest block, because tx ,ust be appended to the latest state // we're checking confirmation in Latest block, because tx ,ust be appended to the latest state
let do_call = |data| client.call_contract(BlockId::Latest, *contract_address, data); let (encoded, decoder) = service::functions::require_key_server::call(key_server);
contract.functions() let index = decoder.decode(&client.call_contract(BlockId::Latest, *contract_address, encoded)?)
.require_key_server() .map_err(|e| e.to_string())?;
.call(key_server, &do_call)
.map_err(|e| format!("{}", e)) if index > u8::max_value().into() {
.and_then(|index| if index > ::std::u8::MAX.into() { Err(format!("key server index is too big: {}", index))
Err(format!("key server index is too big: {}", index)) } else {
} else { let index: u32 = index.into();
let index: u32 = index.into(); Ok(index as u8)
Ok(index as u8) }
})
} }
} }

View File

@ -9,9 +9,9 @@ authors = ["Parity Technologies <admin@parity.io>"]
keccak-hash = "0.1" keccak-hash = "0.1"
lazy_static = "1.0" lazy_static = "1.0"
log = "0.4" log = "0.4"
ethabi = "5.1.2" ethabi = "6.0"
ethabi-derive = "5.1.3" ethabi-derive = "6.0"
ethabi-contract = "5.1.1" ethabi-contract = "6.0"
target_info = "0.1" target_info = "0.1"
semver = "0.9" semver = "0.9"
ethcore = { path = "../ethcore" } ethcore = { path = "../ethcore" }

View File

@ -37,8 +37,9 @@ use sync::{SyncProvider};
use types::{ReleaseInfo, OperationsInfo, CapState, VersionInfo, ReleaseTrack}; use types::{ReleaseInfo, OperationsInfo, CapState, VersionInfo, ReleaseTrack};
use version; use version;
use semver::Version; use semver::Version;
use ethabi::FunctionOutputDecoder;
use_contract!(operations_contract, "Operations", "res/operations.json"); use_contract!(operations, "res/operations.json");
/// Filter for releases. /// Filter for releases.
#[derive(Debug, Eq, PartialEq, Clone)] #[derive(Debug, Eq, PartialEq, Clone)]
@ -192,41 +193,35 @@ pub trait OperationsClient: Send + Sync + 'static {
/// `OperationsClient` that delegates calls to the operations contract. /// `OperationsClient` that delegates calls to the operations contract.
pub struct OperationsContractClient { pub struct OperationsContractClient {
operations_contract: operations_contract::Operations,
client: Weak<BlockChainClient>, client: Weak<BlockChainClient>,
} }
impl OperationsContractClient { impl OperationsContractClient {
fn new( fn new(client: Weak<BlockChainClient>) -> Self {
operations_contract: operations_contract::Operations, OperationsContractClient {
client: Weak<BlockChainClient>, client
) -> OperationsContractClient { }
OperationsContractClient { operations_contract, client }
} }
/// Get the hash of the latest release for the given track /// Get the hash of the latest release for the given track
fn latest_hash<F>(&self, track: ReleaseTrack, do_call: &F) -> Result<H256, String> fn latest_hash<F>(&self, track: ReleaseTrack, do_call: &F) -> Result<H256, String>
where F: Fn(Vec<u8>) -> Result<Vec<u8>, String> { where F: Fn(Vec<u8>) -> Result<Vec<u8>, String> {
self.operations_contract.functions() let (data, decoder) = operations::functions::latest_in_track::call(*CLIENT_ID_HASH, u8::from(track));
.latest_in_track() let value = do_call(data)?;
.call(*CLIENT_ID_HASH, u8::from(track), do_call) decoder.decode(&value).map_err(|e| e.to_string())
.map_err(|e| format!("{:?}", e))
} }
/// Get release info for the given release /// Get release info for the given release
fn release_info<F>(&self, release_id: H256, do_call: &F) -> Result<ReleaseInfo, String> fn release_info<F>(&self, release_id: H256, do_call: &F) -> Result<ReleaseInfo, String>
where F: Fn(Vec<u8>) -> Result<Vec<u8>, String> { where F: Fn(Vec<u8>) -> Result<Vec<u8>, String> {
let (fork, track, semver, is_critical) = self.operations_contract.functions() let (data, decoder) = operations::functions::release::call(*CLIENT_ID_HASH, release_id);
.release()
.call(*CLIENT_ID_HASH, release_id, &do_call) let (fork, track, semver, is_critical) = decoder.decode(&do_call(data)?).map_err(|e| e.to_string())?;
.map_err(|e| format!("{:?}", e))?;
let (fork, track, semver) = (fork.low_u64(), track.low_u32(), semver.low_u32()); let (fork, track, semver) = (fork.low_u64(), track.low_u32(), semver.low_u32());
let latest_binary = self.operations_contract.functions() let (data, decoder) = operations::functions::checksum::call(*CLIENT_ID_HASH, release_id, *PLATFORM_ID_HASH);
.checksum() let latest_binary = decoder.decode(&do_call(data)?).map_err(|e| e.to_string())?;
.call(*CLIENT_ID_HASH, release_id, *PLATFORM_ID_HASH, &do_call)
.map_err(|e| format!("{:?}", e))?;
Ok(ReleaseInfo { Ok(ReleaseInfo {
version: VersionInfo::from_raw(semver, track as u8, release_id.into()), version: VersionInfo::from_raw(semver, track as u8, release_id.into()),
@ -250,9 +245,9 @@ impl OperationsClient for OperationsContractClient {
trace!(target: "updater", "Looking up this_fork for our release: {}/{:?}", CLIENT_ID, this.hash); trace!(target: "updater", "Looking up this_fork for our release: {}/{:?}", CLIENT_ID, this.hash);
// get the fork number of this release // get the fork number of this release
let this_fork = self.operations_contract.functions() let (data, decoder) = operations::functions::release::call(*CLIENT_ID_HASH, this.hash);
.release() let this_fork = do_call(data)
.call(*CLIENT_ID_HASH, this.hash, &do_call) .and_then(|value| decoder.decode(&value).map_err(|e| e.to_string()))
.ok() .ok()
.and_then(|(fork, track, _, _)| { .and_then(|(fork, track, _, _)| {
let this_track: ReleaseTrack = (track.low_u64() as u8).into(); let this_track: ReleaseTrack = (track.low_u64() as u8).into();
@ -282,10 +277,10 @@ impl OperationsClient for OperationsContractClient {
in_minor = Some(self.release_info(latest_in_track, &do_call)?); in_minor = Some(self.release_info(latest_in_track, &do_call)?);
} }
let fork = self.operations_contract.functions() let (data, decoder) = operations::functions::latest_fork::call();
.latest_fork() let fork = do_call(data)
.call(&do_call) .and_then(|value| decoder.decode(&value).map_err(|e| e.to_string()))?
.map_err(|e| format!("{:?}", e))?.low_u64(); .low_u64();
Ok(OperationsInfo { Ok(OperationsInfo {
fork, fork,
@ -299,9 +294,7 @@ impl OperationsClient for OperationsContractClient {
let client = self.client.upgrade()?; let client = self.client.upgrade()?;
let address = client.registry_address("operations".into(), BlockId::Latest)?; let address = client.registry_address("operations".into(), BlockId::Latest)?;
let event = self.operations_contract.events().release_added(); let topics = operations::events::release_added::filter(Some(*CLIENT_ID_HASH), Some(release.fork.into()), Some(release.is_critical));
let topics = event.create_filter(Some(*CLIENT_ID_HASH), Some(release.fork.into()), Some(release.is_critical));
let topics = vec![topics.topic0, topics.topic1, topics.topic2, topics.topic3]; let topics = vec![topics.topic0, topics.topic1, topics.topic2, topics.topic3];
let topics = topics.into_iter().map(Into::into).map(Some).collect(); let topics = topics.into_iter().map(Into::into).map(Some).collect();
@ -317,7 +310,7 @@ impl OperationsClient for OperationsContractClient {
.unwrap_or_default() .unwrap_or_default()
.iter() .iter()
.filter_map(|log| { .filter_map(|log| {
let event = event.parse_log((log.topics.clone(), log.data.clone()).into()).ok()?; let event = operations::events::release_added::parse_log((log.topics.clone(), log.data.clone()).into()).ok()?;
let version_info = VersionInfo::from_raw(event.semver.low_u32(), event.track.low_u32() as u8, event.release.into()); let version_info = VersionInfo::from_raw(event.semver.low_u32(), event.track.low_u32() as u8, event.release.into());
if version_info == release.version { if version_info == release.version {
Some(log.block_number) Some(log.block_number)
@ -375,7 +368,6 @@ impl Updater {
sync: Some(sync.clone()), sync: Some(sync.clone()),
fetcher, fetcher,
operations_client: OperationsContractClient::new( operations_client: OperationsContractClient::new(
operations_contract::Operations::default(),
client.clone()), client.clone()),
exit_handler: Mutex::new(None), exit_handler: Mutex::new(None),
this: if cfg!(feature = "test-updater") { this: if cfg!(feature = "test-updater") {