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:
		
							parent
							
								
									7dfb5ff5bd
								
							
						
					
					
						commit
						ef4a61c769
					
				
							
								
								
									
										89
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										89
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							@ -456,7 +456,7 @@ dependencies = [
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "ethabi"
 | 
			
		||||
version = "5.1.2"
 | 
			
		||||
version = "6.0.1"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
 | 
			
		||||
@ -470,18 +470,18 @@ dependencies = [
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "ethabi-contract"
 | 
			
		||||
version = "5.1.1"
 | 
			
		||||
version = "6.0.0"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "ethabi-derive"
 | 
			
		||||
version = "5.1.3"
 | 
			
		||||
version = "6.0.1"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
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)",
 | 
			
		||||
 "quote 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
 | 
			
		||||
 "syn 0.12.15 (registry+https://github.com/rust-lang/crates.io-index)",
 | 
			
		||||
 "quote 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
 | 
			
		||||
 "syn 0.13.11 (registry+https://github.com/rust-lang/crates.io-index)",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
@ -522,9 +522,9 @@ dependencies = [
 | 
			
		||||
 "common-types 0.1.0",
 | 
			
		||||
 "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)",
 | 
			
		||||
 "ethabi 5.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
 | 
			
		||||
 "ethabi-contract 5.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
 | 
			
		||||
 "ethabi-derive 5.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
 | 
			
		||||
 "ethabi 6.0.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 6.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
 | 
			
		||||
 "ethash 1.12.0",
 | 
			
		||||
 "ethcore-bloom-journal 0.1.0",
 | 
			
		||||
 "ethcore-io 1.12.0",
 | 
			
		||||
@ -747,9 +747,9 @@ name = "ethcore-private-tx"
 | 
			
		||||
version = "1.0.0"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "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-contract 5.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
 | 
			
		||||
 "ethabi-derive 5.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
 | 
			
		||||
 "ethabi 6.0.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 6.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
 | 
			
		||||
 "ethcore 1.12.0",
 | 
			
		||||
 "ethcore-io 1.12.0",
 | 
			
		||||
 "ethcore-logger 1.12.0",
 | 
			
		||||
@ -785,9 +785,9 @@ name = "ethcore-secretstore"
 | 
			
		||||
version = "1.0.0"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "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-contract 5.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
 | 
			
		||||
 "ethabi-derive 5.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
 | 
			
		||||
 "ethabi 6.0.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 6.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
 | 
			
		||||
 "ethcore 1.12.0",
 | 
			
		||||
 "ethcore-logger 1.12.0",
 | 
			
		||||
 "ethcore-sync 1.12.0",
 | 
			
		||||
@ -1863,9 +1863,9 @@ dependencies = [
 | 
			
		||||
name = "node-filter"
 | 
			
		||||
version = "1.12.0"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "ethabi 5.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
 | 
			
		||||
 "ethabi-contract 5.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
 | 
			
		||||
 "ethabi-derive 5.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
 | 
			
		||||
 "ethabi 6.0.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 6.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
 | 
			
		||||
 "ethcore 1.12.0",
 | 
			
		||||
 "ethcore-io 1.12.0",
 | 
			
		||||
 "ethcore-network 1.12.0",
 | 
			
		||||
@ -2097,9 +2097,9 @@ dependencies = [
 | 
			
		||||
name = "parity-hash-fetch"
 | 
			
		||||
version = "1.12.0"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "ethabi 5.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
 | 
			
		||||
 "ethabi-contract 5.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
 | 
			
		||||
 "ethabi-derive 5.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
 | 
			
		||||
 "ethabi 6.0.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 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)",
 | 
			
		||||
 "fake-fetch 0.0.1",
 | 
			
		||||
 "fetch 0.1.0",
 | 
			
		||||
@ -2313,9 +2313,9 @@ dependencies = [
 | 
			
		||||
name = "parity-updater"
 | 
			
		||||
version = "1.12.0"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "ethabi 5.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
 | 
			
		||||
 "ethabi-contract 5.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
 | 
			
		||||
 "ethabi-derive 5.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
 | 
			
		||||
 "ethabi 6.0.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 6.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
 | 
			
		||||
 "ethcore 1.12.0",
 | 
			
		||||
 "ethcore-sync 1.12.0",
 | 
			
		||||
 "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)",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[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]]
 | 
			
		||||
name = "proc-macro2"
 | 
			
		||||
version = "0.3.8"
 | 
			
		||||
@ -2631,14 +2623,6 @@ name = "quick-error"
 | 
			
		||||
version = "1.2.2"
 | 
			
		||||
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]]
 | 
			
		||||
name = "quote"
 | 
			
		||||
version = "0.5.2"
 | 
			
		||||
@ -2770,9 +2754,9 @@ dependencies = [
 | 
			
		||||
name = "registrar"
 | 
			
		||||
version = "0.0.1"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "ethabi 5.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
 | 
			
		||||
 "ethabi-contract 5.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
 | 
			
		||||
 "ethabi-derive 5.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
 | 
			
		||||
 "ethabi 6.0.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 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)",
 | 
			
		||||
 "keccak-hash 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
 | 
			
		||||
]
 | 
			
		||||
@ -3103,16 +3087,6 @@ name = "strsim"
 | 
			
		||||
version = "0.7.0"
 | 
			
		||||
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]]
 | 
			
		||||
name = "syn"
 | 
			
		||||
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.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 ethabi 5.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "cf28f7a4a82229af21a4b2233eb411c459034010ad524976c4fb4556c5969b5b"
 | 
			
		||||
"checksum ethabi-contract 5.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7311354f2a46a4b564004047bf8dce9a57cbd8d7ce30021a56bd1a975baaf2f9"
 | 
			
		||||
"checksum ethabi-derive 5.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7caf91e5d37033970be4a66cdef1e5e267af1c999e48b78d6ba86564c1081fab"
 | 
			
		||||
"checksum ethabi 6.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "36c7bf66bd7ff02c3bc512a276a0f95300e3abb87060704fddf588ae11b86d99"
 | 
			
		||||
"checksum ethabi-contract 6.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "795e25fd868e12a59ca235dbe1f6cc8f1eba8f67d6a39438b29535e0126e0c27"
 | 
			
		||||
"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 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"
 | 
			
		||||
@ -4084,14 +4058,12 @@ dependencies = [
 | 
			
		||||
"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-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.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 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 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.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"
 | 
			
		||||
@ -4146,7 +4118,6 @@ dependencies = [
 | 
			
		||||
"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.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.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"
 | 
			
		||||
 | 
			
		||||
@ -29,9 +29,9 @@ ethcore-stratum = { path = "./stratum", optional = true }
 | 
			
		||||
ethcore-transaction = { path = "./transaction" }
 | 
			
		||||
ethereum-types = "0.4"
 | 
			
		||||
memory-cache = { path = "../util/memory_cache" }
 | 
			
		||||
ethabi = "5.1.2"
 | 
			
		||||
ethabi-derive = "5.1.3"
 | 
			
		||||
ethabi-contract = "5.1.1"
 | 
			
		||||
ethabi = "6.0"
 | 
			
		||||
ethabi-derive = "6.0"
 | 
			
		||||
ethabi-contract = "6.0"
 | 
			
		||||
ethjson = { path = "../json" }
 | 
			
		||||
ethkey = { path = "../ethkey" }
 | 
			
		||||
ethstore = { path = "../ethstore" }
 | 
			
		||||
 | 
			
		||||
@ -13,9 +13,9 @@ ethcore-network-devp2p = { path = "../../util/network-devp2p" }
 | 
			
		||||
ethereum-types = "0.4"
 | 
			
		||||
log = "0.4"
 | 
			
		||||
parking_lot = "0.6"
 | 
			
		||||
ethabi = "5.1.2"
 | 
			
		||||
ethabi-derive = "5.1.3"
 | 
			
		||||
ethabi-contract = "5.1.1"
 | 
			
		||||
ethabi = "6.0"
 | 
			
		||||
ethabi-derive = "6.0"
 | 
			
		||||
ethabi-contract = "6.0"
 | 
			
		||||
lru-cache = "0.1"
 | 
			
		||||
 | 
			
		||||
[dev-dependencies]
 | 
			
		||||
 | 
			
		||||
@ -44,16 +44,16 @@ use parking_lot::Mutex;
 | 
			
		||||
 | 
			
		||||
use ethcore::client::{BlockChainClient, BlockId};
 | 
			
		||||
use ethereum_types::{H256, Address};
 | 
			
		||||
use ethabi::FunctionOutputDecoder;
 | 
			
		||||
use network::{ConnectionFilter, ConnectionDirection};
 | 
			
		||||
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;
 | 
			
		||||
 | 
			
		||||
/// Connection filter that uses a contract to manage permissions.
 | 
			
		||||
pub struct NodeFilter {
 | 
			
		||||
	contract: peer_set::PeerSet,
 | 
			
		||||
	client: Weak<BlockChainClient>,
 | 
			
		||||
	contract_address: Address,
 | 
			
		||||
	permission_cache: Mutex<LruCache<(H256, NodeId), bool>>,
 | 
			
		||||
@ -63,7 +63,6 @@ impl NodeFilter {
 | 
			
		||||
	/// Create a new instance. Accepts a contract address.
 | 
			
		||||
	pub fn new(client: Weak<BlockChainClient>, contract_address: Address) -> NodeFilter {
 | 
			
		||||
		NodeFilter {
 | 
			
		||||
			contract: peer_set::PeerSet::default(),
 | 
			
		||||
			client,
 | 
			
		||||
			contract_address,
 | 
			
		||||
			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_high = H256::from_slice(&connecting_id[32..64]);
 | 
			
		||||
 | 
			
		||||
		let allowed = self.contract.functions()
 | 
			
		||||
			.connection_allowed()
 | 
			
		||||
			.call(own_low, own_high, id_low, id_high, &|data| client.call_contract(BlockId::Latest, address, data))
 | 
			
		||||
		let (data, decoder) = peer_set::functions::connection_allowed::call(own_low, own_high, id_low, id_high);
 | 
			
		||||
		let allowed = client.call_contract(BlockId::Latest, address, data)
 | 
			
		||||
			.and_then(|value| decoder.decode(&value).map_err(|e| e.to_string()))
 | 
			
		||||
			.unwrap_or_else(|e| {
 | 
			
		||||
				debug!("Error callling peer set contract: {:?}", e);
 | 
			
		||||
				false
 | 
			
		||||
 | 
			
		||||
@ -7,9 +7,9 @@ authors = ["Parity Technologies <admin@parity.io>"]
 | 
			
		||||
 | 
			
		||||
[dependencies]
 | 
			
		||||
error-chain = { version = "0.12", default-features = false }
 | 
			
		||||
ethabi = "5.1.2"
 | 
			
		||||
ethabi-derive = "5.1.3"
 | 
			
		||||
ethabi-contract = "5.1.1"
 | 
			
		||||
ethabi = "6.0"
 | 
			
		||||
ethabi-derive = "6.0"
 | 
			
		||||
ethabi-contract = "6.0"
 | 
			
		||||
ethcore = { path = ".." }
 | 
			
		||||
parity-bytes = "0.1"
 | 
			
		||||
parity-crypto = "0.1"
 | 
			
		||||
 | 
			
		||||
@ -89,11 +89,12 @@ use ethcore::miner::{self, Miner, MinerService, pool_client::NonceCache};
 | 
			
		||||
use ethcore::trace::{Tracer, VMTracer};
 | 
			
		||||
use rustc_hex::FromHex;
 | 
			
		||||
use ethkey::Password;
 | 
			
		||||
use ethabi::FunctionOutputDecoder;
 | 
			
		||||
 | 
			
		||||
// 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");
 | 
			
		||||
 | 
			
		||||
use_contract!(private, "PrivateContract", "res/private.json");
 | 
			
		||||
use_contract!(private_contract, "res/private.json");
 | 
			
		||||
 | 
			
		||||
/// Initialization vector length.
 | 
			
		||||
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> {
 | 
			
		||||
		let contract = private::PrivateContract::default();
 | 
			
		||||
		let state = contract.functions()
 | 
			
		||||
			.state()
 | 
			
		||||
			.call(&|data| self.client.call_contract(block, *address, data))
 | 
			
		||||
			.map_err(|e| ErrorKind::Call(format!("Contract call failed {:?}", e)))?;
 | 
			
		||||
 | 
			
		||||
		let (data, decoder) = private_contract::functions::state::call();
 | 
			
		||||
		let value = self.client.call_contract(block, *address, data)?;
 | 
			
		||||
		let state = decoder.decode(&value).map_err(|e| ErrorKind::Call(format!("Contract call failed {:?}", e)))?;
 | 
			
		||||
		self.decrypt(address, &state)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	fn get_decrypted_code(&self, address: &Address, block: BlockId) -> Result<Bytes, Error> {
 | 
			
		||||
		let contract = private::PrivateContract::default();
 | 
			
		||||
		let code = contract.functions()
 | 
			
		||||
			.code()
 | 
			
		||||
			.call(&|data| self.client.call_contract(block, *address, data))
 | 
			
		||||
			.map_err(|e| ErrorKind::Call(format!("Contract call failed {:?}", e)))?;
 | 
			
		||||
 | 
			
		||||
		self.decrypt(address, &code)
 | 
			
		||||
		let (data, decoder) = private_contract::functions::code::call();
 | 
			
		||||
		let value = self.client.call_contract(block, *address, data)?;
 | 
			
		||||
		let state = decoder.decode(&value).map_err(|e| ErrorKind::Call(format!("Contract call failed {:?}", e)))?;
 | 
			
		||||
		self.decrypt(address, &state)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	pub fn get_contract_nonce(&self, address: &Address, block: BlockId) -> Result<U256, Error> {
 | 
			
		||||
		let contract = private::PrivateContract::default();
 | 
			
		||||
		Ok(contract.functions()
 | 
			
		||||
			.nonce()
 | 
			
		||||
			.call(&|data| self.client.call_contract(block, *address, data))
 | 
			
		||||
			.map_err(|e| ErrorKind::Call(format!("Contract call failed {:?}", e)))?)
 | 
			
		||||
		let (data, decoder) = private_contract::functions::nonce::call();
 | 
			
		||||
		let value = self.client.call_contract(block, *address, data)?;
 | 
			
		||||
		decoder.decode(&value).map_err(|e| ErrorKind::Call(format!("Contract call failed {:?}", e)).into())
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	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 {
 | 
			
		||||
		let constructor_code = DEFAULT_STUB_CONTRACT.from_hex().expect("Default contract code is valid");
 | 
			
		||||
		let private = private::PrivateContract::default();
 | 
			
		||||
		private.constructor(constructor_code, validators.iter().map(|a| *a).collect::<Vec<Address>>(), code, storage)
 | 
			
		||||
		private_contract::constructor(constructor_code, validators.iter().map(|a| *a).collect::<Vec<Address>>(), code, storage)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	fn generate_set_state_call(signatures: &[Signature], storage: Bytes) -> Bytes {
 | 
			
		||||
		let private = private::PrivateContract::default();
 | 
			
		||||
		private.functions().set_state().input(
 | 
			
		||||
		private_contract::functions::set_state::encode_input(
 | 
			
		||||
			storage,
 | 
			
		||||
			signatures.iter().map(|s| {
 | 
			
		||||
				let mut v: [u8; 32] = [0; 32];
 | 
			
		||||
@ -604,11 +595,9 @@ impl Provider where {
 | 
			
		||||
 | 
			
		||||
	/// Returns private validators for a contract.
 | 
			
		||||
	pub fn get_validators(&self, block: BlockId, address: &Address) -> Result<Vec<Address>, Error> {
 | 
			
		||||
		let contract = private::PrivateContract::default();
 | 
			
		||||
		Ok(contract.functions()
 | 
			
		||||
			.get_validators()
 | 
			
		||||
			.call(&|data| self.client.call_contract(block, *address, data))
 | 
			
		||||
			.map_err(|e| ErrorKind::Call(format!("Contract call failed {:?}", e)))?)
 | 
			
		||||
		let (data, decoder) = private_contract::functions::get_validators::call();
 | 
			
		||||
		let value = self.client.call_contract(block, *address, data)?;
 | 
			
		||||
		decoder.decode(&value).map_err(|e| ErrorKind::Call(format!("Contract call failed {:?}", e)).into())
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -86,7 +86,7 @@ pub use types::block_status::BlockStatus;
 | 
			
		||||
pub use blockchain::CacheSize as BlockChainCacheSize;
 | 
			
		||||
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;
 | 
			
		||||
// 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
 | 
			
		||||
	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>,
 | 
			
		||||
 | 
			
		||||
	/// A closure to call when we want to restart the client
 | 
			
		||||
@ -776,7 +774,6 @@ impl Client {
 | 
			
		||||
			factories: factories,
 | 
			
		||||
			history: history,
 | 
			
		||||
			on_user_defaults_change: Mutex::new(None),
 | 
			
		||||
			registrar: registry::Registry::default(),
 | 
			
		||||
			registrar_address,
 | 
			
		||||
			exit_handler: Mutex::new(None),
 | 
			
		||||
			importer,
 | 
			
		||||
@ -1365,17 +1362,17 @@ impl BlockChainTrait for Client {}
 | 
			
		||||
 | 
			
		||||
impl RegistryInfo for Client {
 | 
			
		||||
	fn registry_address(&self, name: String, block: BlockId) -> Option<Address> {
 | 
			
		||||
		use ethabi::FunctionOutputDecoder;
 | 
			
		||||
 | 
			
		||||
		let address = self.registrar_address?;
 | 
			
		||||
 | 
			
		||||
		self.registrar.functions()
 | 
			
		||||
			.get_address()
 | 
			
		||||
			.call(keccak(name.as_bytes()), "A", &|data| self.call_contract(block, address, data))
 | 
			
		||||
			.ok()
 | 
			
		||||
			.and_then(|a| if a.is_zero() {
 | 
			
		||||
				None
 | 
			
		||||
			} else {
 | 
			
		||||
				Some(a)
 | 
			
		||||
			})
 | 
			
		||||
		let (data, decoder) = registry::functions::get_address::call(keccak(name.as_bytes()), "A");
 | 
			
		||||
		let value = decoder.decode(&self.call_contract(block, address, data).ok()?).ok()?;
 | 
			
		||||
		if value.is_zero() {
 | 
			
		||||
			None
 | 
			
		||||
		} else {
 | 
			
		||||
			Some(value)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -30,7 +30,7 @@ use trace;
 | 
			
		||||
use types::BlockNumber;
 | 
			
		||||
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.
 | 
			
		||||
/// Depending on the consensus engine the allocated block reward might have
 | 
			
		||||
@ -81,7 +81,6 @@ impl Into<trace::RewardType> for RewardKind {
 | 
			
		||||
#[derive(PartialEq, Debug)]
 | 
			
		||||
pub struct BlockRewardContract {
 | 
			
		||||
	kind: SystemOrCodeCallKind,
 | 
			
		||||
	block_reward_contract: block_reward_contract::BlockReward,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl BlockRewardContract {
 | 
			
		||||
@ -89,7 +88,6 @@ impl BlockRewardContract {
 | 
			
		||||
	pub fn new(kind: SystemOrCodeCallKind) -> BlockRewardContract {
 | 
			
		||||
		BlockRewardContract {
 | 
			
		||||
			kind,
 | 
			
		||||
			block_reward_contract: block_reward_contract::BlockReward::default(),
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@ -114,9 +112,7 @@ impl BlockRewardContract {
 | 
			
		||||
		beneficiaries: &[(Address, RewardKind)],
 | 
			
		||||
		caller: &mut SystemOrCodeCall,
 | 
			
		||||
	) -> Result<Vec<(Address, U256)>, Error> {
 | 
			
		||||
		let reward = self.block_reward_contract.functions().reward();
 | 
			
		||||
 | 
			
		||||
		let input = reward.input(
 | 
			
		||||
		let input = block_reward_contract::functions::reward::encode_input(
 | 
			
		||||
			beneficiaries.iter().map(|&(address, _)| H160::from(address)),
 | 
			
		||||
			beneficiaries.iter().map(|&(_, ref reward_kind)| u16::from(*reward_kind)),
 | 
			
		||||
		);
 | 
			
		||||
 | 
			
		||||
@ -30,13 +30,12 @@ use machine::{AuxiliaryData, Call, EthereumMachine};
 | 
			
		||||
use super::{ValidatorSet, SimpleList, SystemCall};
 | 
			
		||||
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.
 | 
			
		||||
pub struct ValidatorContract {
 | 
			
		||||
	contract_address: Address,
 | 
			
		||||
	validators: ValidatorSafeContract,
 | 
			
		||||
	provider: validator_report::ValidatorReport,
 | 
			
		||||
	client: RwLock<Option<Weak<EngineClient>>>, // TODO [keorn]: remove
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -45,7 +44,6 @@ impl ValidatorContract {
 | 
			
		||||
		ValidatorContract {
 | 
			
		||||
			contract_address,
 | 
			
		||||
			validators: ValidatorSafeContract::new(contract_address),
 | 
			
		||||
			provider: validator_report::ValidatorReport::default(),
 | 
			
		||||
			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) {
 | 
			
		||||
		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) {
 | 
			
		||||
			Ok(_) => warn!(target: "engine", "Reported malicious validator {}", address),
 | 
			
		||||
			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) {
 | 
			
		||||
		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) {
 | 
			
		||||
			Ok(_) => warn!(target: "engine", "Reported benign validator misbehaviour {}", address),
 | 
			
		||||
			Err(s) => warn!(target: "engine", "Validator {} could not be reported {}", address, s),
 | 
			
		||||
 | 
			
		||||
@ -33,8 +33,9 @@ use std::sync::{Weak, Arc};
 | 
			
		||||
use super::{SystemCall, ValidatorSet};
 | 
			
		||||
use super::simple_list::SimpleList;
 | 
			
		||||
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;
 | 
			
		||||
 | 
			
		||||
@ -50,12 +51,11 @@ lazy_static! {
 | 
			
		||||
struct StateProof {
 | 
			
		||||
	contract_address: Address,
 | 
			
		||||
	header: Header,
 | 
			
		||||
	provider: validator_set::ValidatorSet,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl ::engines::StateDependentProof<EthereumMachine> for StateProof {
 | 
			
		||||
	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> {
 | 
			
		||||
@ -65,7 +65,7 @@ impl ::engines::StateDependentProof<EthereumMachine> for StateProof {
 | 
			
		||||
			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 {
 | 
			
		||||
	contract_address: Address,
 | 
			
		||||
	validators: RwLock<MemoryLruCache<H256, SimpleList>>,
 | 
			
		||||
	provider: validator_set::ValidatorSet,
 | 
			
		||||
	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.
 | 
			
		||||
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>
 | 
			
		||||
{
 | 
			
		||||
	use transaction::{Action, Transaction};
 | 
			
		||||
@ -114,31 +113,31 @@ fn check_first_proof(machine: &EthereumMachine, provider: &validator_set::Valida
 | 
			
		||||
 | 
			
		||||
	// check state proof using given machine.
 | 
			
		||||
	let number = old_header.number();
 | 
			
		||||
	provider.functions().get_validators().call(&|data| {
 | 
			
		||||
		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 (data, decoder) = validator_set::functions::get_validators::call();
 | 
			
		||||
 | 
			
		||||
		let res = ::state::check_proof(
 | 
			
		||||
			state_items,
 | 
			
		||||
			*old_header.state_root(),
 | 
			
		||||
			&tx,
 | 
			
		||||
			machine,
 | 
			
		||||
			&env_info,
 | 
			
		||||
		);
 | 
			
		||||
	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);
 | 
			
		||||
 | 
			
		||||
		match res {
 | 
			
		||||
			::state::ProvedExecution::BadProof => Err("Bad proof".into()),
 | 
			
		||||
			::state::ProvedExecution::Failed(e) => Err(format!("Failed call: {}", e)),
 | 
			
		||||
			::state::ProvedExecution::Complete(e) => Ok(e.output),
 | 
			
		||||
		}
 | 
			
		||||
	}).map_err(|err| err.to_string())
 | 
			
		||||
	let res = ::state::check_proof(
 | 
			
		||||
		state_items,
 | 
			
		||||
		*old_header.state_root(),
 | 
			
		||||
		&tx,
 | 
			
		||||
		machine,
 | 
			
		||||
		&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> {
 | 
			
		||||
@ -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
 | 
			
		||||
// 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;
 | 
			
		||||
 | 
			
		||||
	let epoch_proof = RefCell::new(None);
 | 
			
		||||
	let res = {
 | 
			
		||||
		let caller = |data| {
 | 
			
		||||
			let (result, proof) = caller(contract_address, data)?;
 | 
			
		||||
			*epoch_proof.borrow_mut() = Some(encode_first_proof(header, &proof));
 | 
			
		||||
			Ok(result)
 | 
			
		||||
		};
 | 
			
		||||
 | 
			
		||||
		provider.functions().get_validators().call(&caller)
 | 
			
		||||
			.map_err(|err| err.to_string())
 | 
			
		||||
	let validators = {
 | 
			
		||||
		let (data, decoder) = validator_set::functions::get_validators::call();
 | 
			
		||||
		let (value, proof) = caller(contract_address, data)?;
 | 
			
		||||
		*epoch_proof.borrow_mut() = Some(encode_first_proof(header, &proof));
 | 
			
		||||
		decoder.decode(&value).map_err(|e| e.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",
 | 
			
		||||
			validators.len(), proof.len());
 | 
			
		||||
	trace!(target: "engine", "obtained proof for initial set: {} validators, {} bytes",
 | 
			
		||||
		validators.len(), proof.len());
 | 
			
		||||
 | 
			
		||||
		info!(target: "engine", "Signal for switch to contract-based validator set.");
 | 
			
		||||
		info!(target: "engine", "Initial contract validators: {:?}", validators);
 | 
			
		||||
	info!(target: "engine", "Signal for switch to contract-based validator set.");
 | 
			
		||||
	info!(target: "engine", "Initial contract validators: {:?}", validators);
 | 
			
		||||
 | 
			
		||||
		proof
 | 
			
		||||
	})
 | 
			
		||||
	Ok(proof)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl ValidatorSafeContract {
 | 
			
		||||
@ -200,7 +193,6 @@ impl ValidatorSafeContract {
 | 
			
		||||
		ValidatorSafeContract {
 | 
			
		||||
			contract_address,
 | 
			
		||||
			validators: RwLock::new(MemoryLruCache::new(MEMOIZE_CAPACITY)),
 | 
			
		||||
			provider: validator_set::ValidatorSet::default(),
 | 
			
		||||
			client: RwLock::new(None),
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
@ -208,8 +200,11 @@ impl ValidatorSafeContract {
 | 
			
		||||
	/// Queries the state and gets the set of validators.
 | 
			
		||||
	fn get_list(&self, caller: &Call) -> Option<SimpleList> {
 | 
			
		||||
		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) => {
 | 
			
		||||
				debug!(target: "engine", "Set of validators obtained: {:?}", new);
 | 
			
		||||
				Some(SimpleList::new(new))
 | 
			
		||||
@ -259,7 +254,6 @@ impl ValidatorSafeContract {
 | 
			
		||||
				log.topics[1] == *header.parent_hash()
 | 
			
		||||
		};
 | 
			
		||||
 | 
			
		||||
		let event = self.provider.events().initiate_change();
 | 
			
		||||
		//// iterate in reverse because only the _last_ change in a given
 | 
			
		||||
		//// block actually has any effect.
 | 
			
		||||
		//// the contract should only increment the nonce once.
 | 
			
		||||
@ -269,7 +263,7 @@ impl ValidatorSafeContract {
 | 
			
		||||
			.flat_map(|r| r.logs.iter())
 | 
			
		||||
			.filter(move |l| check_log(l))
 | 
			
		||||
			.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
 | 
			
		||||
@ -296,7 +290,7 @@ impl ValidatorSet for ValidatorSafeContract {
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	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)
 | 
			
		||||
			.map(|_| ())
 | 
			
		||||
			.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> {
 | 
			
		||||
		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>> {
 | 
			
		||||
@ -322,7 +316,6 @@ impl ValidatorSet for ValidatorSafeContract {
 | 
			
		||||
			let state_proof = Arc::new(StateProof {
 | 
			
		||||
				contract_address: self.contract_address,
 | 
			
		||||
				header: header.clone(),
 | 
			
		||||
				provider: validator_set::ValidatorSet::default(),
 | 
			
		||||
			});
 | 
			
		||||
			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 number = old_header.number();
 | 
			
		||||
			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)?;
 | 
			
		||||
 | 
			
		||||
			trace!(target: "engine", "extracted epoch set at #{}: {} addresses",
 | 
			
		||||
 | 
			
		||||
@ -18,16 +18,15 @@
 | 
			
		||||
 | 
			
		||||
use client::{RegistryInfo, CallContract, BlockId};
 | 
			
		||||
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";
 | 
			
		||||
 | 
			
		||||
/// Service transactions checker.
 | 
			
		||||
#[derive(Default, Clone)]
 | 
			
		||||
pub struct ServiceTransactionChecker {
 | 
			
		||||
	contract: service_transaction::ServiceTransaction,
 | 
			
		||||
}
 | 
			
		||||
pub struct ServiceTransactionChecker;
 | 
			
		||||
 | 
			
		||||
impl ServiceTransactionChecker {
 | 
			
		||||
	/// 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);
 | 
			
		||||
 | 
			
		||||
		self.contract.functions()
 | 
			
		||||
			.certified()
 | 
			
		||||
			.call(sender, &|data| client.call_contract(BlockId::Latest, address, data))
 | 
			
		||||
			.map_err(|e| e.to_string())
 | 
			
		||||
		let (data, decoder) = service_transaction::functions::certified::call(sender);
 | 
			
		||||
		let value = client.call_contract(BlockId::Latest, address, data)?;
 | 
			
		||||
		decoder.decode(&value).map_err(|e| e.to_string())
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -32,7 +32,7 @@ use tempdir::TempDir;
 | 
			
		||||
use ethereum_types::Address;
 | 
			
		||||
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 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]
 | 
			
		||||
		};
 | 
			
		||||
 | 
			
		||||
		let contract = test_validator_set::ValidatorSet::default();
 | 
			
		||||
 | 
			
		||||
		// apply all transitions.
 | 
			
		||||
		for transition in transitions {
 | 
			
		||||
			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,
 | 
			
		||||
				};
 | 
			
		||||
 | 
			
		||||
				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 transaction = Transaction {
 | 
			
		||||
					nonce: *nonce,
 | 
			
		||||
 | 
			
		||||
@ -18,6 +18,7 @@
 | 
			
		||||
 | 
			
		||||
use ethereum_types::{H256, U256, Address};
 | 
			
		||||
use lru_cache::LruCache;
 | 
			
		||||
use ethabi::FunctionOutputDecoder;
 | 
			
		||||
 | 
			
		||||
use client::{BlockInfo, CallContract, BlockId};
 | 
			
		||||
use parking_lot::Mutex;
 | 
			
		||||
@ -26,8 +27,8 @@ use transaction::{Action, SignedTransaction};
 | 
			
		||||
use types::BlockNumber;
 | 
			
		||||
use hash::KECCAK_EMPTY;
 | 
			
		||||
 | 
			
		||||
use_contract!(transact_acl_deprecated, "TransactAclDeprecated", "res/contracts/tx_acl_deprecated.json");
 | 
			
		||||
use_contract!(transact_acl, "TransactAcl", "res/contracts/tx_acl.json");
 | 
			
		||||
use_contract!(transact_acl_deprecated, "res/contracts/tx_acl_deprecated.json");
 | 
			
		||||
use_contract!(transact_acl, "res/contracts/tx_acl.json");
 | 
			
		||||
 | 
			
		||||
const MAX_CACHE_SIZE: usize = 4096;
 | 
			
		||||
 | 
			
		||||
@ -42,8 +43,6 @@ mod tx_permissions {
 | 
			
		||||
 | 
			
		||||
/// Connection filter that uses a contract to manage permissions.
 | 
			
		||||
pub struct TransactionFilter {
 | 
			
		||||
	contract_deprecated: transact_acl_deprecated::TransactAclDeprecated,
 | 
			
		||||
	contract: transact_acl::TransactAcl,
 | 
			
		||||
	contract_address: Address,
 | 
			
		||||
	transition_block: BlockNumber,
 | 
			
		||||
	permission_cache: Mutex<LruCache<(H256, Address), u32>>,
 | 
			
		||||
@ -55,8 +54,6 @@ impl TransactionFilter {
 | 
			
		||||
	pub fn from_params(params: &CommonParams) -> Option<TransactionFilter> {
 | 
			
		||||
		params.transaction_permission_contract.map(|address|
 | 
			
		||||
			TransactionFilter {
 | 
			
		||||
				contract_deprecated: transact_acl_deprecated::TransactAclDeprecated::default(),
 | 
			
		||||
				contract: transact_acl::TransactAcl::default(),
 | 
			
		||||
				contract_address: address,
 | 
			
		||||
				transition_block: params.transaction_permission_contract_transition,
 | 
			
		||||
				permission_cache: Mutex::new(LruCache::new(MAX_CACHE_SIZE)),
 | 
			
		||||
@ -91,10 +88,8 @@ impl TransactionFilter {
 | 
			
		||||
 | 
			
		||||
		let contract_address = self.contract_address;
 | 
			
		||||
		let contract_version = contract_version_cache.get_mut(parent_hash).and_then(|v| *v).or_else(||  {
 | 
			
		||||
			self.contract.functions()
 | 
			
		||||
				.contract_version()
 | 
			
		||||
				.call(&|data| client.call_contract(BlockId::Hash(*parent_hash), contract_address, data))
 | 
			
		||||
				.ok()
 | 
			
		||||
			let (data, decoder) = transact_acl::functions::contract_version::call();
 | 
			
		||||
			decoder.decode(&client.call_contract(BlockId::Hash(*parent_hash), contract_address, data).ok()?).ok()
 | 
			
		||||
		});
 | 
			
		||||
		contract_version_cache.insert(*parent_hash, contract_version);
 | 
			
		||||
 | 
			
		||||
@ -104,14 +99,16 @@ impl TransactionFilter {
 | 
			
		||||
				let version_u64 = version.low_u64();
 | 
			
		||||
				trace!(target: "tx_filter", "Version of tx permission contract: {}", version);
 | 
			
		||||
				match version_u64 {
 | 
			
		||||
					2 => self.contract.functions()
 | 
			
		||||
						.allowed_tx_types()
 | 
			
		||||
						.call(sender, to, value, &|data| client.call_contract(BlockId::Hash(*parent_hash), contract_address, data))
 | 
			
		||||
						.map(|(p, f)| (p.low_u32(), f))
 | 
			
		||||
						.unwrap_or_else(|e| {
 | 
			
		||||
							error!(target: "tx_filter", "Error calling tx permissions contract: {:?}", e);
 | 
			
		||||
							(tx_permissions::NONE, true)
 | 
			
		||||
						}),
 | 
			
		||||
					2 => {
 | 
			
		||||
						let (data, decoder) = transact_acl::functions::allowed_tx_types::call(sender, to, value);
 | 
			
		||||
						client.call_contract(BlockId::Hash(*parent_hash), contract_address, data)
 | 
			
		||||
							.and_then(|value| decoder.decode(&value).map_err(|e| e.to_string()))
 | 
			
		||||
							.map(|(p, f)| (p.low_u32(), f))
 | 
			
		||||
							.unwrap_or_else(|e| {
 | 
			
		||||
								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");
 | 
			
		||||
						(tx_permissions::NONE, true)
 | 
			
		||||
@ -120,14 +117,14 @@ impl TransactionFilter {
 | 
			
		||||
			},
 | 
			
		||||
			None => {
 | 
			
		||||
				trace!(target: "tx_filter", "Fallback to the deprecated version of tx permission contract");
 | 
			
		||||
				(self.contract_deprecated.functions()
 | 
			
		||||
					 .allowed_tx_types()
 | 
			
		||||
					 .call(sender, &|data| client.call_contract(BlockId::Hash(*parent_hash), contract_address, data))
 | 
			
		||||
					 .map(|p| p.low_u32())
 | 
			
		||||
					 .unwrap_or_else(|e| {
 | 
			
		||||
						 error!(target: "tx_filter", "Error calling tx permissions contract: {:?}", e);
 | 
			
		||||
						 tx_permissions::NONE
 | 
			
		||||
					 }), true)
 | 
			
		||||
				let (data, decoder) = transact_acl_deprecated::functions::allowed_tx_types::call(sender);
 | 
			
		||||
				(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())
 | 
			
		||||
					.unwrap_or_else(|e| {
 | 
			
		||||
						error!(target: "tx_filter", "Error calling tx permissions contract: {:?}", e);
 | 
			
		||||
						tx_permissions::NONE
 | 
			
		||||
					}), true)
 | 
			
		||||
			}
 | 
			
		||||
		};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -21,9 +21,9 @@ parity-reactor = { path = "../util/reactor" }
 | 
			
		||||
keccak-hash = "0.1"
 | 
			
		||||
registrar = { path = "../registrar" }
 | 
			
		||||
 | 
			
		||||
ethabi = "5.1.2"
 | 
			
		||||
ethabi-derive = "5.1.3"
 | 
			
		||||
ethabi-contract = "5.1.1"
 | 
			
		||||
ethabi = "6.0"
 | 
			
		||||
ethabi-derive = "6.0"
 | 
			
		||||
ethabi-contract = "6.0"
 | 
			
		||||
 | 
			
		||||
[dev-dependencies]
 | 
			
		||||
hyper = "0.11"
 | 
			
		||||
 | 
			
		||||
@ -26,7 +26,7 @@ use futures::future::Either;
 | 
			
		||||
use ethereum_types::{H256, Address};
 | 
			
		||||
use registrar::{Registrar, RegistrarClient, Asynchronous};
 | 
			
		||||
 | 
			
		||||
use_contract!(urlhint, "Urlhint", "res/urlhint.json");
 | 
			
		||||
use_contract!(urlhint, "res/urlhint.json");
 | 
			
		||||
 | 
			
		||||
const COMMIT_LEN: usize = 20;
 | 
			
		||||
const GITHUB_HINT: &'static str = "githubhint";
 | 
			
		||||
@ -100,16 +100,14 @@ pub trait URLHint: Send + Sync {
 | 
			
		||||
 | 
			
		||||
/// `URLHintContract` API
 | 
			
		||||
pub struct URLHintContract {
 | 
			
		||||
	urlhint: urlhint::Urlhint,
 | 
			
		||||
	registrar: Registrar,
 | 
			
		||||
	client: Arc<RegistrarClient<Call=Asynchronous>>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl URLHintContract {
 | 
			
		||||
	/// Creates new `URLHintContract`
 | 
			
		||||
		pub fn new(client: Arc<RegistrarClient<Call=Asynchronous>>) -> Self {
 | 
			
		||||
	pub fn new(client: Arc<RegistrarClient<Call=Asynchronous>>) -> Self {
 | 
			
		||||
		URLHintContract {
 | 
			
		||||
			urlhint: urlhint::Urlhint::default(),
 | 
			
		||||
			registrar: Registrar::new(client.clone()),
 | 
			
		||||
			client: client,
 | 
			
		||||
		}
 | 
			
		||||
@ -162,14 +160,13 @@ fn decode_urlhint_output(output: (String, [u8; 20], Address)) -> Option<URLHintR
 | 
			
		||||
 | 
			
		||||
impl URLHint for URLHintContract {
 | 
			
		||||
	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 future = self.registrar.get_address(GITHUB_HINT)
 | 
			
		||||
			.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)
 | 
			
		||||
					.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);
 | 
			
		||||
				Either::B(result)
 | 
			
		||||
			} else {
 | 
			
		||||
 | 
			
		||||
@ -7,7 +7,7 @@ authors = ["Parity Technologies <admin@parity.io>"]
 | 
			
		||||
 | 
			
		||||
[dependencies]
 | 
			
		||||
futures = "0.1"
 | 
			
		||||
ethabi = "5.1.2"
 | 
			
		||||
ethabi-derive = "5.1.3"
 | 
			
		||||
ethabi-contract = "5.1.1"
 | 
			
		||||
ethabi = "6.0"
 | 
			
		||||
ethabi-derive = "6.0"
 | 
			
		||||
ethabi-contract = "6.0"
 | 
			
		||||
keccak-hash = "0.1"
 | 
			
		||||
 | 
			
		||||
@ -19,7 +19,7 @@ use ethabi::{Address, Bytes};
 | 
			
		||||
use std::sync::Arc;
 | 
			
		||||
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
 | 
			
		||||
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
 | 
			
		||||
/// which in turn generates an address when a client requests one
 | 
			
		||||
pub struct Registrar {
 | 
			
		||||
	registrar: registry::Registry,
 | 
			
		||||
	client: Arc<RegistrarClient<Call=Asynchronous>>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -38,7 +37,6 @@ impl Registrar {
 | 
			
		||||
	/// Registrar constructor
 | 
			
		||||
	pub fn new(client: Arc<RegistrarClient<Call=Asynchronous>>) -> Self {
 | 
			
		||||
		Self {
 | 
			
		||||
			registrar: registry::Registry::default(),
 | 
			
		||||
			client: client,
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
@ -51,14 +49,11 @@ impl Registrar {
 | 
			
		||||
			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 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| {
 | 
			
		||||
			address_fetcher.output(&address)
 | 
			
		||||
		}
 | 
			
		||||
		.map_err(|e| e.to_string()));
 | 
			
		||||
		let future = self.client.call_contract(registrar_address, id)
 | 
			
		||||
			.and_then(move |address| registrar::functions::get_address::decode_output(&address).map_err(|e| e.to_string()));
 | 
			
		||||
 | 
			
		||||
		Box::new(future)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@ -34,9 +34,9 @@ kvdb = "0.1"
 | 
			
		||||
keccak-hash = "0.1"
 | 
			
		||||
ethkey = { path = "../ethkey" }
 | 
			
		||||
lazy_static = "1.0"
 | 
			
		||||
ethabi = "5.1.2"
 | 
			
		||||
ethabi-derive = "5.1.3"
 | 
			
		||||
ethabi-contract = "5.1.1"
 | 
			
		||||
ethabi = "6.0"
 | 
			
		||||
ethabi-derive = "6.0"
 | 
			
		||||
ethabi-contract = "6.0"
 | 
			
		||||
 | 
			
		||||
[dev-dependencies]
 | 
			
		||||
ethcore = { path = "../ethcore", features = ["test-helpers"] }
 | 
			
		||||
 | 
			
		||||
@ -20,11 +20,12 @@ use std::time::Duration;
 | 
			
		||||
use parking_lot::{Mutex, RwLock};
 | 
			
		||||
use ethcore::client::{BlockId, ChainNotify, ChainRoute, CallContract};
 | 
			
		||||
use ethereum_types::{H256, Address};
 | 
			
		||||
use ethabi::FunctionOutputDecoder;
 | 
			
		||||
use bytes::Bytes;
 | 
			
		||||
use trusted_client::TrustedClient;
 | 
			
		||||
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";
 | 
			
		||||
 | 
			
		||||
@ -48,8 +49,6 @@ struct CachedContract {
 | 
			
		||||
	address_source: ContractAddress,
 | 
			
		||||
	/// Current contract address.
 | 
			
		||||
	contract_address: Option<Address>,
 | 
			
		||||
	/// Contract at given address.
 | 
			
		||||
	contract: acl_storage::AclStorage,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Dummy ACL storage implementation (check always passed).
 | 
			
		||||
@ -91,7 +90,6 @@ impl CachedContract {
 | 
			
		||||
			client,
 | 
			
		||||
			address_source,
 | 
			
		||||
			contract_address: None,
 | 
			
		||||
			contract: acl_storage::AclStorage::default(),
 | 
			
		||||
		};
 | 
			
		||||
		contract.update_contract_address();
 | 
			
		||||
		contract
 | 
			
		||||
@ -112,10 +110,10 @@ impl CachedContract {
 | 
			
		||||
			// call contract to check accesss
 | 
			
		||||
			match self.contract_address {
 | 
			
		||||
				Some(contract_address) => {
 | 
			
		||||
					let do_call = |data| client.call_contract(BlockId::Latest, contract_address, data);
 | 
			
		||||
					self.contract.functions()
 | 
			
		||||
						.check_permissions()
 | 
			
		||||
						.call(requester, document.clone(), &do_call)
 | 
			
		||||
					let (encoded, decoder) = acl_storage::functions::check_permissions::call(requester, document.clone());
 | 
			
		||||
					let d = client.call_contract(BlockId::Latest, contract_address, encoded)
 | 
			
		||||
						.map_err(|e| Error::Internal(format!("ACL checker call error: {}", e.to_string())))?;
 | 
			
		||||
					decoder.decode(&d)
 | 
			
		||||
						.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())),
 | 
			
		||||
 | 
			
		||||
@ -19,15 +19,16 @@ use std::net::SocketAddr;
 | 
			
		||||
use std::collections::{BTreeMap, HashSet};
 | 
			
		||||
use std::time::Duration;
 | 
			
		||||
use parking_lot::Mutex;
 | 
			
		||||
use ethabi::FunctionOutputDecoder;
 | 
			
		||||
use ethcore::client::{Client, BlockChainClient, BlockId, ChainNotify, ChainRoute, CallContract};
 | 
			
		||||
use ethkey::public_to_address;
 | 
			
		||||
use ethereum_types::{H256, Address};
 | 
			
		||||
use ethkey::public_to_address;
 | 
			
		||||
use bytes::Bytes;
 | 
			
		||||
use types::{Error, Public, NodeAddress, NodeId};
 | 
			
		||||
use trusted_client::TrustedClient;
 | 
			
		||||
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.
 | 
			
		||||
const KEY_SERVER_SET_CONTRACT_REGISTRY_NAME: &'static str = "secretstore_server_set";
 | 
			
		||||
@ -104,8 +105,6 @@ struct CachedContract {
 | 
			
		||||
	contract_address_source: Option<ContractAddress>,
 | 
			
		||||
	/// Current contract address.
 | 
			
		||||
	contract_address: Option<Address>,
 | 
			
		||||
	/// Contract interface.
 | 
			
		||||
	contract: key_server::KeyServerSet,
 | 
			
		||||
	/// Is auto-migrate enabled?
 | 
			
		||||
	auto_migrate_enabled: bool,
 | 
			
		||||
	/// 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>;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(Default)]
 | 
			
		||||
struct CurrentKeyServerSubset {
 | 
			
		||||
	read_list: key_server::functions::GetCurrentKeyServers,
 | 
			
		||||
	read_public: key_server::functions::GetCurrentKeyServerPublic,
 | 
			
		||||
	read_address: key_server::functions::GetCurrentKeyServerAddress,
 | 
			
		||||
}
 | 
			
		||||
struct CurrentKeyServerSubset;
 | 
			
		||||
 | 
			
		||||
impl <F: Fn(Vec<u8>) -> Result<Vec<u8>, String>> KeyServerSubset<F> for CurrentKeyServerSubset {
 | 
			
		||||
	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> {
 | 
			
		||||
		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> {
 | 
			
		||||
		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 {
 | 
			
		||||
	read_list: key_server::functions::GetMigrationKeyServers,
 | 
			
		||||
	read_public: key_server::functions::GetMigrationKeyServerPublic,
 | 
			
		||||
	read_address: key_server::functions::GetMigrationKeyServerAddress,
 | 
			
		||||
}
 | 
			
		||||
struct MigrationKeyServerSubset;
 | 
			
		||||
 | 
			
		||||
impl <F: Fn(Vec<u8>) -> Result<Vec<u8>, String>> KeyServerSubset<F> for MigrationKeyServerSubset {
 | 
			
		||||
	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> {
 | 
			
		||||
		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> {
 | 
			
		||||
		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 {
 | 
			
		||||
	read_list: key_server::functions::GetNewKeyServers,
 | 
			
		||||
	read_public: key_server::functions::GetNewKeyServerPublic,
 | 
			
		||||
	read_address: key_server::functions::GetNewKeyServerAddress,
 | 
			
		||||
}
 | 
			
		||||
struct NewKeyServerSubset;
 | 
			
		||||
 | 
			
		||||
impl <F: Fn(Vec<u8>) -> Result<Vec<u8>, String>> KeyServerSubset<F> for NewKeyServerSubset {
 | 
			
		||||
	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> {
 | 
			
		||||
		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> {
 | 
			
		||||
		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,
 | 
			
		||||
			contract_address_source: contract_address_source,
 | 
			
		||||
			contract_address: None,
 | 
			
		||||
			contract: key_server::KeyServerSet::default(),
 | 
			
		||||
			auto_migrate_enabled: auto_migrate_enabled,
 | 
			
		||||
			future_new_set: None,
 | 
			
		||||
			confirm_migration_tx: None,
 | 
			
		||||
@ -313,7 +305,7 @@ impl CachedContract {
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			// 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
 | 
			
		||||
			match self.client.transact_contract(*contract_address, transaction_data) {
 | 
			
		||||
@ -334,7 +326,7 @@ impl CachedContract {
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			// 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
 | 
			
		||||
			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 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
 | 
			
		||||
		let (new_set, migration) = match self.auto_migrate_enabled {
 | 
			
		||||
			true => {
 | 
			
		||||
				let new_set = Self::read_key_server_set(NewKeyServerSubset::default(), &do_call);
 | 
			
		||||
				let migration_set = Self::read_key_server_set(MigrationKeyServerSubset::default(), &do_call);
 | 
			
		||||
				let new_set = Self::read_key_server_set(NewKeyServerSubset, &do_call);
 | 
			
		||||
				let migration_set = Self::read_key_server_set(MigrationKeyServerSubset, &do_call);
 | 
			
		||||
 | 
			
		||||
				let migration_id = match migration_set.is_empty() {
 | 
			
		||||
					false => self.contract.functions().get_migration_id().call(&do_call)
 | 
			
		||||
						.map_err(|err| { trace!(target: "secretstore", "Error {} reading migration id from contract", err); err })
 | 
			
		||||
						.ok(),
 | 
			
		||||
					false => {
 | 
			
		||||
						let (encoded, decoder) = key_server::functions::get_migration_id::call();
 | 
			
		||||
						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,
 | 
			
		||||
				};
 | 
			
		||||
 | 
			
		||||
				let migration_master = match migration_set.is_empty() {
 | 
			
		||||
					false => self.contract.functions().get_migration_master().call(&do_call)
 | 
			
		||||
						.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()),
 | 
			
		||||
					false => {
 | 
			
		||||
						let (encoded, decoder) = key_server::functions::get_migration_master::call();
 | 
			
		||||
						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 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,
 | 
			
		||||
				};
 | 
			
		||||
 | 
			
		||||
				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()) =>
 | 
			
		||||
						self.contract.functions().is_migration_confirmed().call(self.self_key_pair.address(), &do_call)
 | 
			
		||||
					false if current_set.contains_key(self.self_key_pair.public()) || migration_set.contains_key(self.self_key_pair.public()) => {
 | 
			
		||||
						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 })
 | 
			
		||||
							.ok(),
 | 
			
		||||
							.ok()
 | 
			
		||||
					},
 | 
			
		||||
					_ => None,
 | 
			
		||||
				};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -17,8 +17,9 @@
 | 
			
		||||
use std::sync::Arc;
 | 
			
		||||
use parking_lot::RwLock;
 | 
			
		||||
use ethabi::RawLog;
 | 
			
		||||
use ethcore::filter::Filter;
 | 
			
		||||
use ethabi::FunctionOutputDecoder;
 | 
			
		||||
use ethcore::client::{Client, BlockChainClient, BlockId, CallContract};
 | 
			
		||||
use ethcore::filter::Filter;
 | 
			
		||||
use ethkey::{Public, public_to_address};
 | 
			
		||||
use hash::keccak;
 | 
			
		||||
use bytes::Bytes;
 | 
			
		||||
@ -29,7 +30,7 @@ use trusted_client::TrustedClient;
 | 
			
		||||
use helpers::{get_confirmed_block_hash, REQUEST_CONFIRMATIONS_REQUIRED};
 | 
			
		||||
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.
 | 
			
		||||
pub const SERVICE_CONTRACT_REGISTRY_NAME: &'static str = "secretstore_service";
 | 
			
		||||
@ -102,8 +103,6 @@ pub struct OnChainServiceContract {
 | 
			
		||||
	/// Contract address source.
 | 
			
		||||
	address_source: ContractAddress,
 | 
			
		||||
	/// Contract.
 | 
			
		||||
	contract: service::Service,
 | 
			
		||||
	/// Contract.
 | 
			
		||||
	data: RwLock<ServiceData>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -143,7 +142,6 @@ impl OnChainServiceContract {
 | 
			
		||||
			self_key_pair: self_key_pair,
 | 
			
		||||
			name: name,
 | 
			
		||||
			address_source: address_source,
 | 
			
		||||
			contract: service::Service::default(),
 | 
			
		||||
			data: RwLock::new(ServiceData {
 | 
			
		||||
				contract_address: None,
 | 
			
		||||
				last_log_block: None,
 | 
			
		||||
@ -156,8 +154,8 @@ impl OnChainServiceContract {
 | 
			
		||||
 | 
			
		||||
	/// 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>
 | 
			
		||||
		where C: FnOnce(&Client, &Address, &service::Service, &ServerKeyId, &Address) -> bool,
 | 
			
		||||
			P: FnOnce(&Client, &Address, &service::Service) -> Result<Bytes, String> {
 | 
			
		||||
		where C: FnOnce(&Client, &Address, &ServerKeyId, &Address) -> bool,
 | 
			
		||||
			P: FnOnce(&Client, &Address) -> Result<Bytes, String> {
 | 
			
		||||
		// only publish if contract address is set && client is online
 | 
			
		||||
		let client = match self.client.get() {
 | 
			
		||||
			Some(client) => client,
 | 
			
		||||
@ -168,12 +166,12 @@ impl OnChainServiceContract {
 | 
			
		||||
		// failing is ok here - it could be that enough confirmations have been recevied
 | 
			
		||||
		// or key has been requested using HTTP API
 | 
			
		||||
		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(());
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// prepare transaction data
 | 
			
		||||
		let transaction_data = prepare_tx(&*client, origin, &self.contract)?;
 | 
			
		||||
		let transaction_data = prepare_tx(&*client, origin)?;
 | 
			
		||||
 | 
			
		||||
		// send transaction
 | 
			
		||||
		self.client.transact_contract(
 | 
			
		||||
@ -189,18 +187,17 @@ impl OnChainServiceContract {
 | 
			
		||||
 | 
			
		||||
	/// Create task-specific pending requests iterator.
 | 
			
		||||
	fn create_pending_requests_iterator<
 | 
			
		||||
		C: 'static + Fn(&Client, &Address, &service::Service, &BlockId) -> Result<U256, String>,
 | 
			
		||||
		R: 'static + Fn(&NodeKeyPair, &Client, &Address, &service::Service, &BlockId, U256) -> Result<(bool, ServiceTask), String>
 | 
			
		||||
		C: 'static + Fn(&Client, &Address, &BlockId) -> Result<U256, 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)>> {
 | 
			
		||||
		let contract = service::Service::default();
 | 
			
		||||
		get_count(&*client, contract_address, &contract, block)
 | 
			
		||||
		get_count(&*client, contract_address, block)
 | 
			
		||||
			.map(|count| {
 | 
			
		||||
				let client = client.clone();
 | 
			
		||||
				let self_key_pair = self.self_key_pair.clone();
 | 
			
		||||
				let contract_address = contract_address.clone();
 | 
			
		||||
				let block = block.clone();
 | 
			
		||||
				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| {
 | 
			
		||||
							warn!(target: "secretstore", "{}: reading pending request failed: {}",
 | 
			
		||||
								self_key_pair.public(), error);
 | 
			
		||||
@ -289,15 +286,15 @@ impl ServiceContract for OnChainServiceContract {
 | 
			
		||||
			.filter_map(|log| {
 | 
			
		||||
				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 {
 | 
			
		||||
					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 {
 | 
			
		||||
					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 {
 | 
			
		||||
					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 {
 | 
			
		||||
					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 {
 | 
			
		||||
					DocumentKeyShadowRetrievalService::parse_personal_request_log(&address, &self.contract, raw_log)
 | 
			
		||||
					DocumentKeyShadowRetrievalService::parse_personal_request_log(&address, raw_log)
 | 
			
		||||
				} else {
 | 
			
		||||
					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> {
 | 
			
		||||
		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> {
 | 
			
		||||
		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> {
 | 
			
		||||
		let threshold = serialize_threshold(threshold)?;
 | 
			
		||||
		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> {
 | 
			
		||||
		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> {
 | 
			
		||||
		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> {
 | 
			
		||||
		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> {
 | 
			
		||||
		let threshold = serialize_threshold(threshold)?;
 | 
			
		||||
		self.send_contract_transaction("publish_retrieved_document_key_common", origin, server_key_id,
 | 
			
		||||
			|client, contract_address, contract, server_key_id, key_server|
 | 
			
		||||
				DocumentKeyShadowRetrievalService::is_response_required(client, contract_address, contract, server_key_id, requester, key_server),
 | 
			
		||||
			|_, _, service|
 | 
			
		||||
				Ok(DocumentKeyShadowRetrievalService::prepare_pubish_common_tx_data(service, server_key_id, requester, common_point, threshold))
 | 
			
		||||
			|client, contract_address, server_key_id, key_server|
 | 
			
		||||
				DocumentKeyShadowRetrievalService::is_response_required(client, contract_address, server_key_id, requester, key_server),
 | 
			
		||||
			|_, _|
 | 
			
		||||
				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> {
 | 
			
		||||
		self.send_contract_transaction("publish_retrieved_document_key_personal", origin, server_key_id, |_, _, _, _, _| true,
 | 
			
		||||
		move |client, address, service|
 | 
			
		||||
			DocumentKeyShadowRetrievalService::prepare_pubish_personal_tx_data(client, address, service, server_key_id, requester, participants, decrypted_secret, shadow)
 | 
			
		||||
		self.send_contract_transaction("publish_retrieved_document_key_personal", origin, server_key_id, |_, _, _, _| true,
 | 
			
		||||
		move |client, address|
 | 
			
		||||
			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> {
 | 
			
		||||
		self.send_contract_transaction("publish_document_key_retrieval_error", origin, server_key_id,
 | 
			
		||||
			|client, contract_address, contract, server_key_id, key_server|
 | 
			
		||||
				DocumentKeyShadowRetrievalService::is_response_required(client, contract_address, contract, server_key_id, requester, key_server),
 | 
			
		||||
			|_, _, service|
 | 
			
		||||
				Ok(DocumentKeyShadowRetrievalService::prepare_error_tx_data(service, server_key_id, requester))
 | 
			
		||||
			|client, contract_address, server_key_id, key_server|
 | 
			
		||||
				DocumentKeyShadowRetrievalService::is_response_required(client, contract_address, server_key_id, requester, key_server),
 | 
			
		||||
			|_, _|
 | 
			
		||||
				Ok(DocumentKeyShadowRetrievalService::prepare_error_tx_data(server_key_id, requester))
 | 
			
		||||
		)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
@ -449,318 +446,280 @@ pub fn mask_topics(mask: &ApiMask) -> Vec<H256> {
 | 
			
		||||
 | 
			
		||||
impl ServerKeyGenerationService {
 | 
			
		||||
	/// Parse request log entry.
 | 
			
		||||
	pub fn parse_log(origin: &Address, contract: &service::Service, raw_log: RawLog) -> Result<ServiceTask, String> {
 | 
			
		||||
		let event = contract.events().server_key_generation_requested();
 | 
			
		||||
		match event.parse_log(raw_log) {
 | 
			
		||||
	pub fn parse_log(origin: &Address, raw_log: RawLog) -> Result<ServiceTask, String> {
 | 
			
		||||
		match service::events::server_key_generation_requested::parse_log(raw_log) {
 | 
			
		||||
			Ok(l) => Ok(ServiceTask::GenerateServerKey(origin.clone(), l.server_key_id, l.author, parse_threshold(l.threshold)?)),
 | 
			
		||||
			Err(e) => Err(format!("{}", e)),
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/// 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
 | 
			
		||||
		let do_call = |data| client.call_contract(BlockId::Latest, *contract_address, data);
 | 
			
		||||
		contract.functions()
 | 
			
		||||
			.is_server_key_generation_response_required()
 | 
			
		||||
			.call(*server_key_id, key_server.clone(), &do_call)
 | 
			
		||||
			.unwrap_or(true)
 | 
			
		||||
		let (encoded, decoder) = service::functions::is_server_key_generation_response_required::call(*server_key_id, *key_server);
 | 
			
		||||
		match client.call_contract(BlockId::Latest, *contract_address, encoded) {
 | 
			
		||||
			Err(_) => true,
 | 
			
		||||
			Ok(data) => decoder.decode(&data).unwrap_or(true)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/// Prepare publish key transaction data.
 | 
			
		||||
	pub fn prepare_pubish_tx_data(contract: &service::Service, server_key_id: &ServerKeyId, server_key_public: &Public) -> Bytes {
 | 
			
		||||
		contract.functions()
 | 
			
		||||
			.server_key_generated()
 | 
			
		||||
			.input(*server_key_id, server_key_public.to_vec())
 | 
			
		||||
	pub fn prepare_pubish_tx_data(server_key_id: &ServerKeyId, server_key_public: &Public) -> Bytes {
 | 
			
		||||
		service::functions::server_key_generated::encode_input(*server_key_id, server_key_public.to_vec())
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/// Prepare error transaction data.
 | 
			
		||||
	pub fn prepare_error_tx_data(contract: &service::Service, server_key_id: &ServerKeyId) -> Bytes {
 | 
			
		||||
		contract.functions()
 | 
			
		||||
			.server_key_generation_error()
 | 
			
		||||
			.input(*server_key_id)
 | 
			
		||||
	pub fn prepare_error_tx_data(server_key_id: &ServerKeyId) -> Bytes {
 | 
			
		||||
		service::functions::server_key_generation_error::encode_input(*server_key_id)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/// Read pending requests count.
 | 
			
		||||
	fn read_pending_requests_count(client: &Client, contract_address: &Address, _contract: &service::Service, block: &BlockId) -> Result<U256, String> {
 | 
			
		||||
		let do_call = |data| client.call_contract(block.clone(), contract_address.clone(), data);
 | 
			
		||||
		let contract = service::Service::default();
 | 
			
		||||
		contract.functions()
 | 
			
		||||
			.server_key_generation_requests_count()
 | 
			
		||||
			.call(&do_call)
 | 
			
		||||
			.map_err(|error| format!("{}", error))
 | 
			
		||||
	fn read_pending_requests_count(client: &Client, contract_address: &Address, block: &BlockId) -> Result<U256, String> {
 | 
			
		||||
		let (encoded, decoder) = service::functions::server_key_generation_requests_count::call();
 | 
			
		||||
		decoder.decode(&client.call_contract(*block, *contract_address, encoded)?)
 | 
			
		||||
			.map_err(|e| e.to_string())
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/// 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 do_call = |d| client.call_contract(block.clone(), contract_address.clone(), d);
 | 
			
		||||
		contract.functions()
 | 
			
		||||
			.get_server_key_generation_request()
 | 
			
		||||
			.call(index, &do_call)
 | 
			
		||||
			.map_err(|error| format!("{}", error))
 | 
			
		||||
			.and_then(|(server_key_id, author, threshold)| parse_threshold(threshold)
 | 
			
		||||
				.map(|threshold| (server_key_id, author, threshold)))
 | 
			
		||||
			.and_then(|(server_key_id, author, threshold)| contract.functions()
 | 
			
		||||
				.is_server_key_generation_response_required()
 | 
			
		||||
				.call(server_key_id.clone(), self_address, &do_call)
 | 
			
		||||
				.map(|not_confirmed| (
 | 
			
		||||
					not_confirmed,
 | 
			
		||||
					ServiceTask::GenerateServerKey(
 | 
			
		||||
						contract_address.clone(),
 | 
			
		||||
						server_key_id,
 | 
			
		||||
						author,
 | 
			
		||||
						threshold,
 | 
			
		||||
					)))
 | 
			
		||||
				.map_err(|error| format!("{}", error)))
 | 
			
		||||
 | 
			
		||||
		let (encoded, decoder) = service::functions::get_server_key_generation_request::call(index);
 | 
			
		||||
		let (server_key_id, author, threshold) = decoder.decode(&client.call_contract(*block, *contract_address, encoded)?)
 | 
			
		||||
			.map_err(|e| e.to_string())?;
 | 
			
		||||
		let threshold = parse_threshold(threshold)?;
 | 
			
		||||
 | 
			
		||||
		let (encoded, decoder) = service::functions::is_server_key_generation_response_required::call(server_key_id, self_address);
 | 
			
		||||
		let not_confirmed = decoder.decode(&client.call_contract(*block, *contract_address, encoded)?)
 | 
			
		||||
			.map_err(|e| e.to_string())?;
 | 
			
		||||
 | 
			
		||||
		let task = ServiceTask::GenerateServerKey(
 | 
			
		||||
			contract_address.clone(),
 | 
			
		||||
			server_key_id,
 | 
			
		||||
			author,
 | 
			
		||||
			threshold,
 | 
			
		||||
		);
 | 
			
		||||
 | 
			
		||||
		Ok((not_confirmed, task))
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl ServerKeyRetrievalService {
 | 
			
		||||
	/// Parse request log entry.
 | 
			
		||||
	pub fn parse_log(origin: &Address, contract: &service::Service, raw_log: RawLog) -> Result<ServiceTask, String> {
 | 
			
		||||
		let event = contract.events().server_key_retrieval_requested();
 | 
			
		||||
		match event.parse_log(raw_log) {
 | 
			
		||||
			Ok(l) => Ok(ServiceTask::RetrieveServerKey(origin.clone(), l.server_key_id)),
 | 
			
		||||
			Err(e) => Err(format!("{}", e)),
 | 
			
		||||
	pub fn parse_log(origin: &Address, raw_log: RawLog) -> Result<ServiceTask, String> {
 | 
			
		||||
		match service::events::server_key_retrieval_requested::parse_log(raw_log) {
 | 
			
		||||
			Ok(l) => Ok(ServiceTask::RetrieveServerKey(*origin, l.server_key_id)),
 | 
			
		||||
			Err(e) => Err(e.to_string())
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/// 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
 | 
			
		||||
		let do_call = |data| client.call_contract(BlockId::Latest, *contract_address, data);
 | 
			
		||||
		contract.functions()
 | 
			
		||||
			.is_server_key_retrieval_response_required()
 | 
			
		||||
			.call(*server_key_id, key_server.clone(), &do_call)
 | 
			
		||||
			.unwrap_or(true)
 | 
			
		||||
		let (encoded, decoder) = service::functions::is_server_key_retrieval_response_required::call(*server_key_id, *key_server);
 | 
			
		||||
		match client.call_contract(BlockId::Latest, *contract_address, encoded) {
 | 
			
		||||
			Err(_) => true,
 | 
			
		||||
			Ok(data) => decoder.decode(&data).unwrap_or(true)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/// 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 {
 | 
			
		||||
		contract.functions()
 | 
			
		||||
			.server_key_retrieved()
 | 
			
		||||
			.input(*server_key_id, server_key_public.to_vec(), threshold)
 | 
			
		||||
	pub fn prepare_pubish_tx_data(server_key_id: &ServerKeyId, server_key_public: Public, threshold: U256) -> Bytes {
 | 
			
		||||
		service::functions::server_key_retrieved::encode_input(*server_key_id, server_key_public.to_vec(), threshold)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/// Prepare error transaction data.
 | 
			
		||||
	pub fn prepare_error_tx_data(contract: &service::Service, server_key_id: &ServerKeyId) -> Bytes {
 | 
			
		||||
		contract.functions()
 | 
			
		||||
			.server_key_retrieval_error()
 | 
			
		||||
			.input(*server_key_id)
 | 
			
		||||
	pub fn prepare_error_tx_data(server_key_id: &ServerKeyId) -> Bytes {
 | 
			
		||||
		service::functions::server_key_retrieval_error::encode_input(*server_key_id)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/// Read pending requests count.
 | 
			
		||||
	fn read_pending_requests_count(client: &Client, contract_address: &Address, _contract: &service::Service, block: &BlockId) -> Result<U256, String> {
 | 
			
		||||
		let do_call = |data| client.call_contract(block.clone(), contract_address.clone(), data);
 | 
			
		||||
		let contract = service::Service::default();
 | 
			
		||||
		contract.functions()
 | 
			
		||||
			.server_key_retrieval_requests_count()
 | 
			
		||||
			.call(&do_call)
 | 
			
		||||
			.map_err(|error| format!("{}", error))
 | 
			
		||||
	fn read_pending_requests_count(client: &Client, contract_address: &Address, block: &BlockId) -> Result<U256, String> {
 | 
			
		||||
		let (encoded, decoder) = service::functions::server_key_retrieval_requests_count::call();
 | 
			
		||||
		decoder.decode(&client.call_contract(*block, *contract_address, encoded)?)
 | 
			
		||||
			.map_err(|e| e.to_string())
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/// 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 do_call = |d| client.call_contract(block.clone(), contract_address.clone(), d);
 | 
			
		||||
		contract.functions()
 | 
			
		||||
			.get_server_key_retrieval_request()
 | 
			
		||||
			.call(index, &do_call)
 | 
			
		||||
			.map_err(|error| format!("{}", error))
 | 
			
		||||
			.and_then(|server_key_id| contract.functions()
 | 
			
		||||
				.is_server_key_retrieval_response_required()
 | 
			
		||||
				.call(server_key_id.clone(), self_address, &do_call)
 | 
			
		||||
				.map(|not_confirmed| (
 | 
			
		||||
					not_confirmed,
 | 
			
		||||
					ServiceTask::RetrieveServerKey(
 | 
			
		||||
						contract_address.clone(),
 | 
			
		||||
						server_key_id,
 | 
			
		||||
					)))
 | 
			
		||||
				.map_err(|error| format!("{}", error)))
 | 
			
		||||
 | 
			
		||||
		let (encoded, decoder) = service::functions::get_server_key_retrieval_request::call(index);
 | 
			
		||||
		let server_key_id = decoder.decode(&client.call_contract(*block, *contract_address, encoded)?)
 | 
			
		||||
			.map_err(|e| e.to_string())?;
 | 
			
		||||
 | 
			
		||||
		let (encoded, decoder) = service::functions::is_server_key_retrieval_response_required::call(server_key_id, self_address);
 | 
			
		||||
		let not_confirmed = decoder.decode(&client.call_contract(*block, *contract_address, encoded)?)
 | 
			
		||||
			.map_err(|e| e.to_string())?;
 | 
			
		||||
 | 
			
		||||
		let task = ServiceTask::RetrieveServerKey(
 | 
			
		||||
			*contract_address,
 | 
			
		||||
			server_key_id,
 | 
			
		||||
		);
 | 
			
		||||
 | 
			
		||||
		Ok((not_confirmed, task))
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl DocumentKeyStoreService {
 | 
			
		||||
	/// Parse request log entry.
 | 
			
		||||
	pub fn parse_log(origin: &Address, contract: &service::Service, raw_log: RawLog) -> Result<ServiceTask, String> {
 | 
			
		||||
		let event = contract.events().document_key_store_requested();
 | 
			
		||||
		match event.parse_log(raw_log) {
 | 
			
		||||
	pub fn parse_log(origin: &Address, raw_log: RawLog) -> Result<ServiceTask, String> {
 | 
			
		||||
		match service::events::document_key_store_requested::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())),
 | 
			
		||||
			Err(e) => Err(format!("{}", e)),
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/// 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
 | 
			
		||||
		let do_call = |data| client.call_contract(BlockId::Latest, *contract_address, data);
 | 
			
		||||
		contract.functions()
 | 
			
		||||
			.is_document_key_store_response_required()
 | 
			
		||||
			.call(*server_key_id, key_server.clone(), &do_call)
 | 
			
		||||
			.unwrap_or(true)
 | 
			
		||||
		let (encoded, decoder) = service::functions::is_document_key_store_response_required::call(*server_key_id, *key_server);
 | 
			
		||||
		match client.call_contract(BlockId::Latest, *contract_address, encoded) {
 | 
			
		||||
			Err(_) => true,
 | 
			
		||||
			Ok(data) => decoder.decode(&data).unwrap_or(true)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/// Prepare publish key transaction data.
 | 
			
		||||
	pub fn prepare_pubish_tx_data(contract: &service::Service, server_key_id: &ServerKeyId) -> Bytes {
 | 
			
		||||
		contract.functions()
 | 
			
		||||
			.document_key_stored()
 | 
			
		||||
			.input(*server_key_id)
 | 
			
		||||
	pub fn prepare_pubish_tx_data(server_key_id: &ServerKeyId) -> Bytes {
 | 
			
		||||
		service::functions::document_key_stored::encode_input(*server_key_id)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/// Prepare error transaction data.
 | 
			
		||||
	pub fn prepare_error_tx_data(contract: &service::Service, server_key_id: &ServerKeyId) -> Bytes {
 | 
			
		||||
		contract.functions()
 | 
			
		||||
			.document_key_store_error()
 | 
			
		||||
			.input(*server_key_id)
 | 
			
		||||
	pub fn prepare_error_tx_data(server_key_id: &ServerKeyId) -> Bytes {
 | 
			
		||||
		service::functions::document_key_store_error::encode_input(*server_key_id)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/// Read pending requests count.
 | 
			
		||||
	fn read_pending_requests_count(client: &Client, contract_address: &Address, _contract: &service::Service, block: &BlockId) -> Result<U256, String> {
 | 
			
		||||
		let do_call = |data| client.call_contract(block.clone(), contract_address.clone(), data);
 | 
			
		||||
		let contract = service::Service::default();
 | 
			
		||||
		contract.functions()
 | 
			
		||||
			.document_key_store_requests_count()
 | 
			
		||||
			.call(&do_call)
 | 
			
		||||
			.map_err(|error| format!("{}", error))
 | 
			
		||||
	fn read_pending_requests_count(client: &Client, contract_address: &Address, block: &BlockId) -> Result<U256, String> {
 | 
			
		||||
		let (encoded, decoder) = service::functions::document_key_store_requests_count::call();
 | 
			
		||||
		decoder.decode(&client.call_contract(*block, *contract_address, encoded)?)
 | 
			
		||||
			.map_err(|e| e.to_string())
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/// 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 do_call = |d| client.call_contract(block.clone(), contract_address.clone(), d);
 | 
			
		||||
		contract.functions()
 | 
			
		||||
			.get_document_key_store_request()
 | 
			
		||||
			.call(index, &do_call)
 | 
			
		||||
			.map_err(|error| format!("{}", error))
 | 
			
		||||
			.and_then(|(server_key_id, author, common_point, encrypted_point)| contract.functions()
 | 
			
		||||
				.is_document_key_store_response_required()
 | 
			
		||||
				.call(server_key_id.clone(), self_address, &do_call)
 | 
			
		||||
				.map(|not_confirmed| (
 | 
			
		||||
					not_confirmed,
 | 
			
		||||
					ServiceTask::StoreDocumentKey(
 | 
			
		||||
						contract_address.clone(),
 | 
			
		||||
						server_key_id,
 | 
			
		||||
						author,
 | 
			
		||||
						Public::from_slice(&common_point),
 | 
			
		||||
						Public::from_slice(&encrypted_point),
 | 
			
		||||
					)))
 | 
			
		||||
				.map_err(|error| format!("{}", error)))
 | 
			
		||||
		let (encoded, decoder) = service::functions::get_document_key_store_request::call(index);
 | 
			
		||||
		let (server_key_id, author, common_point, encrypted_point) = decoder.decode(&client.call_contract(*block, *contract_address, encoded)?)
 | 
			
		||||
			.map_err(|e| e.to_string())?;
 | 
			
		||||
 | 
			
		||||
		let (encoded, decoder) = service::functions::is_document_key_store_response_required::call(server_key_id, self_address);
 | 
			
		||||
		let not_confirmed = decoder.decode(&client.call_contract(*block, *contract_address, encoded)?)
 | 
			
		||||
			.map_err(|e| e.to_string())?;
 | 
			
		||||
 | 
			
		||||
		let task = ServiceTask::StoreDocumentKey(
 | 
			
		||||
			*contract_address,
 | 
			
		||||
			server_key_id,
 | 
			
		||||
			author,
 | 
			
		||||
			Public::from_slice(&common_point),
 | 
			
		||||
			Public::from_slice(&encrypted_point),
 | 
			
		||||
		);
 | 
			
		||||
 | 
			
		||||
		Ok((not_confirmed, task))
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl DocumentKeyShadowRetrievalService {
 | 
			
		||||
	/// Parse common request log entry.
 | 
			
		||||
	pub fn parse_common_request_log(origin: &Address, contract: &service::Service, raw_log: RawLog) -> Result<ServiceTask, String> {
 | 
			
		||||
		let event = contract.events().document_key_common_retrieval_requested();
 | 
			
		||||
		match event.parse_log(raw_log) {
 | 
			
		||||
	pub fn parse_common_request_log(origin: &Address, raw_log: RawLog) -> Result<ServiceTask, String> {
 | 
			
		||||
		match service::events::document_key_common_retrieval_requested::parse_log(raw_log) {
 | 
			
		||||
			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.
 | 
			
		||||
	pub fn parse_personal_request_log(origin: &Address, contract: &service::Service, raw_log: RawLog) -> Result<ServiceTask, String> {
 | 
			
		||||
		let event = contract.events().document_key_personal_retrieval_requested();
 | 
			
		||||
		match event.parse_log(raw_log) {
 | 
			
		||||
	pub fn parse_personal_request_log(origin: &Address, raw_log: RawLog) -> Result<ServiceTask, String> {
 | 
			
		||||
		match service::events::document_key_personal_retrieval_requested::parse_log(raw_log) {
 | 
			
		||||
			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.
 | 
			
		||||
	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
 | 
			
		||||
		let do_call = |data| client.call_contract(BlockId::Latest, *contract_address, data);
 | 
			
		||||
		contract.functions()
 | 
			
		||||
			.is_document_key_shadow_retrieval_response_required()
 | 
			
		||||
			.call(*server_key_id, *requester, key_server.clone(), &do_call)
 | 
			
		||||
			.unwrap_or(true)
 | 
			
		||||
		let (encoded, decoder) = service::functions::is_document_key_shadow_retrieval_response_required::call(*server_key_id, *requester, *key_server);
 | 
			
		||||
		match client.call_contract(BlockId::Latest, *contract_address, encoded) {
 | 
			
		||||
			Err(_) => true,
 | 
			
		||||
			Ok(data) => decoder.decode(&data).unwrap_or(true)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/// 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 {
 | 
			
		||||
		contract.functions()
 | 
			
		||||
			.document_key_common_retrieved()
 | 
			
		||||
			.input(*server_key_id, *requester, common_point.to_vec(), threshold)
 | 
			
		||||
	pub fn prepare_pubish_common_tx_data(server_key_id: &ServerKeyId, requester: &Address, common_point: Public, threshold: U256) -> Bytes {
 | 
			
		||||
		service::functions::document_key_common_retrieved::encode_input(*server_key_id, *requester, common_point.to_vec(), threshold)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/// 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();
 | 
			
		||||
		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))?;
 | 
			
		||||
			participants_mask = participants_mask | (U256::one() << participant_index);
 | 
			
		||||
		}
 | 
			
		||||
		Ok(contract.functions()
 | 
			
		||||
			.document_key_personal_retrieved()
 | 
			
		||||
			.input(*server_key_id, *requester, participants_mask, decrypted_secret.to_vec(), shadow))
 | 
			
		||||
		Ok(service::functions::document_key_personal_retrieved::encode_input(
 | 
			
		||||
			*server_key_id, *requester, participants_mask, decrypted_secret.to_vec(), shadow
 | 
			
		||||
		))
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/// Prepare error transaction data.
 | 
			
		||||
	pub fn prepare_error_tx_data(contract: &service::Service, server_key_id: &ServerKeyId, requester: &Address) -> Bytes {
 | 
			
		||||
		contract.functions()
 | 
			
		||||
			.document_key_shadow_retrieval_error()
 | 
			
		||||
			.input(*server_key_id, *requester)
 | 
			
		||||
	pub fn prepare_error_tx_data(server_key_id: &ServerKeyId, requester: &Address) -> Bytes {
 | 
			
		||||
		service::functions::document_key_shadow_retrieval_error::encode_input(*server_key_id, *requester)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/// Read pending requests count.
 | 
			
		||||
	fn read_pending_requests_count(client: &Client, contract_address: &Address, _contract: &service::Service, block: &BlockId) -> Result<U256, String> {
 | 
			
		||||
		let do_call = |data| client.call_contract(block.clone(), contract_address.clone(), data);
 | 
			
		||||
		let contract = service::Service::default();
 | 
			
		||||
		contract.functions()
 | 
			
		||||
			.document_key_shadow_retrieval_requests_count()
 | 
			
		||||
			.call(&do_call)
 | 
			
		||||
			.map_err(|error| format!("{}", error))
 | 
			
		||||
	fn read_pending_requests_count(client: &Client, contract_address: &Address, block: &BlockId) -> Result<U256, String> {
 | 
			
		||||
		let (encoded, decoder) = service::functions::document_key_shadow_retrieval_requests_count::call();
 | 
			
		||||
		decoder.decode(&client.call_contract(*block, *contract_address, encoded)?)
 | 
			
		||||
			.map_err(|e| e.to_string())
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/// 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 do_call = |d| client.call_contract(block.clone(), contract_address.clone(), d);
 | 
			
		||||
		contract.functions()
 | 
			
		||||
			.get_document_key_shadow_retrieval_request()
 | 
			
		||||
			.call(index, &do_call)
 | 
			
		||||
			.map_err(|error| format!("{}", error))
 | 
			
		||||
			.and_then(|(server_key_id, requester, is_common_retrieval_completed)| {
 | 
			
		||||
				let requester = Public::from_slice(&requester);
 | 
			
		||||
				contract.functions()
 | 
			
		||||
					.is_document_key_shadow_retrieval_response_required()
 | 
			
		||||
					.call(server_key_id.clone(), public_to_address(&requester), self_address, &do_call)
 | 
			
		||||
					.map(|not_confirmed| (
 | 
			
		||||
						not_confirmed,
 | 
			
		||||
						match is_common_retrieval_completed {
 | 
			
		||||
							true => ServiceTask::RetrieveShadowDocumentKeyPersonal(
 | 
			
		||||
								contract_address.clone(),
 | 
			
		||||
								server_key_id,
 | 
			
		||||
								requester,
 | 
			
		||||
							),
 | 
			
		||||
							false => ServiceTask::RetrieveShadowDocumentKeyCommon(
 | 
			
		||||
								contract_address.clone(),
 | 
			
		||||
								server_key_id,
 | 
			
		||||
								public_to_address(&requester),
 | 
			
		||||
							),
 | 
			
		||||
						},
 | 
			
		||||
					))
 | 
			
		||||
					.map_err(|error| format!("{}", error))
 | 
			
		||||
			})
 | 
			
		||||
 | 
			
		||||
		let (encoded, decoder) = service::functions::get_document_key_shadow_retrieval_request::call(index);
 | 
			
		||||
		let (server_key_id, requester, is_common_retrieval_completed) =
 | 
			
		||||
			decoder.decode(&client.call_contract(*block, *contract_address, encoded)?)
 | 
			
		||||
			.map_err(|e| e.to_string())?;
 | 
			
		||||
 | 
			
		||||
		let requester = Public::from_slice(&requester);
 | 
			
		||||
		let (encoded, decoder) = service::functions::is_document_key_shadow_retrieval_response_required::call(server_key_id, public_to_address(&requester), self_address);
 | 
			
		||||
		let not_confirmed = decoder.decode(&client.call_contract(*block, *contract_address, encoded)?)
 | 
			
		||||
			.map_err(|e| e.to_string())?;
 | 
			
		||||
 | 
			
		||||
		let task = match is_common_retrieval_completed {
 | 
			
		||||
			true => ServiceTask::RetrieveShadowDocumentKeyPersonal(
 | 
			
		||||
				*contract_address,
 | 
			
		||||
				server_key_id,
 | 
			
		||||
				requester,
 | 
			
		||||
			),
 | 
			
		||||
			false => ServiceTask::RetrieveShadowDocumentKeyCommon(
 | 
			
		||||
				*contract_address,
 | 
			
		||||
				server_key_id,
 | 
			
		||||
				public_to_address(&requester),
 | 
			
		||||
			),
 | 
			
		||||
		};
 | 
			
		||||
 | 
			
		||||
		Ok((not_confirmed, task))
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/// 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
 | 
			
		||||
		let do_call = |data| client.call_contract(BlockId::Latest, *contract_address, data);
 | 
			
		||||
		contract.functions()
 | 
			
		||||
			.require_key_server()
 | 
			
		||||
			.call(key_server, &do_call)
 | 
			
		||||
			.map_err(|e| format!("{}", e))
 | 
			
		||||
			.and_then(|index| if index > ::std::u8::MAX.into() {
 | 
			
		||||
				Err(format!("key server index is too big: {}", index))
 | 
			
		||||
			} else {
 | 
			
		||||
				let index: u32 = index.into();
 | 
			
		||||
				Ok(index as u8)
 | 
			
		||||
			})
 | 
			
		||||
		let (encoded, decoder) = service::functions::require_key_server::call(key_server);
 | 
			
		||||
		let index = decoder.decode(&client.call_contract(BlockId::Latest, *contract_address, encoded)?)
 | 
			
		||||
			.map_err(|e| e.to_string())?;
 | 
			
		||||
 | 
			
		||||
		if index > u8::max_value().into() {
 | 
			
		||||
			Err(format!("key server index is too big: {}", index))
 | 
			
		||||
		} else {
 | 
			
		||||
			let index: u32 = index.into();
 | 
			
		||||
			Ok(index as u8)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -9,9 +9,9 @@ authors = ["Parity Technologies <admin@parity.io>"]
 | 
			
		||||
keccak-hash = "0.1"
 | 
			
		||||
lazy_static = "1.0"
 | 
			
		||||
log = "0.4"
 | 
			
		||||
ethabi = "5.1.2"
 | 
			
		||||
ethabi-derive = "5.1.3"
 | 
			
		||||
ethabi-contract = "5.1.1"
 | 
			
		||||
ethabi = "6.0"
 | 
			
		||||
ethabi-derive = "6.0"
 | 
			
		||||
ethabi-contract = "6.0"
 | 
			
		||||
target_info = "0.1"
 | 
			
		||||
semver = "0.9"
 | 
			
		||||
ethcore = { path = "../ethcore" }
 | 
			
		||||
 | 
			
		||||
@ -37,8 +37,9 @@ use sync::{SyncProvider};
 | 
			
		||||
use types::{ReleaseInfo, OperationsInfo, CapState, VersionInfo, ReleaseTrack};
 | 
			
		||||
use version;
 | 
			
		||||
use semver::Version;
 | 
			
		||||
use ethabi::FunctionOutputDecoder;
 | 
			
		||||
 | 
			
		||||
use_contract!(operations_contract, "Operations", "res/operations.json");
 | 
			
		||||
use_contract!(operations, "res/operations.json");
 | 
			
		||||
 | 
			
		||||
/// Filter for releases.
 | 
			
		||||
#[derive(Debug, Eq, PartialEq, Clone)]
 | 
			
		||||
@ -192,41 +193,35 @@ pub trait OperationsClient: Send + Sync + 'static {
 | 
			
		||||
 | 
			
		||||
/// `OperationsClient` that delegates calls to the operations contract.
 | 
			
		||||
pub struct OperationsContractClient {
 | 
			
		||||
	operations_contract: operations_contract::Operations,
 | 
			
		||||
	client: Weak<BlockChainClient>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl OperationsContractClient {
 | 
			
		||||
	fn new(
 | 
			
		||||
		operations_contract: operations_contract::Operations,
 | 
			
		||||
		client: Weak<BlockChainClient>,
 | 
			
		||||
	) -> OperationsContractClient {
 | 
			
		||||
		OperationsContractClient { operations_contract, client }
 | 
			
		||||
	fn new(client: Weak<BlockChainClient>) -> Self {
 | 
			
		||||
		OperationsContractClient {
 | 
			
		||||
			client
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/// Get the hash of the latest release for the given track
 | 
			
		||||
	fn latest_hash<F>(&self, track: ReleaseTrack, do_call: &F) -> Result<H256, String>
 | 
			
		||||
	where F: Fn(Vec<u8>) -> Result<Vec<u8>, String> {
 | 
			
		||||
		self.operations_contract.functions()
 | 
			
		||||
			.latest_in_track()
 | 
			
		||||
			.call(*CLIENT_ID_HASH, u8::from(track), do_call)
 | 
			
		||||
			.map_err(|e| format!("{:?}", e))
 | 
			
		||||
		let (data, decoder) = operations::functions::latest_in_track::call(*CLIENT_ID_HASH, u8::from(track));
 | 
			
		||||
		let value = do_call(data)?;
 | 
			
		||||
		decoder.decode(&value).map_err(|e| e.to_string())
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/// Get release info for the given release
 | 
			
		||||
	fn release_info<F>(&self, release_id: H256, do_call: &F) -> Result<ReleaseInfo, String>
 | 
			
		||||
	where F: Fn(Vec<u8>) -> Result<Vec<u8>, String> {
 | 
			
		||||
		let (fork, track, semver, is_critical) = self.operations_contract.functions()
 | 
			
		||||
			.release()
 | 
			
		||||
			.call(*CLIENT_ID_HASH, release_id, &do_call)
 | 
			
		||||
			.map_err(|e| format!("{:?}", e))?;
 | 
			
		||||
		let (data, decoder) = operations::functions::release::call(*CLIENT_ID_HASH, release_id);
 | 
			
		||||
 | 
			
		||||
		let (fork, track, semver, is_critical) = decoder.decode(&do_call(data)?).map_err(|e| e.to_string())?;
 | 
			
		||||
 | 
			
		||||
		let (fork, track, semver) = (fork.low_u64(), track.low_u32(), semver.low_u32());
 | 
			
		||||
 | 
			
		||||
		let latest_binary = self.operations_contract.functions()
 | 
			
		||||
			.checksum()
 | 
			
		||||
			.call(*CLIENT_ID_HASH, release_id, *PLATFORM_ID_HASH, &do_call)
 | 
			
		||||
			.map_err(|e| format!("{:?}", e))?;
 | 
			
		||||
		let (data, decoder) = operations::functions::checksum::call(*CLIENT_ID_HASH, release_id, *PLATFORM_ID_HASH);
 | 
			
		||||
		let latest_binary = decoder.decode(&do_call(data)?).map_err(|e| e.to_string())?;
 | 
			
		||||
 | 
			
		||||
		Ok(ReleaseInfo {
 | 
			
		||||
			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);
 | 
			
		||||
 | 
			
		||||
		// get the fork number of this release
 | 
			
		||||
		let this_fork = self.operations_contract.functions()
 | 
			
		||||
			.release()
 | 
			
		||||
			.call(*CLIENT_ID_HASH, this.hash, &do_call)
 | 
			
		||||
		let (data, decoder) = operations::functions::release::call(*CLIENT_ID_HASH, this.hash);
 | 
			
		||||
		let this_fork = do_call(data)
 | 
			
		||||
			.and_then(|value| decoder.decode(&value).map_err(|e| e.to_string()))
 | 
			
		||||
			.ok()
 | 
			
		||||
			.and_then(|(fork, track, _, _)| {
 | 
			
		||||
				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)?);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		let fork = self.operations_contract.functions()
 | 
			
		||||
			.latest_fork()
 | 
			
		||||
			.call(&do_call)
 | 
			
		||||
			.map_err(|e| format!("{:?}", e))?.low_u64();
 | 
			
		||||
		let (data, decoder) = operations::functions::latest_fork::call();
 | 
			
		||||
		let fork = do_call(data)
 | 
			
		||||
			.and_then(|value| decoder.decode(&value).map_err(|e| e.to_string()))?
 | 
			
		||||
			.low_u64();
 | 
			
		||||
 | 
			
		||||
		Ok(OperationsInfo {
 | 
			
		||||
			fork,
 | 
			
		||||
@ -299,9 +294,7 @@ impl OperationsClient for OperationsContractClient {
 | 
			
		||||
		let client = self.client.upgrade()?;
 | 
			
		||||
		let address = client.registry_address("operations".into(), BlockId::Latest)?;
 | 
			
		||||
 | 
			
		||||
		let event = self.operations_contract.events().release_added();
 | 
			
		||||
 | 
			
		||||
		let topics = event.create_filter(Some(*CLIENT_ID_HASH), Some(release.fork.into()), Some(release.is_critical));
 | 
			
		||||
		let topics = operations::events::release_added::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 = topics.into_iter().map(Into::into).map(Some).collect();
 | 
			
		||||
 | 
			
		||||
@ -317,7 +310,7 @@ impl OperationsClient for OperationsContractClient {
 | 
			
		||||
			.unwrap_or_default()
 | 
			
		||||
			.iter()
 | 
			
		||||
			.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());
 | 
			
		||||
				if version_info == release.version {
 | 
			
		||||
					Some(log.block_number)
 | 
			
		||||
@ -375,7 +368,6 @@ impl Updater {
 | 
			
		||||
			sync: Some(sync.clone()),
 | 
			
		||||
			fetcher,
 | 
			
		||||
			operations_client: OperationsContractClient::new(
 | 
			
		||||
				operations_contract::Operations::default(),
 | 
			
		||||
				client.clone()),
 | 
			
		||||
			exit_handler: Mutex::new(None),
 | 
			
		||||
			this: if cfg!(feature = "test-updater") {
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user