Futures-based native wrappers for contract ABIs (#5341)
* initial native contract generator * get generated code compiling * unit tests for type codegen * autogenerate registry contract * native_contracts entry for registry * service_transaction_checker * fixed indentation
This commit is contained in:
parent
21e21f1e02
commit
c9c8f920d2
46
Cargo.lock
generated
46
Cargo.lock
generated
@ -361,7 +361,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ethabi"
|
||||
version = "1.0.0"
|
||||
version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -392,7 +392,7 @@ dependencies = [
|
||||
"clippy 0.0.103 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"crossbeam 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"env_logger 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ethabi 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ethabi 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ethash 1.7.0",
|
||||
"ethcore-bloom-journal 0.1.0",
|
||||
"ethcore-devtools 1.7.0",
|
||||
@ -407,6 +407,7 @@ dependencies = [
|
||||
"ethkey 0.2.0",
|
||||
"ethstore 0.1.0",
|
||||
"evmjit 1.7.0",
|
||||
"futures 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"hardware-wallet 1.7.0",
|
||||
"hyper 0.10.0-a.0 (git+https://github.com/paritytech/hyper)",
|
||||
"itertools 0.5.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -414,6 +415,7 @@ dependencies = [
|
||||
"linked-hash-map 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lru-cache 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"native-contracts 0.1.0",
|
||||
"num 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num_cpus 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -944,6 +946,14 @@ dependencies = [
|
||||
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "heck"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"unicode-segmentation 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hidapi"
|
||||
version = "0.3.1"
|
||||
@ -1394,6 +1404,25 @@ dependencies = [
|
||||
"libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "native-contract-generator"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"ethabi 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"heck 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "native-contracts"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ethabi 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ethcore-util 1.7.0",
|
||||
"futures 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"native-contract-generator 0.1.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "native-tls"
|
||||
version = "0.1.0"
|
||||
@ -1593,7 +1622,7 @@ dependencies = [
|
||||
name = "parity-hash-fetch"
|
||||
version = "1.7.0"
|
||||
dependencies = [
|
||||
"ethabi 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ethabi 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ethcore-util 1.7.0",
|
||||
"fetch 0.1.0",
|
||||
"futures 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -1703,7 +1732,7 @@ dependencies = [
|
||||
name = "parity-updater"
|
||||
version = "1.7.0"
|
||||
dependencies = [
|
||||
"ethabi 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ethabi 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ethcore 1.7.0",
|
||||
"ethcore-ipc 1.7.0",
|
||||
"ethcore-ipc-codegen 1.7.0",
|
||||
@ -2503,6 +2532,11 @@ name = "unicode-normalization"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-segmentation"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-xid"
|
||||
version = "0.0.4"
|
||||
@ -2678,7 +2712,7 @@ dependencies = [
|
||||
"checksum elastic-array 0.6.0 (git+https://github.com/paritytech/elastic-array)" = "<none>"
|
||||
"checksum env_logger 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e3856f1697098606fc6cb97a93de88ca3f3bc35bb878c725920e6e82ecf05e83"
|
||||
"checksum eth-secp256k1 0.5.6 (git+https://github.com/paritytech/rust-secp256k1)" = "<none>"
|
||||
"checksum ethabi 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5d8f6cc4c1acd005f48e1d17b06a461adac8fb6eeeb331fbf19a0e656fba91cd"
|
||||
"checksum ethabi 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "63df67d0af5e3cb906b667ca1a6e00baffbed87d0d8f5f78468a1f5eb3a66345"
|
||||
"checksum fdlimit 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b1ee15a7050e5580b3712877157068ea713b245b080ff302ae2ca973cfcd9baa"
|
||||
"checksum flate2 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "3eeb481e957304178d2e782f2da1257f1434dfecbae883bafb61ada2a9fea3bb"
|
||||
"checksum futures 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8e51e7f9c150ba7fd4cee9df8bf6ea3dea5b63b68955ddad19ccd35b71dcfb4d"
|
||||
@ -2688,6 +2722,7 @@ dependencies = [
|
||||
"checksum glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb"
|
||||
"checksum hamming 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "65043da274378d68241eb9a8f8f8aa54e349136f7b8e12f63e3ef44043cc30e1"
|
||||
"checksum heapsize 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "abb306abb8d398e053cfb1b3e7b72c2f580be048b85745c52652954f8ad1439c"
|
||||
"checksum heck 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6f807d2f64cc044a6bcf250ff23e59be0deec7a16612c014f962a06fa7e020f9"
|
||||
"checksum hidapi 0.3.1 (git+https://github.com/paritytech/hidapi-rs)" = "<none>"
|
||||
"checksum httparse 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "46534074dbb80b070d60a5cb8ecadd8963a00a438ae1a95268850a7ef73b67ae"
|
||||
"checksum hyper 0.10.0-a.0 (git+https://github.com/paritytech/hyper)" = "<none>"
|
||||
@ -2848,6 +2883,7 @@ dependencies = [
|
||||
"checksum unicase 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "13a5906ca2b98c799f4b1ab4557b76367ebd6ae5ef14930ec841c74aed5f3764"
|
||||
"checksum unicode-bidi 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c1f7ceb96afdfeedee42bade65a0d585a6a0106f681b6749c8ff4daa8df30b3f"
|
||||
"checksum unicode-normalization 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "26643a2f83bac55f1976fb716c10234485f9202dcd65cfbdf9da49867b271172"
|
||||
"checksum unicode-segmentation 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "18127285758f0e2c6cf325bb3f3d138a12fee27de4f23e146cd6a179f26c2cf3"
|
||||
"checksum unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc"
|
||||
"checksum unreachable 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1f2ae5ddb18e1c92664717616dd9549dde73f539f01bd7b77c2edb2446bdff91"
|
||||
"checksum untrusted 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "193df64312e3515fd983ded55ad5bcaa7647a035804828ed757e832ce6029ef3"
|
||||
|
@ -11,44 +11,46 @@ build = "build.rs"
|
||||
"ethcore-ipc-codegen" = { path = "../ipc/codegen" }
|
||||
|
||||
[dependencies]
|
||||
log = "0.3"
|
||||
env_logger = "0.4"
|
||||
rustc-serialize = "0.3"
|
||||
rust-crypto = "0.2.34"
|
||||
num_cpus = "1.2"
|
||||
crossbeam = "0.2.9"
|
||||
lazy_static = "0.2"
|
||||
bloomchain = "0.1"
|
||||
semver = "0.6"
|
||||
bit-set = "0.4"
|
||||
time = "0.1"
|
||||
rand = "0.3"
|
||||
byteorder = "1.0"
|
||||
transient-hashmap = "0.4"
|
||||
linked-hash-map = "0.3.0"
|
||||
lru-cache = "0.1.0"
|
||||
itertools = "0.5"
|
||||
ethabi = "1.0.0"
|
||||
evmjit = { path = "../evmjit", optional = true }
|
||||
clippy = { version = "0.0.103", optional = true}
|
||||
ethash = { path = "../ethash" }
|
||||
ethcore-util = { path = "../util" }
|
||||
ethcore-io = { path = "../util/io" }
|
||||
ethcore-devtools = { path = "../devtools" }
|
||||
ethjson = { path = "../json" }
|
||||
ethcore-ipc = { path = "../ipc/rpc" }
|
||||
ethstore = { path = "../ethstore" }
|
||||
ethkey = { path = "../ethkey" }
|
||||
ethcore-ipc-nano = { path = "../ipc/nano" }
|
||||
rlp = { path = "../util/rlp" }
|
||||
ethcore-stratum = { path = "../stratum" }
|
||||
ethcore-bloom-journal = { path = "../util/bloom" }
|
||||
hardware-wallet = { path = "../hw" }
|
||||
ethcore-logger = { path = "../logger" }
|
||||
stats = { path = "../util/stats" }
|
||||
hyper = { git = "https://github.com/paritytech/hyper", default-features = false }
|
||||
num = "0.1"
|
||||
bloomchain = "0.1"
|
||||
bn = { git = "https://github.com/paritytech/bn" }
|
||||
byteorder = "1.0"
|
||||
clippy = { version = "0.0.103", optional = true}
|
||||
crossbeam = "0.2.9"
|
||||
env_logger = "0.4"
|
||||
ethabi = "1.0.0"
|
||||
ethash = { path = "../ethash" }
|
||||
ethcore-bloom-journal = { path = "../util/bloom" }
|
||||
ethcore-devtools = { path = "../devtools" }
|
||||
ethcore-io = { path = "../util/io" }
|
||||
ethcore-ipc = { path = "../ipc/rpc" }
|
||||
ethcore-ipc-nano = { path = "../ipc/nano" }
|
||||
ethcore-logger = { path = "../logger" }
|
||||
ethcore-stratum = { path = "../stratum" }
|
||||
ethcore-util = { path = "../util" }
|
||||
ethjson = { path = "../json" }
|
||||
ethkey = { path = "../ethkey" }
|
||||
ethstore = { path = "../ethstore" }
|
||||
evmjit = { path = "../evmjit", optional = true }
|
||||
futures = "0.1"
|
||||
hardware-wallet = { path = "../hw" }
|
||||
hyper = { git = "https://github.com/paritytech/hyper", default-features = false }
|
||||
itertools = "0.5"
|
||||
lazy_static = "0.2"
|
||||
linked-hash-map = "0.3.0"
|
||||
log = "0.3"
|
||||
lru-cache = "0.1.0"
|
||||
native-contracts = { path = "native_contracts" }
|
||||
num = "0.1"
|
||||
num_cpus = "1.2"
|
||||
rand = "0.3"
|
||||
rlp = { path = "../util/rlp" }
|
||||
rust-crypto = "0.2.34"
|
||||
rustc-serialize = "0.3"
|
||||
semver = "0.6"
|
||||
stats = { path = "../util/stats" }
|
||||
time = "0.1"
|
||||
transient-hashmap = "0.4"
|
||||
|
||||
[features]
|
||||
jit = ["evmjit"]
|
||||
|
15
ethcore/native_contracts/Cargo.toml
Normal file
15
ethcore/native_contracts/Cargo.toml
Normal file
@ -0,0 +1,15 @@
|
||||
[package]
|
||||
name = "native-contracts"
|
||||
description = "Generated Rust code for Ethereum contract ABIs"
|
||||
version = "0.1.0"
|
||||
authors = ["Parity Technologies <admin@parity.io>"]
|
||||
build = "build.rs"
|
||||
|
||||
[dependencies]
|
||||
ethabi = "1.0"
|
||||
futures = "0.1"
|
||||
byteorder = "1.0"
|
||||
ethcore-util = { path = "../../util" }
|
||||
|
||||
[build-dependencies]
|
||||
native-contract-generator = { path = "generator" }
|
40
ethcore/native_contracts/build.rs
Normal file
40
ethcore/native_contracts/build.rs
Normal file
@ -0,0 +1,40 @@
|
||||
// Copyright 2015-2017 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity.
|
||||
|
||||
// Parity is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// Parity is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
extern crate native_contract_generator;
|
||||
|
||||
use std::path::Path;
|
||||
use std::fs::File;
|
||||
use std::io::Write;
|
||||
|
||||
// TODO: `include!` these from files where they're pretty-printed?
|
||||
const REGISTRY_ABI: &'static str = r#"[{"constant":true,"inputs":[{"name":"_data","type":"address"}],"name":"canReverse","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_new","type":"address"}],"name":"setOwner","outputs":[],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_name","type":"bytes32"},{"name":"_key","type":"string"},{"name":"_value","type":"bytes32"}],"name":"setData","outputs":[{"name":"success","type":"bool"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_name","type":"string"}],"name":"confirmReverse","outputs":[{"name":"success","type":"bool"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_name","type":"bytes32"}],"name":"reserve","outputs":[{"name":"success","type":"bool"}],"payable":true,"type":"function"},{"constant":false,"inputs":[{"name":"_name","type":"bytes32"}],"name":"drop","outputs":[{"name":"success","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_name","type":"bytes32"},{"name":"_key","type":"string"}],"name":"getAddress","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_amount","type":"uint256"}],"name":"setFee","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_name","type":"bytes32"},{"name":"_to","type":"address"}],"name":"transfer","outputs":[{"name":"success","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_name","type":"bytes32"},{"name":"_key","type":"string"}],"name":"getData","outputs":[{"name":"","type":"bytes32"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_name","type":"bytes32"}],"name":"reserved","outputs":[{"name":"reserved","type":"bool"}],"payable":false,"type":"function"},{"constant":false,"inputs":[],"name":"drain","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_name","type":"string"},{"name":"_who","type":"address"}],"name":"proposeReverse","outputs":[{"name":"success","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_name","type":"bytes32"}],"name":"hasReverse","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_name","type":"bytes32"},{"name":"_key","type":"string"}],"name":"getUint","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"fee","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_name","type":"bytes32"}],"name":"getOwner","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_name","type":"bytes32"}],"name":"getReverse","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_data","type":"address"}],"name":"reverse","outputs":[{"name":"","type":"string"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_name","type":"bytes32"},{"name":"_key","type":"string"},{"name":"_value","type":"uint256"}],"name":"setUint","outputs":[{"name":"success","type":"bool"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_name","type":"string"},{"name":"_who","type":"address"}],"name":"confirmReverseAs","outputs":[{"name":"success","type":"bool"}],"payable":false,"type":"function"},{"constant":false,"inputs":[],"name":"removeReverse","outputs":[],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_name","type":"bytes32"},{"name":"_key","type":"string"},{"name":"_value","type":"address"}],"name":"setAddress","outputs":[{"name":"success","type":"bool"}],"payable":false,"type":"function"}]"#;
|
||||
const SERVICE_TRANSACTION_ABI: &'static str = r#"[{"constant":false,"inputs":[{"name":"_new","type":"address"}],"name":"setOwner","outputs":[],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_who","type":"address"}],"name":"certify","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_who","type":"address"},{"name":"_field","type":"string"}],"name":"getAddress","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_who","type":"address"}],"name":"revoke","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"delegate","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_who","type":"address"},{"name":"_field","type":"string"}],"name":"getUint","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_new","type":"address"}],"name":"setDelegate","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_who","type":"address"}],"name":"certified","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_who","type":"address"},{"name":"_field","type":"string"}],"name":"get","outputs":[{"name":"","type":"bytes32"}],"payable":false,"type":"function"}]"#;
|
||||
|
||||
fn build_file(name: &str, abi: &str, filename: &str) {
|
||||
let code = ::native_contract_generator::generate_module(name, abi).unwrap();
|
||||
|
||||
let out_dir = ::std::env::var("OUT_DIR").unwrap();
|
||||
let dest_path = Path::new(&out_dir).join(filename);
|
||||
let mut f = File::create(&dest_path).unwrap();
|
||||
|
||||
f.write_all(code.as_bytes()).unwrap();
|
||||
}
|
||||
|
||||
fn main() {
|
||||
build_file("Registry", REGISTRY_ABI, "registry.rs");
|
||||
build_file("ServiceTransactionChecker", SERVICE_TRANSACTION_ABI, "service_transaction.rs");
|
||||
}
|
9
ethcore/native_contracts/generator/Cargo.toml
Normal file
9
ethcore/native_contracts/generator/Cargo.toml
Normal file
@ -0,0 +1,9 @@
|
||||
[package]
|
||||
name = "native-contract-generator"
|
||||
description = "Generates Rust code for ethereum contract ABIs"
|
||||
version = "0.1.0"
|
||||
authors = ["Parity Technologies <admin@parity.io>"]
|
||||
|
||||
[dependencies]
|
||||
ethabi = "1.0.2"
|
||||
heck = "0.2"
|
346
ethcore/native_contracts/generator/src/lib.rs
Normal file
346
ethcore/native_contracts/generator/src/lib.rs
Normal file
@ -0,0 +1,346 @@
|
||||
// Copyright 2015-2017 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity.
|
||||
|
||||
// Parity is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// Parity is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! Rust code contract generator.
|
||||
//! The code generated will require a dependence on the `ethcore-util`,
|
||||
//! `ethabi`, `byteorder`, and `futures` crates.
|
||||
//! This currently isn't hygienic, so compilation of generated code may fail
|
||||
//! due to missing crates or name collisions. This will change when
|
||||
//! it can be ported to a procedural macro.
|
||||
|
||||
use ethabi::Contract;
|
||||
use ethabi::spec::{Interface, ParamType, Error as AbiError};
|
||||
use heck::SnakeCase;
|
||||
|
||||
extern crate ethabi;
|
||||
extern crate heck;
|
||||
|
||||
/// Errors in generation.
|
||||
#[derive(Debug)]
|
||||
pub enum Error {
|
||||
/// Bad ABI.
|
||||
Abi(AbiError),
|
||||
/// Unsupported parameter type in given function.
|
||||
UnsupportedType(String, ParamType),
|
||||
}
|
||||
|
||||
/// Given an ABI string, generate code for a a Rust module containing
|
||||
/// a struct which can be used to call it.
|
||||
// TODO: make this a proc macro when that's possible.
|
||||
pub fn generate_module(struct_name: &str, abi: &str) -> Result<String, Error> {
|
||||
let contract = Contract::new(Interface::load(abi.as_bytes()).map_err(Error::Abi)?);
|
||||
let functions = generate_functions(&contract)?;
|
||||
|
||||
Ok(format!(r##"
|
||||
use byteorder::{{BigEndian, ByteOrder}};
|
||||
use futures::{{future, Future, BoxFuture}};
|
||||
use ethabi::{{Contract, Interface, Token}};
|
||||
use util::{{self, Uint}};
|
||||
|
||||
pub struct {name} {{
|
||||
contract: Contract,
|
||||
/// Address to make calls to.
|
||||
pub address: util::Address,
|
||||
}}
|
||||
|
||||
const ABI: &'static str = r#"{abi_str}"#;
|
||||
|
||||
impl {name} {{
|
||||
/// Create a new instance of `{name}` with an address.
|
||||
/// Calls can be made, given a callback for dispatching calls asynchronously.
|
||||
pub fn new(address: util::Address) -> Self {{
|
||||
let contract = Contract::new(Interface::load(ABI.as_bytes())
|
||||
.expect("ABI checked at generation-time; qed"));
|
||||
{name} {{
|
||||
contract: contract,
|
||||
address: address,
|
||||
}}
|
||||
}}
|
||||
|
||||
{functions}
|
||||
}}
|
||||
"##,
|
||||
name = struct_name,
|
||||
abi_str = abi,
|
||||
functions = functions,
|
||||
))
|
||||
}
|
||||
|
||||
// generate function bodies from the ABI.
|
||||
fn generate_functions(contract: &Contract) -> Result<String, Error> {
|
||||
let mut functions = String::new();
|
||||
for function in contract.functions() {
|
||||
let name = function.name();
|
||||
let snake_name = name.to_snake_case();
|
||||
let inputs = function.input_params();
|
||||
let outputs = function.output_params();
|
||||
|
||||
let (input_params, to_tokens) = input_params_codegen(&inputs)
|
||||
.map_err(|bad_type| Error::UnsupportedType(name.into(), bad_type))?;
|
||||
|
||||
let (output_type, decode_outputs) = output_params_codegen(&outputs)
|
||||
.map_err(|bad_type| Error::UnsupportedType(name.into(), bad_type))?;
|
||||
|
||||
functions.push_str(&format!(r##"
|
||||
/// Call the function "{abi_name}" on the contract.
|
||||
/// Inputs: {abi_inputs:?}
|
||||
/// Outputs: {abi_outputs:?}
|
||||
pub fn {snake_name}<F, U>(&self, call: F, {params}) -> BoxFuture<{output_type}, String>
|
||||
where F: Fn(util::Address, Vec<u8>) -> U, U: Future<Item=Vec<u8>, Error=String> + Send + 'static
|
||||
{{
|
||||
let function = self.contract.function(r#"{abi_name}"#.to_string())
|
||||
.expect("function existence checked at compile-time; qed");
|
||||
let call_addr = self.address;
|
||||
|
||||
let call_future = match function.encode_call({to_tokens}) {{
|
||||
Ok(call_data) => (call)(call_addr, call_data),
|
||||
Err(e) => return future::err(format!("Error encoding call: {{:?}}", e)).boxed(),
|
||||
}};
|
||||
|
||||
call_future
|
||||
.and_then(move |out| function.decode_output(out).map_err(|e| format!("{{:?}}", e)))
|
||||
.map(::std::collections::VecDeque::from)
|
||||
.and_then(|mut outputs| {decode_outputs})
|
||||
.boxed()
|
||||
}}
|
||||
"##,
|
||||
abi_name = name,
|
||||
abi_inputs = inputs,
|
||||
abi_outputs = outputs,
|
||||
snake_name = snake_name,
|
||||
params = input_params,
|
||||
output_type = output_type,
|
||||
to_tokens = to_tokens,
|
||||
decode_outputs = decode_outputs,
|
||||
))
|
||||
}
|
||||
|
||||
Ok(functions)
|
||||
}
|
||||
|
||||
// generate code for params in function signature and turning them into tokens.
|
||||
//
|
||||
// two pieces of code are generated: the first gives input types for the function signature,
|
||||
// and the second gives code to tokenize those inputs.
|
||||
//
|
||||
// params of form `param_0: type_0, param_1: type_1, ...`
|
||||
// tokenizing code of form `{let mut tokens = Vec::new(); tokens.push({param_X}); tokens }`
|
||||
//
|
||||
// returns any unsupported param type encountered.
|
||||
fn input_params_codegen(inputs: &[ParamType]) -> Result<(String, String), ParamType> {
|
||||
let mut params = String::new();
|
||||
let mut to_tokens = "{ let mut tokens = Vec::new();".to_string();
|
||||
|
||||
for (index, param_type) in inputs.iter().enumerate() {
|
||||
let param_name = format!("param_{}", index);
|
||||
let rust_type = rust_type(param_type.clone())?;
|
||||
let (needs_mut, tokenize_code) = tokenize(¶m_name, param_type.clone());
|
||||
|
||||
params.push_str(&format!("{}{}: {}, ",
|
||||
if needs_mut { "mut " } else { "" }, param_name, rust_type));
|
||||
|
||||
to_tokens.push_str(&format!("tokens.push({{ {} }});", tokenize_code));
|
||||
}
|
||||
|
||||
to_tokens.push_str(" tokens }");
|
||||
Ok((params, to_tokens))
|
||||
}
|
||||
|
||||
// generate code for outputs of the function and detokenizing them.
|
||||
//
|
||||
// two pieces of code are generated: the first gives an output type for the function signature
|
||||
// as a tuple, and the second gives code to get that tuple from a deque of tokens.
|
||||
//
|
||||
// produce output type of the form (type_1, type_2, ...) without trailing comma.
|
||||
// produce code for getting this output type from `outputs: VecDeque<Token>`, where
|
||||
// an `Err(String)` can be returned.
|
||||
//
|
||||
// returns any unsupported param type encountered.
|
||||
fn output_params_codegen(outputs: &[ParamType]) -> Result<(String, String), ParamType> {
|
||||
let mut output_type = "(".to_string();
|
||||
let mut decode_outputs = "Ok((".to_string();
|
||||
|
||||
for (index, output) in outputs.iter().cloned().enumerate() {
|
||||
let rust_type = rust_type(output.clone())?;
|
||||
|
||||
output_type.push_str(&rust_type);
|
||||
|
||||
decode_outputs.push_str(&format!(
|
||||
r#"
|
||||
outputs
|
||||
.pop_front()
|
||||
.and_then(|output| {{ {} }})
|
||||
.ok_or_else(|| "Wrong output type".to_string())?
|
||||
"#,
|
||||
detokenize("output", output)
|
||||
));
|
||||
|
||||
// don't append trailing commas for the last element
|
||||
// so we can reuse the same code for single-output contracts,
|
||||
// since T == (T) != (T,)
|
||||
if index < outputs.len() - 1 {
|
||||
output_type.push_str(", ");
|
||||
decode_outputs.push_str(", ");
|
||||
}
|
||||
}
|
||||
|
||||
output_type.push_str(")");
|
||||
decode_outputs.push_str("))");
|
||||
Ok((output_type, decode_outputs))
|
||||
}
|
||||
|
||||
// create code for an argument type from param type.
|
||||
fn rust_type(input: ParamType) -> Result<String, ParamType> {
|
||||
Ok(match input {
|
||||
ParamType::Address => "util::Address".into(),
|
||||
ParamType::FixedBytes(len) if len <= 32 => format!("util::H{}", len * 8),
|
||||
ParamType::Bytes | ParamType::FixedBytes(_) => "Vec<u8>".into(),
|
||||
ParamType::Int(width) => match width {
|
||||
8 | 16 | 32 | 64 => format!("i{}", width),
|
||||
_ => return Err(ParamType::Int(width)),
|
||||
},
|
||||
ParamType::Uint(width) => match width {
|
||||
8 | 16 | 32 | 64 => format!("u{}", width),
|
||||
128 | 160 | 256 => format!("util::U{}", width),
|
||||
_ => return Err(ParamType::Uint(width)),
|
||||
},
|
||||
ParamType::Bool => "bool".into(),
|
||||
ParamType::String => "String".into(),
|
||||
ParamType::Array(kind) => format!("Vec<{}>", rust_type(*kind)?),
|
||||
other => return Err(other),
|
||||
})
|
||||
}
|
||||
|
||||
// create code for tokenizing this parameter.
|
||||
// returns (needs_mut, code), where needs_mut indicates mutability required.
|
||||
// panics on unsupported types.
|
||||
fn tokenize(name: &str, input: ParamType) -> (bool, String) {
|
||||
let mut needs_mut = false;
|
||||
let code = match input {
|
||||
ParamType::Address => format!("Token::Address({}.0)", name),
|
||||
ParamType::Bytes => format!("Token::Bytes({})", name),
|
||||
ParamType::FixedBytes(len) if len <= 32 =>
|
||||
format!("Token::FixedBytes({}.0.to_vec())", name),
|
||||
ParamType::FixedBytes(len) => {
|
||||
needs_mut = true;
|
||||
format!("{}.resize({}, 0); Token::FixedBytes({})", name, len, name)
|
||||
}
|
||||
ParamType::Int(width) => match width {
|
||||
8 => format!("let mut r = [0xff; 32]; r[31] = {}; Token::Int(r)", name),
|
||||
16 | 32 | 64 =>
|
||||
format!("let mut r = [0xff; 32]; BigEndian::write_i{}(&mut r[{}..], {}); Token::Int(r))",
|
||||
width, 32 - (width / 8), name),
|
||||
_ => panic!("Signed int with more than 64 bits not supported."),
|
||||
},
|
||||
ParamType::Uint(width) => format!(
|
||||
"let mut r = [0; 32]; {}.to_big_endian(&mut r); Token::Uint(r)",
|
||||
if width <= 64 { format!("util::U256::from({} as u64)", name) }
|
||||
else { format!("util::U256::from({})", name) }
|
||||
),
|
||||
ParamType::Bool => format!("Token::Bool({})", name),
|
||||
ParamType::String => format!("Token::String({})", name),
|
||||
ParamType::Array(kind) => {
|
||||
let (needs_mut, code) = tokenize("i", *kind);
|
||||
format!("Token::Array({}.into_iter().map(|{}i| {{ {} }}).collect())",
|
||||
name, if needs_mut { "mut " } else { "" }, code)
|
||||
}
|
||||
ParamType::FixedArray(_, _) => panic!("Fixed-length arrays not supported."),
|
||||
};
|
||||
|
||||
(needs_mut, code)
|
||||
}
|
||||
|
||||
// create code for detokenizing this parameter.
|
||||
// takes an output type and the identifier of a token.
|
||||
// expands to code that evaluates to a Option<concrete type>
|
||||
// panics on unsupported types.
|
||||
fn detokenize(name: &str, output_type: ParamType) -> String {
|
||||
match output_type {
|
||||
ParamType::Address => format!("{}.to_address().map(util::H160)", name),
|
||||
ParamType::Bytes => format!("{}.to_bytes()", name),
|
||||
ParamType::FixedBytes(len) if len <= 32 => {
|
||||
// ensure no panic on slice too small.
|
||||
let read_hash = format!("b.resize({}, 0); util::H{}::from_slice(&b[..{}])",
|
||||
len, len * 8, len);
|
||||
|
||||
format!("{}.to_fixed_bytes().map(|mut b| {{ {} }})",
|
||||
name, read_hash)
|
||||
}
|
||||
ParamType::FixedBytes(_) => format!("{}.to_fixed_bytes()", name),
|
||||
ParamType::Int(width) => {
|
||||
let read_int = match width {
|
||||
8 => "i[31] as i8".into(),
|
||||
16 | 32 | 64 => format!("BigEndian::read_i{}(&i[{}..])", width, 32 - (width / 8)),
|
||||
_ => panic!("Signed integers over 64 bytes not allowed."),
|
||||
};
|
||||
format!("{}.to_int().map(|i| {})", name, read_int)
|
||||
}
|
||||
ParamType::Uint(width) => {
|
||||
let read_uint = match width {
|
||||
8 | 16 | 32 | 64 => format!("util::U256(u).low_u64() as u{}", width),
|
||||
_ => format!("util::U{}::from(&u[..])", width),
|
||||
};
|
||||
|
||||
format!("{}.to_uint().map(|u| {})", name, read_uint)
|
||||
}
|
||||
ParamType::Bool => format!("{}.to_bool()", name),
|
||||
ParamType::String => format!("{}.to_string()", name),
|
||||
ParamType::Array(kind) => {
|
||||
let read_array = format!("x.into_iter().map(|a| {{ {} }}).collect::<Option<Vec<_>>()",
|
||||
detokenize("a", *kind));
|
||||
|
||||
format!("{}.to_array().and_then(|x| {})",
|
||||
name, read_array)
|
||||
}
|
||||
ParamType::FixedArray(_, _) => panic!("Fixed-length arrays not supported.")
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use ethabi::spec::ParamType;
|
||||
|
||||
#[test]
|
||||
fn input_types() {
|
||||
assert_eq!(::input_params_codegen(&[]).unwrap().0, "");
|
||||
assert_eq!(::input_params_codegen(&[ParamType::Address]).unwrap().0, "param_0: util::Address, ");
|
||||
assert_eq!(::input_params_codegen(&[ParamType::Address, ParamType::Bytes]).unwrap().0,
|
||||
"param_0: util::Address, param_1: Vec<u8>, ");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn output_types() {
|
||||
assert_eq!(::output_params_codegen(&[]).unwrap().0, "()");
|
||||
assert_eq!(::output_params_codegen(&[ParamType::Address]).unwrap().0, "(util::Address)");
|
||||
assert_eq!(::output_params_codegen(&[ParamType::Address, ParamType::Array(Box::new(ParamType::Bytes))]).unwrap().0,
|
||||
"(util::Address, Vec<Vec<u8>>)");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rust_type() {
|
||||
assert_eq!(::rust_type(ParamType::FixedBytes(32)).unwrap(), "util::H256");
|
||||
assert_eq!(::rust_type(ParamType::Array(Box::new(ParamType::FixedBytes(32)))).unwrap(),
|
||||
"Vec<util::H256>");
|
||||
|
||||
assert_eq!(::rust_type(ParamType::Uint(64)).unwrap(), "u64");
|
||||
assert!(::rust_type(ParamType::Uint(63)).is_err());
|
||||
|
||||
assert_eq!(::rust_type(ParamType::Int(32)).unwrap(), "i32");
|
||||
assert_eq!(::rust_type(ParamType::Uint(256)).unwrap(), "util::U256");
|
||||
}
|
||||
|
||||
// codegen tests will need bootstrapping of some kind.
|
||||
}
|
30
ethcore/native_contracts/src/lib.rs
Normal file
30
ethcore/native_contracts/src/lib.rs
Normal file
@ -0,0 +1,30 @@
|
||||
// Copyright 2015-2017 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity.
|
||||
|
||||
// Parity is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// Parity is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! Native contracts useful for Parity. These are type-safe wrappers
|
||||
//! autogenerated at compile-time from Ethereum ABIs, and can be instantiated
|
||||
//! given any closure which can dispatch calls to them asynchronously.
|
||||
|
||||
extern crate futures;
|
||||
extern crate byteorder;
|
||||
extern crate ethabi;
|
||||
extern crate ethcore_util as util;
|
||||
|
||||
mod registry;
|
||||
mod service_transaction;
|
||||
|
||||
pub use self::registry::Registry;
|
||||
pub use self::service_transaction::ServiceTransactionChecker;
|
22
ethcore/native_contracts/src/registry.rs
Normal file
22
ethcore/native_contracts/src/registry.rs
Normal file
@ -0,0 +1,22 @@
|
||||
// Copyright 2015-2017 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity.
|
||||
|
||||
// Parity is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// Parity is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#![allow(unused_mut, unused_variables, unused_imports)]
|
||||
|
||||
//! Registrar contract: maps names to addresses and data.
|
||||
// TODO: testing.
|
||||
|
||||
include!(concat!(env!("OUT_DIR"), "/registry.rs"));
|
22
ethcore/native_contracts/src/service_transaction.rs
Normal file
22
ethcore/native_contracts/src/service_transaction.rs
Normal file
@ -0,0 +1,22 @@
|
||||
// Copyright 2015-2017 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Parity.
|
||||
|
||||
// Parity is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// Parity is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#![allow(unused_mut, unused_variables, unused_imports)]
|
||||
|
||||
//! Service transaction contract.
|
||||
// TODO: testing.
|
||||
|
||||
include!(concat!(env!("OUT_DIR"), "/service_transaction.rs"));
|
@ -30,47 +30,48 @@ use util::trie::TrieSpec;
|
||||
use util::kvdb::*;
|
||||
|
||||
// other
|
||||
use io::*;
|
||||
use views::BlockView;
|
||||
use error::{ImportError, ExecutionError, CallError, BlockError, ImportResult, Error as EthcoreError};
|
||||
use header::BlockNumber;
|
||||
use state::{self, State, CleanupMode};
|
||||
use spec::Spec;
|
||||
use basic_types::Seal;
|
||||
use engines::Engine;
|
||||
use service::ClientIoMessage;
|
||||
use env_info::LastHashes;
|
||||
use verification;
|
||||
use verification::{PreverifiedBlock, Verifier};
|
||||
use block::*;
|
||||
use transaction::{LocalizedTransaction, UnverifiedTransaction, SignedTransaction, Transaction, PendingTransaction, Action};
|
||||
use blockchain::extras::TransactionAddress;
|
||||
use types::filter::Filter;
|
||||
use types::mode::Mode as IpcMode;
|
||||
use log_entry::LocalizedLogEntry;
|
||||
use verification::queue::BlockQueue;
|
||||
use blockchain::{BlockChain, BlockProvider, TreeRoute, ImportRoute};
|
||||
use blockchain::extras::TransactionAddress;
|
||||
use client::Error as ClientError;
|
||||
use client::{
|
||||
BlockId, TransactionId, UncleId, TraceId, ClientConfig, BlockChainClient,
|
||||
MiningBlockChainClient, EngineClient, TraceFilter, CallAnalytics, BlockImportError, Mode,
|
||||
ChainNotify, PruningInfo,
|
||||
};
|
||||
use client::Error as ClientError;
|
||||
use env_info::EnvInfo;
|
||||
use executive::{Executive, Executed, TransactOptions, contract_address};
|
||||
use receipt::{Receipt, LocalizedReceipt};
|
||||
use trace::{TraceDB, ImportRequest as TraceImportRequest, LocalizedTrace, Database as TraceDatabase};
|
||||
use trace;
|
||||
use trace::FlatTransactionTraces;
|
||||
use evm::{Factory as EvmFactory, Schedule};
|
||||
use miner::{Miner, MinerService, TransactionImportResult};
|
||||
use snapshot::{self, io as snapshot_io};
|
||||
use factory::Factories;
|
||||
use rlp::UntrustedRlp;
|
||||
use state_db::StateDB;
|
||||
use rand::OsRng;
|
||||
use client::registry::Registry;
|
||||
use encoded;
|
||||
use engines::Engine;
|
||||
use env_info::EnvInfo;
|
||||
use env_info::LastHashes;
|
||||
use error::{ImportError, ExecutionError, CallError, BlockError, ImportResult, Error as EthcoreError};
|
||||
use evm::{Factory as EvmFactory, Schedule};
|
||||
use executive::{Executive, Executed, TransactOptions, contract_address};
|
||||
use factory::Factories;
|
||||
use futures::{future, Future};
|
||||
use header::BlockNumber;
|
||||
use io::*;
|
||||
use log_entry::LocalizedLogEntry;
|
||||
use miner::{Miner, MinerService, TransactionImportResult};
|
||||
use native_contracts::Registry;
|
||||
use rand::OsRng;
|
||||
use receipt::{Receipt, LocalizedReceipt};
|
||||
use rlp::UntrustedRlp;
|
||||
use service::ClientIoMessage;
|
||||
use snapshot::{self, io as snapshot_io};
|
||||
use spec::Spec;
|
||||
use state_db::StateDB;
|
||||
use state::{self, State, CleanupMode};
|
||||
use trace;
|
||||
use trace::{TraceDB, ImportRequest as TraceImportRequest, LocalizedTrace, Database as TraceDatabase};
|
||||
use trace::FlatTransactionTraces;
|
||||
use transaction::{LocalizedTransaction, UnverifiedTransaction, SignedTransaction, Transaction, PendingTransaction, Action};
|
||||
use types::filter::Filter;
|
||||
use types::mode::Mode as IpcMode;
|
||||
use verification;
|
||||
use verification::{PreverifiedBlock, Verifier};
|
||||
use verification::queue::BlockQueue;
|
||||
use views::BlockView;
|
||||
|
||||
// re-export
|
||||
pub use types::blockchain_info::BlockChainInfo;
|
||||
@ -254,8 +255,7 @@ impl Client {
|
||||
|
||||
if let Some(reg_addr) = client.additional_params().get("registrar").and_then(|s| Address::from_str(s).ok()) {
|
||||
trace!(target: "client", "Found registrar at {}", reg_addr);
|
||||
let weak = Arc::downgrade(&client);
|
||||
let registrar = Registry::new(reg_addr, move |a, d| weak.upgrade().ok_or("No client!".into()).and_then(|c| c.call_contract(BlockId::Latest, a, d)));
|
||||
let registrar = Registry::new(reg_addr);
|
||||
*client.registrar.lock() = Some(registrar);
|
||||
}
|
||||
Ok(client)
|
||||
@ -1488,12 +1488,17 @@ impl BlockChainClient for Client {
|
||||
}
|
||||
|
||||
fn registrar_address(&self) -> Option<Address> {
|
||||
self.registrar.lock().as_ref().map(|r| r.address.clone())
|
||||
self.registrar.lock().as_ref().map(|r| r.address)
|
||||
}
|
||||
|
||||
fn registry_address(&self, name: String) -> Option<Address> {
|
||||
self.registrar.lock().as_ref()
|
||||
.and_then(|r| r.get_address(&(name.as_bytes().sha3()), "A").ok())
|
||||
.and_then(|r| {
|
||||
let dispatch = move |reg_addr, data| {
|
||||
future::done(self.call_contract(BlockId::Latest, reg_addr, data))
|
||||
};
|
||||
r.get_address(dispatch, name.as_bytes().sha3(), "A".to_string()).wait().ok()
|
||||
})
|
||||
.and_then(|a| if a.is_zero() { None } else { Some(a) })
|
||||
}
|
||||
}
|
||||
|
@ -16,7 +16,6 @@
|
||||
|
||||
//! Blockchain database client.
|
||||
|
||||
mod registry;
|
||||
mod config;
|
||||
mod error;
|
||||
mod test_client;
|
||||
|
@ -1,338 +0,0 @@
|
||||
// Autogenerated from JSON contract definition using Rust contract convertor.
|
||||
// Command line: --name=Registry --jsonabi=/Users/gav/registry.abi
|
||||
#![allow(unused_imports)]
|
||||
use std::string::String;
|
||||
use std::result::Result;
|
||||
use std::fmt;
|
||||
use {util, ethabi};
|
||||
use util::{Uint};
|
||||
|
||||
pub struct Registry {
|
||||
contract: ethabi::Contract,
|
||||
pub address: util::Address,
|
||||
do_call: Box<Fn(util::Address, Vec<u8>) -> Result<Vec<u8>, String> + Send + Sync + 'static>,
|
||||
}
|
||||
impl Registry {
|
||||
pub fn new<F>(address: util::Address, do_call: F) -> Self
|
||||
where F: Fn(util::Address, Vec<u8>) -> Result<Vec<u8>, String> + Send + Sync + 'static {
|
||||
Registry {
|
||||
contract: ethabi::Contract::new(ethabi::Interface::load(b"[{\"constant\":true,\"inputs\":[{\"name\":\"_data\",\"type\":\"address\"}],\"name\":\"canReverse\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_new\",\"type\":\"address\"}],\"name\":\"setOwner\",\"outputs\":[],\"payable\":false,\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_name\",\"type\":\"bytes32\"},{\"name\":\"_key\",\"type\":\"string\"},{\"name\":\"_value\",\"type\":\"bytes32\"}],\"name\":\"setData\",\"outputs\":[{\"name\":\"success\",\"type\":\"bool\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_name\",\"type\":\"string\"}],\"name\":\"confirmReverse\",\"outputs\":[{\"name\":\"success\",\"type\":\"bool\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_name\",\"type\":\"bytes32\"}],\"name\":\"reserve\",\"outputs\":[{\"name\":\"success\",\"type\":\"bool\"}],\"payable\":true,\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_name\",\"type\":\"bytes32\"}],\"name\":\"drop\",\"outputs\":[{\"name\":\"success\",\"type\":\"bool\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_name\",\"type\":\"bytes32\"},{\"name\":\"_key\",\"type\":\"string\"}],\"name\":\"getAddress\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_amount\",\"type\":\"uint256\"}],\"name\":\"setFee\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_name\",\"type\":\"bytes32\"},{\"name\":\"_to\",\"type\":\"address\"}],\"name\":\"transfer\",\"outputs\":[{\"name\":\"success\",\"type\":\"bool\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_name\",\"type\":\"bytes32\"},{\"name\":\"_key\",\"type\":\"string\"}],\"name\":\"getData\",\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_name\",\"type\":\"bytes32\"}],\"name\":\"reserved\",\"outputs\":[{\"name\":\"reserved\",\"type\":\"bool\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"drain\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_name\",\"type\":\"string\"},{\"name\":\"_who\",\"type\":\"address\"}],\"name\":\"proposeReverse\",\"outputs\":[{\"name\":\"success\",\"type\":\"bool\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_name\",\"type\":\"bytes32\"}],\"name\":\"hasReverse\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_name\",\"type\":\"bytes32\"},{\"name\":\"_key\",\"type\":\"string\"}],\"name\":\"getUint\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"fee\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_name\",\"type\":\"bytes32\"}],\"name\":\"getOwner\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_name\",\"type\":\"bytes32\"}],\"name\":\"getReverse\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_data\",\"type\":\"address\"}],\"name\":\"reverse\",\"outputs\":[{\"name\":\"\",\"type\":\"string\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_name\",\"type\":\"bytes32\"},{\"name\":\"_key\",\"type\":\"string\"},{\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"setUint\",\"outputs\":[{\"name\":\"success\",\"type\":\"bool\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_name\",\"type\":\"string\"},{\"name\":\"_who\",\"type\":\"address\"}],\"name\":\"confirmReverseAs\",\"outputs\":[{\"name\":\"success\",\"type\":\"bool\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"removeReverse\",\"outputs\":[],\"payable\":false,\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_name\",\"type\":\"bytes32\"},{\"name\":\"_key\",\"type\":\"string\"},{\"name\":\"_value\",\"type\":\"address\"}],\"name\":\"setAddress\",\"outputs\":[{\"name\":\"success\",\"type\":\"bool\"}],\"payable\":false,\"type\":\"function\"}]").expect("JSON is autogenerated; qed")),
|
||||
address: address,
|
||||
do_call: Box::new(do_call),
|
||||
}
|
||||
}
|
||||
fn as_string<T: fmt::Debug>(e: T) -> String { format!("{:?}", e) }
|
||||
|
||||
/// Auto-generated from: `{"constant":true,"inputs":[{"name":"_data","type":"address"}],"name":"canReverse","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"}`
|
||||
#[allow(dead_code)]
|
||||
pub fn can_reverse(&self, _data: &util::Address) -> Result<bool, String>
|
||||
{
|
||||
let call = self.contract.function("canReverse".into()).map_err(Self::as_string)?;
|
||||
let data = call.encode_call(
|
||||
vec![ethabi::Token::Address(_data.clone().0)]
|
||||
).map_err(Self::as_string)?;
|
||||
let output = call.decode_output((self.do_call)(self.address.clone(), data)?).map_err(Self::as_string)?;
|
||||
let mut result = output.into_iter().rev().collect::<Vec<_>>();
|
||||
Ok(({ let r = result.pop().ok_or("Invalid return arity")?; let r = r.to_bool().ok_or("Invalid type returned")?; r }))
|
||||
}
|
||||
|
||||
/// Auto-generated from: `{"constant":false,"inputs":[{"name":"_new","type":"address"}],"name":"setOwner","outputs":[],"payable":false,"type":"function"}`
|
||||
#[allow(dead_code)]
|
||||
pub fn set_owner(&self, _new: &util::Address) -> Result<(), String>
|
||||
{
|
||||
let call = self.contract.function("setOwner".into()).map_err(Self::as_string)?;
|
||||
let data = call.encode_call(
|
||||
vec![ethabi::Token::Address(_new.clone().0)]
|
||||
).map_err(Self::as_string)?;
|
||||
call.decode_output((self.do_call)(self.address.clone(), data)?).map_err(Self::as_string)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Auto-generated from: `{"constant":false,"inputs":[{"name":"_name","type":"bytes32"},{"name":"_key","type":"string"},{"name":"_value","type":"bytes32"}],"name":"setData","outputs":[{"name":"success","type":"bool"}],"payable":false,"type":"function"}`
|
||||
#[allow(dead_code)]
|
||||
pub fn set_data(&self, _name: &util::H256, _key: &str, _value: &util::H256) -> Result<bool, String>
|
||||
{
|
||||
let call = self.contract.function("setData".into()).map_err(Self::as_string)?;
|
||||
let data = call.encode_call(
|
||||
vec![ethabi::Token::FixedBytes(_name.as_ref().to_owned()), ethabi::Token::String(_key.to_owned()), ethabi::Token::FixedBytes(_value.as_ref().to_owned())]
|
||||
).map_err(Self::as_string)?;
|
||||
let output = call.decode_output((self.do_call)(self.address.clone(), data)?).map_err(Self::as_string)?;
|
||||
let mut result = output.into_iter().rev().collect::<Vec<_>>();
|
||||
Ok(({ let r = result.pop().ok_or("Invalid return arity")?; let r = r.to_bool().ok_or("Invalid type returned")?; r }))
|
||||
}
|
||||
|
||||
/// Auto-generated from: `{"constant":false,"inputs":[{"name":"_name","type":"string"}],"name":"confirmReverse","outputs":[{"name":"success","type":"bool"}],"payable":false,"type":"function"}`
|
||||
#[allow(dead_code)]
|
||||
pub fn confirm_reverse(&self, _name: &str) -> Result<bool, String>
|
||||
{
|
||||
let call = self.contract.function("confirmReverse".into()).map_err(Self::as_string)?;
|
||||
let data = call.encode_call(
|
||||
vec![ethabi::Token::String(_name.to_owned())]
|
||||
).map_err(Self::as_string)?;
|
||||
let output = call.decode_output((self.do_call)(self.address.clone(), data)?).map_err(Self::as_string)?;
|
||||
let mut result = output.into_iter().rev().collect::<Vec<_>>();
|
||||
Ok(({ let r = result.pop().ok_or("Invalid return arity")?; let r = r.to_bool().ok_or("Invalid type returned")?; r }))
|
||||
}
|
||||
|
||||
/// Auto-generated from: `{"constant":false,"inputs":[{"name":"_name","type":"bytes32"}],"name":"reserve","outputs":[{"name":"success","type":"bool"}],"payable":true,"type":"function"}`
|
||||
#[allow(dead_code)]
|
||||
pub fn reserve(&self, _name: &util::H256) -> Result<bool, String>
|
||||
{
|
||||
let call = self.contract.function("reserve".into()).map_err(Self::as_string)?;
|
||||
let data = call.encode_call(
|
||||
vec![ethabi::Token::FixedBytes(_name.as_ref().to_owned())]
|
||||
).map_err(Self::as_string)?;
|
||||
let output = call.decode_output((self.do_call)(self.address.clone(), data)?).map_err(Self::as_string)?;
|
||||
let mut result = output.into_iter().rev().collect::<Vec<_>>();
|
||||
Ok(({ let r = result.pop().ok_or("Invalid return arity")?; let r = r.to_bool().ok_or("Invalid type returned")?; r }))
|
||||
}
|
||||
|
||||
/// Auto-generated from: `{"constant":false,"inputs":[{"name":"_name","type":"bytes32"}],"name":"drop","outputs":[{"name":"success","type":"bool"}],"payable":false,"type":"function"}`
|
||||
#[allow(dead_code)]
|
||||
pub fn drop(&self, _name: &util::H256) -> Result<bool, String>
|
||||
{
|
||||
let call = self.contract.function("drop".into()).map_err(Self::as_string)?;
|
||||
let data = call.encode_call(
|
||||
vec![ethabi::Token::FixedBytes(_name.as_ref().to_owned())]
|
||||
).map_err(Self::as_string)?;
|
||||
let output = call.decode_output((self.do_call)(self.address.clone(), data)?).map_err(Self::as_string)?;
|
||||
let mut result = output.into_iter().rev().collect::<Vec<_>>();
|
||||
Ok(({ let r = result.pop().ok_or("Invalid return arity")?; let r = r.to_bool().ok_or("Invalid type returned")?; r }))
|
||||
}
|
||||
|
||||
/// Auto-generated from: `{"constant":true,"inputs":[{"name":"_name","type":"bytes32"},{"name":"_key","type":"string"}],"name":"getAddress","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"}`
|
||||
#[allow(dead_code)]
|
||||
pub fn get_address(&self, _name: &util::H256, _key: &str) -> Result<util::Address, String>
|
||||
{
|
||||
let call = self.contract.function("getAddress".into()).map_err(Self::as_string)?;
|
||||
let data = call.encode_call(
|
||||
vec![ethabi::Token::FixedBytes(_name.as_ref().to_owned()), ethabi::Token::String(_key.to_owned())]
|
||||
).map_err(Self::as_string)?;
|
||||
let output = call.decode_output((self.do_call)(self.address.clone(), data)?).map_err(Self::as_string)?;
|
||||
let mut result = output.into_iter().rev().collect::<Vec<_>>();
|
||||
Ok(({ let r = result.pop().ok_or("Invalid return arity")?; let r = r.to_address().ok_or("Invalid type returned")?; util::Address::from(r) }))
|
||||
}
|
||||
|
||||
/// Auto-generated from: `{"constant":false,"inputs":[{"name":"_amount","type":"uint256"}],"name":"setFee","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"}`
|
||||
#[allow(dead_code)]
|
||||
pub fn set_fee(&self, _amount: util::U256) -> Result<bool, String>
|
||||
{
|
||||
let call = self.contract.function("setFee".into()).map_err(Self::as_string)?;
|
||||
let data = call.encode_call(
|
||||
vec![ethabi::Token::Uint({ let mut r = [0u8; 32]; _amount.to_big_endian(&mut r); r })]
|
||||
).map_err(Self::as_string)?;
|
||||
let output = call.decode_output((self.do_call)(self.address.clone(), data)?).map_err(Self::as_string)?;
|
||||
let mut result = output.into_iter().rev().collect::<Vec<_>>();
|
||||
Ok(({ let r = result.pop().ok_or("Invalid return arity")?; let r = r.to_bool().ok_or("Invalid type returned")?; r }))
|
||||
}
|
||||
|
||||
/// Auto-generated from: `{"constant":false,"inputs":[{"name":"_name","type":"bytes32"},{"name":"_to","type":"address"}],"name":"transfer","outputs":[{"name":"success","type":"bool"}],"payable":false,"type":"function"}`
|
||||
#[allow(dead_code)]
|
||||
pub fn transfer(&self, _name: &util::H256, _to: &util::Address) -> Result<bool, String>
|
||||
{
|
||||
let call = self.contract.function("transfer".into()).map_err(Self::as_string)?;
|
||||
let data = call.encode_call(
|
||||
vec![ethabi::Token::FixedBytes(_name.as_ref().to_owned()), ethabi::Token::Address(_to.clone().0)]
|
||||
).map_err(Self::as_string)?;
|
||||
let output = call.decode_output((self.do_call)(self.address.clone(), data)?).map_err(Self::as_string)?;
|
||||
let mut result = output.into_iter().rev().collect::<Vec<_>>();
|
||||
Ok(({ let r = result.pop().ok_or("Invalid return arity")?; let r = r.to_bool().ok_or("Invalid type returned")?; r }))
|
||||
}
|
||||
|
||||
/// Auto-generated from: `{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"}`
|
||||
#[allow(dead_code)]
|
||||
pub fn owner(&self) -> Result<util::Address, String>
|
||||
{
|
||||
let call = self.contract.function("owner".into()).map_err(Self::as_string)?;
|
||||
let data = call.encode_call(
|
||||
vec![]
|
||||
).map_err(Self::as_string)?;
|
||||
let output = call.decode_output((self.do_call)(self.address.clone(), data)?).map_err(Self::as_string)?;
|
||||
let mut result = output.into_iter().rev().collect::<Vec<_>>();
|
||||
Ok(({ let r = result.pop().ok_or("Invalid return arity")?; let r = r.to_address().ok_or("Invalid type returned")?; util::Address::from(r) }))
|
||||
}
|
||||
|
||||
/// Auto-generated from: `{"constant":true,"inputs":[{"name":"_name","type":"bytes32"},{"name":"_key","type":"string"}],"name":"getData","outputs":[{"name":"","type":"bytes32"}],"payable":false,"type":"function"}`
|
||||
#[allow(dead_code)]
|
||||
pub fn get_data(&self, _name: &util::H256, _key: &str) -> Result<util::H256, String>
|
||||
{
|
||||
let call = self.contract.function("getData".into()).map_err(Self::as_string)?;
|
||||
let data = call.encode_call(
|
||||
vec![ethabi::Token::FixedBytes(_name.as_ref().to_owned()), ethabi::Token::String(_key.to_owned())]
|
||||
).map_err(Self::as_string)?;
|
||||
let output = call.decode_output((self.do_call)(self.address.clone(), data)?).map_err(Self::as_string)?;
|
||||
let mut result = output.into_iter().rev().collect::<Vec<_>>();
|
||||
Ok(({ let r = result.pop().ok_or("Invalid return arity")?; let r = r.to_fixed_bytes().ok_or("Invalid type returned")?; util::H256::from_slice(r.as_ref()) }))
|
||||
}
|
||||
|
||||
/// Auto-generated from: `{"constant":true,"inputs":[{"name":"_name","type":"bytes32"}],"name":"reserved","outputs":[{"name":"reserved","type":"bool"}],"payable":false,"type":"function"}`
|
||||
#[allow(dead_code)]
|
||||
pub fn reserved(&self, _name: &util::H256) -> Result<bool, String>
|
||||
{
|
||||
let call = self.contract.function("reserved".into()).map_err(Self::as_string)?;
|
||||
let data = call.encode_call(
|
||||
vec![ethabi::Token::FixedBytes(_name.as_ref().to_owned())]
|
||||
).map_err(Self::as_string)?;
|
||||
let output = call.decode_output((self.do_call)(self.address.clone(), data)?).map_err(Self::as_string)?;
|
||||
let mut result = output.into_iter().rev().collect::<Vec<_>>();
|
||||
Ok(({ let r = result.pop().ok_or("Invalid return arity")?; let r = r.to_bool().ok_or("Invalid type returned")?; r }))
|
||||
}
|
||||
|
||||
/// Auto-generated from: `{"constant":false,"inputs":[],"name":"drain","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"}`
|
||||
#[allow(dead_code)]
|
||||
pub fn drain(&self) -> Result<bool, String>
|
||||
{
|
||||
let call = self.contract.function("drain".into()).map_err(Self::as_string)?;
|
||||
let data = call.encode_call(
|
||||
vec![]
|
||||
).map_err(Self::as_string)?;
|
||||
let output = call.decode_output((self.do_call)(self.address.clone(), data)?).map_err(Self::as_string)?;
|
||||
let mut result = output.into_iter().rev().collect::<Vec<_>>();
|
||||
Ok(({ let r = result.pop().ok_or("Invalid return arity")?; let r = r.to_bool().ok_or("Invalid type returned")?; r }))
|
||||
}
|
||||
|
||||
/// Auto-generated from: `{"constant":false,"inputs":[{"name":"_name","type":"string"},{"name":"_who","type":"address"}],"name":"proposeReverse","outputs":[{"name":"success","type":"bool"}],"payable":false,"type":"function"}`
|
||||
#[allow(dead_code)]
|
||||
pub fn propose_reverse(&self, _name: &str, _who: &util::Address) -> Result<bool, String>
|
||||
{
|
||||
let call = self.contract.function("proposeReverse".into()).map_err(Self::as_string)?;
|
||||
let data = call.encode_call(
|
||||
vec![ethabi::Token::String(_name.to_owned()), ethabi::Token::Address(_who.clone().0)]
|
||||
).map_err(Self::as_string)?;
|
||||
let output = call.decode_output((self.do_call)(self.address.clone(), data)?).map_err(Self::as_string)?;
|
||||
let mut result = output.into_iter().rev().collect::<Vec<_>>();
|
||||
Ok(({ let r = result.pop().ok_or("Invalid return arity")?; let r = r.to_bool().ok_or("Invalid type returned")?; r }))
|
||||
}
|
||||
|
||||
/// Auto-generated from: `{"constant":true,"inputs":[{"name":"_name","type":"bytes32"}],"name":"hasReverse","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"}`
|
||||
#[allow(dead_code)]
|
||||
pub fn has_reverse(&self, _name: &util::H256) -> Result<bool, String>
|
||||
{
|
||||
let call = self.contract.function("hasReverse".into()).map_err(Self::as_string)?;
|
||||
let data = call.encode_call(
|
||||
vec![ethabi::Token::FixedBytes(_name.as_ref().to_owned())]
|
||||
).map_err(Self::as_string)?;
|
||||
let output = call.decode_output((self.do_call)(self.address.clone(), data)?).map_err(Self::as_string)?;
|
||||
let mut result = output.into_iter().rev().collect::<Vec<_>>();
|
||||
Ok(({ let r = result.pop().ok_or("Invalid return arity")?; let r = r.to_bool().ok_or("Invalid type returned")?; r }))
|
||||
}
|
||||
|
||||
/// Auto-generated from: `{"constant":true,"inputs":[{"name":"_name","type":"bytes32"},{"name":"_key","type":"string"}],"name":"getUint","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"}`
|
||||
#[allow(dead_code)]
|
||||
pub fn get_uint(&self, _name: &util::H256, _key: &str) -> Result<util::U256, String>
|
||||
{
|
||||
let call = self.contract.function("getUint".into()).map_err(Self::as_string)?;
|
||||
let data = call.encode_call(
|
||||
vec![ethabi::Token::FixedBytes(_name.as_ref().to_owned()), ethabi::Token::String(_key.to_owned())]
|
||||
).map_err(Self::as_string)?;
|
||||
let output = call.decode_output((self.do_call)(self.address.clone(), data)?).map_err(Self::as_string)?;
|
||||
let mut result = output.into_iter().rev().collect::<Vec<_>>();
|
||||
Ok(({ let r = result.pop().ok_or("Invalid return arity")?; let r = r.to_uint().ok_or("Invalid type returned")?; util::U256::from(r.as_ref()) }))
|
||||
}
|
||||
|
||||
/// Auto-generated from: `{"constant":true,"inputs":[],"name":"fee","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"}`
|
||||
#[allow(dead_code)]
|
||||
pub fn fee(&self) -> Result<util::U256, String>
|
||||
{
|
||||
let call = self.contract.function("fee".into()).map_err(Self::as_string)?;
|
||||
let data = call.encode_call(
|
||||
vec![]
|
||||
).map_err(Self::as_string)?;
|
||||
let output = call.decode_output((self.do_call)(self.address.clone(), data)?).map_err(Self::as_string)?;
|
||||
let mut result = output.into_iter().rev().collect::<Vec<_>>();
|
||||
Ok(({ let r = result.pop().ok_or("Invalid return arity")?; let r = r.to_uint().ok_or("Invalid type returned")?; util::U256::from(r.as_ref()) }))
|
||||
}
|
||||
|
||||
/// Auto-generated from: `{"constant":true,"inputs":[{"name":"_name","type":"bytes32"}],"name":"getOwner","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"}`
|
||||
#[allow(dead_code)]
|
||||
pub fn get_owner(&self, _name: &util::H256) -> Result<util::Address, String>
|
||||
{
|
||||
let call = self.contract.function("getOwner".into()).map_err(Self::as_string)?;
|
||||
let data = call.encode_call(
|
||||
vec![ethabi::Token::FixedBytes(_name.as_ref().to_owned())]
|
||||
).map_err(Self::as_string)?;
|
||||
let output = call.decode_output((self.do_call)(self.address.clone(), data)?).map_err(Self::as_string)?;
|
||||
let mut result = output.into_iter().rev().collect::<Vec<_>>();
|
||||
Ok(({ let r = result.pop().ok_or("Invalid return arity")?; let r = r.to_address().ok_or("Invalid type returned")?; util::Address::from(r) }))
|
||||
}
|
||||
|
||||
/// Auto-generated from: `{"constant":true,"inputs":[{"name":"_name","type":"bytes32"}],"name":"getReverse","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"}`
|
||||
#[allow(dead_code)]
|
||||
pub fn get_reverse(&self, _name: &util::H256) -> Result<util::Address, String>
|
||||
{
|
||||
let call = self.contract.function("getReverse".into()).map_err(Self::as_string)?;
|
||||
let data = call.encode_call(
|
||||
vec![ethabi::Token::FixedBytes(_name.as_ref().to_owned())]
|
||||
).map_err(Self::as_string)?;
|
||||
let output = call.decode_output((self.do_call)(self.address.clone(), data)?).map_err(Self::as_string)?;
|
||||
let mut result = output.into_iter().rev().collect::<Vec<_>>();
|
||||
Ok(({ let r = result.pop().ok_or("Invalid return arity")?; let r = r.to_address().ok_or("Invalid type returned")?; util::Address::from(r) }))
|
||||
}
|
||||
|
||||
/// Auto-generated from: `{"constant":true,"inputs":[{"name":"_data","type":"address"}],"name":"reverse","outputs":[{"name":"","type":"string"}],"payable":false,"type":"function"}`
|
||||
#[allow(dead_code)]
|
||||
pub fn reverse(&self, _data: &util::Address) -> Result<String, String>
|
||||
{
|
||||
let call = self.contract.function("reverse".into()).map_err(Self::as_string)?;
|
||||
let data = call.encode_call(
|
||||
vec![ethabi::Token::Address(_data.clone().0)]
|
||||
).map_err(Self::as_string)?;
|
||||
let output = call.decode_output((self.do_call)(self.address.clone(), data)?).map_err(Self::as_string)?;
|
||||
let mut result = output.into_iter().rev().collect::<Vec<_>>();
|
||||
Ok(({ let r = result.pop().ok_or("Invalid return arity")?; let r = r.to_string().ok_or("Invalid type returned")?; r }))
|
||||
}
|
||||
|
||||
/// Auto-generated from: `{"constant":false,"inputs":[{"name":"_name","type":"bytes32"},{"name":"_key","type":"string"},{"name":"_value","type":"uint256"}],"name":"setUint","outputs":[{"name":"success","type":"bool"}],"payable":false,"type":"function"}`
|
||||
#[allow(dead_code)]
|
||||
pub fn set_uint(&self, _name: &util::H256, _key: &str, _value: util::U256) -> Result<bool, String>
|
||||
{
|
||||
let call = self.contract.function("setUint".into()).map_err(Self::as_string)?;
|
||||
let data = call.encode_call(
|
||||
vec![ethabi::Token::FixedBytes(_name.as_ref().to_owned()), ethabi::Token::String(_key.to_owned()), ethabi::Token::Uint({ let mut r = [0u8; 32]; _value.to_big_endian(&mut r); r })]
|
||||
).map_err(Self::as_string)?;
|
||||
let output = call.decode_output((self.do_call)(self.address.clone(), data)?).map_err(Self::as_string)?;
|
||||
let mut result = output.into_iter().rev().collect::<Vec<_>>();
|
||||
Ok(({ let r = result.pop().ok_or("Invalid return arity")?; let r = r.to_bool().ok_or("Invalid type returned")?; r }))
|
||||
}
|
||||
|
||||
/// Auto-generated from: `{"constant":false,"inputs":[{"name":"_name","type":"string"},{"name":"_who","type":"address"}],"name":"confirmReverseAs","outputs":[{"name":"success","type":"bool"}],"payable":false,"type":"function"}`
|
||||
#[allow(dead_code)]
|
||||
pub fn confirm_reverse_as(&self, _name: &str, _who: &util::Address) -> Result<bool, String>
|
||||
{
|
||||
let call = self.contract.function("confirmReverseAs".into()).map_err(Self::as_string)?;
|
||||
let data = call.encode_call(
|
||||
vec![ethabi::Token::String(_name.to_owned()), ethabi::Token::Address(_who.clone().0)]
|
||||
).map_err(Self::as_string)?;
|
||||
let output = call.decode_output((self.do_call)(self.address.clone(), data)?).map_err(Self::as_string)?;
|
||||
let mut result = output.into_iter().rev().collect::<Vec<_>>();
|
||||
Ok(({ let r = result.pop().ok_or("Invalid return arity")?; let r = r.to_bool().ok_or("Invalid type returned")?; r }))
|
||||
}
|
||||
|
||||
/// Auto-generated from: `{"constant":false,"inputs":[],"name":"removeReverse","outputs":[],"payable":false,"type":"function"}`
|
||||
#[allow(dead_code)]
|
||||
pub fn remove_reverse(&self) -> Result<(), String>
|
||||
{
|
||||
let call = self.contract.function("removeReverse".into()).map_err(Self::as_string)?;
|
||||
let data = call.encode_call(
|
||||
vec![]
|
||||
).map_err(Self::as_string)?;
|
||||
call.decode_output((self.do_call)(self.address.clone(), data)?).map_err(Self::as_string)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Auto-generated from: `{"constant":false,"inputs":[{"name":"_name","type":"bytes32"},{"name":"_key","type":"string"},{"name":"_value","type":"address"}],"name":"setAddress","outputs":[{"name":"success","type":"bool"}],"payable":false,"type":"function"}`
|
||||
#[allow(dead_code)]
|
||||
pub fn set_address(&self, _name: &util::H256, _key: &str, _value: &util::Address) -> Result<bool, String>
|
||||
{
|
||||
let call = self.contract.function("setAddress".into()).map_err(Self::as_string)?;
|
||||
let data = call.encode_call(
|
||||
vec![ethabi::Token::FixedBytes(_name.as_ref().to_owned()), ethabi::Token::String(_key.to_owned()), ethabi::Token::Address(_value.clone().0)]
|
||||
).map_err(Self::as_string)?;
|
||||
let output = call.decode_output((self.do_call)(self.address.clone(), data)?).map_err(Self::as_string)?;
|
||||
let mut result = output.into_iter().rev().collect::<Vec<_>>();
|
||||
Ok(({ let r = result.pop().ok_or("Invalid return arity")?; let r = r.to_bool().ok_or("Invalid type returned")?; r }))
|
||||
}
|
||||
}
|
||||
|
@ -79,37 +79,39 @@
|
||||
//! cargo build --release
|
||||
//! ```
|
||||
|
||||
extern crate ethcore_io as io;
|
||||
extern crate rustc_serialize;
|
||||
extern crate crypto;
|
||||
extern crate time;
|
||||
extern crate env_logger;
|
||||
extern crate num_cpus;
|
||||
extern crate crossbeam;
|
||||
extern crate ethjson;
|
||||
extern crate bloomchain;
|
||||
extern crate hyper;
|
||||
extern crate ethash;
|
||||
extern crate ethkey;
|
||||
extern crate semver;
|
||||
extern crate ethcore_ipc_nano as nanoipc;
|
||||
extern crate ethcore_devtools as devtools;
|
||||
extern crate rand;
|
||||
extern crate bit_set;
|
||||
extern crate rlp;
|
||||
extern crate ethcore_bloom_journal as bloom_journal;
|
||||
extern crate bloomchain;
|
||||
extern crate bn;
|
||||
extern crate byteorder;
|
||||
extern crate transient_hashmap;
|
||||
extern crate crossbeam;
|
||||
extern crate crypto;
|
||||
extern crate env_logger;
|
||||
extern crate ethabi;
|
||||
extern crate ethash;
|
||||
extern crate ethcore_bloom_journal as bloom_journal;
|
||||
extern crate ethcore_devtools as devtools;
|
||||
extern crate ethcore_io as io;
|
||||
extern crate ethcore_ipc_nano as nanoipc;
|
||||
extern crate ethcore_logger;
|
||||
extern crate ethcore_stratum;
|
||||
extern crate ethjson;
|
||||
extern crate ethkey;
|
||||
extern crate futures;
|
||||
extern crate hardware_wallet;
|
||||
extern crate hyper;
|
||||
extern crate itertools;
|
||||
extern crate linked_hash_map;
|
||||
extern crate lru_cache;
|
||||
extern crate ethcore_stratum;
|
||||
extern crate ethabi;
|
||||
extern crate hardware_wallet;
|
||||
extern crate stats;
|
||||
extern crate ethcore_logger;
|
||||
extern crate native_contracts;
|
||||
extern crate num_cpus;
|
||||
extern crate num;
|
||||
extern crate bn;
|
||||
extern crate itertools;
|
||||
extern crate rand;
|
||||
extern crate rlp;
|
||||
extern crate rustc_serialize;
|
||||
extern crate semver;
|
||||
extern crate stats;
|
||||
extern crate time;
|
||||
extern crate transient_hashmap;
|
||||
|
||||
#[macro_use]
|
||||
extern crate log;
|
||||
|
@ -14,9 +14,12 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
use types::ids::BlockId;
|
||||
use client::MiningBlockChainClient;
|
||||
use transaction::SignedTransaction;
|
||||
use types::ids::BlockId;
|
||||
|
||||
use futures::{future, Future};
|
||||
use native_contracts::ServiceTransactionChecker as Contract;
|
||||
use util::{U256, Uint, Mutex};
|
||||
|
||||
const SERVICE_TRANSACTION_CONTRACT_REGISTRY_NAME: &'static str = "service_transaction_checker";
|
||||
@ -24,7 +27,7 @@ const SERVICE_TRANSACTION_CONTRACT_REGISTRY_NAME: &'static str = "service_transa
|
||||
/// Service transactions checker.
|
||||
#[derive(Default)]
|
||||
pub struct ServiceTransactionChecker {
|
||||
contract: Mutex<Option<provider::Contract>>,
|
||||
contract: Mutex<Option<Contract>>,
|
||||
}
|
||||
|
||||
impl ServiceTransactionChecker {
|
||||
@ -36,7 +39,7 @@ impl ServiceTransactionChecker {
|
||||
.and_then(|contract_addr| {
|
||||
trace!(target: "txqueue", "Configuring for service transaction checker contract from {}", contract_addr);
|
||||
|
||||
Some(provider::Contract::new(contract_addr))
|
||||
Some(Contract::new(contract_addr))
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -46,168 +49,12 @@ impl ServiceTransactionChecker {
|
||||
debug_assert_eq!(tx.gas_price, U256::zero());
|
||||
|
||||
if let Some(ref contract) = *self.contract.lock() {
|
||||
let do_call = |a, d| client.call_contract(BlockId::Latest, a, d);
|
||||
contract.certified(&do_call, &tx.sender())
|
||||
contract.certified(
|
||||
|addr, data| future::done(client.call_contract(BlockId::Latest, addr, data)),
|
||||
tx.sender()
|
||||
).wait()
|
||||
} else {
|
||||
Err("contract is not configured".to_owned())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mod provider {
|
||||
// Autogenerated from JSON contract definition using Rust contract convertor.
|
||||
// Command line: --jsonabi=SimpleCertifier.abi --explicit-do-call
|
||||
#![allow(unused_imports)]
|
||||
use std::string::String;
|
||||
use std::result::Result;
|
||||
use std::fmt;
|
||||
use {util, ethabi};
|
||||
use util::{Uint};
|
||||
|
||||
pub struct Contract {
|
||||
contract: ethabi::Contract,
|
||||
address: util::Address,
|
||||
|
||||
}
|
||||
impl Contract {
|
||||
pub fn new(address: util::Address) -> Self
|
||||
{
|
||||
Contract {
|
||||
contract: ethabi::Contract::new(ethabi::Interface::load(b"[{\"constant\":false,\"inputs\":[{\"name\":\"_new\",\"type\":\"address\"}],\"name\":\"setOwner\",\"outputs\":[],\"payable\":false,\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_who\",\"type\":\"address\"}],\"name\":\"certify\",\"outputs\":[],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_who\",\"type\":\"address\"},{\"name\":\"_field\",\"type\":\"string\"}],\"name\":\"getAddress\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_who\",\"type\":\"address\"}],\"name\":\"revoke\",\"outputs\":[],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"delegate\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_who\",\"type\":\"address\"},{\"name\":\"_field\",\"type\":\"string\"}],\"name\":\"getUint\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_new\",\"type\":\"address\"}],\"name\":\"setDelegate\",\"outputs\":[],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_who\",\"type\":\"address\"}],\"name\":\"certified\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_who\",\"type\":\"address\"},{\"name\":\"_field\",\"type\":\"string\"}],\"name\":\"get\",\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\"}],\"payable\":false,\"type\":\"function\"}]").expect("JSON is autogenerated; qed")),
|
||||
address: address,
|
||||
|
||||
}
|
||||
}
|
||||
fn as_string<T: fmt::Debug>(e: T) -> String { format!("{:?}", e) }
|
||||
|
||||
/// Auto-generated from: `{"constant":false,"inputs":[{"name":"_new","type":"address"}],"name":"setOwner","outputs":[],"payable":false,"type":"function"}`
|
||||
#[allow(dead_code)]
|
||||
pub fn set_owner<F>(&self, do_call: &F, _new: &util::Address) -> Result<(), String>
|
||||
where F: Fn(util::Address, Vec<u8>) -> Result<Vec<u8>, String> + Send {
|
||||
let call = self.contract.function("setOwner".into()).map_err(Self::as_string)?;
|
||||
let data = call.encode_call(
|
||||
vec![ethabi::Token::Address(_new.clone().0)]
|
||||
).map_err(Self::as_string)?;
|
||||
call.decode_output((do_call)(self.address.clone(), data)?).map_err(Self::as_string)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Auto-generated from: `{"constant":false,"inputs":[{"name":"_who","type":"address"}],"name":"certify","outputs":[],"payable":false,"type":"function"}`
|
||||
#[allow(dead_code)]
|
||||
pub fn certify<F>(&self, do_call: &F, _who: &util::Address) -> Result<(), String>
|
||||
where F: Fn(util::Address, Vec<u8>) -> Result<Vec<u8>, String> + Send {
|
||||
let call = self.contract.function("certify".into()).map_err(Self::as_string)?;
|
||||
let data = call.encode_call(
|
||||
vec![ethabi::Token::Address(_who.clone().0)]
|
||||
).map_err(Self::as_string)?;
|
||||
call.decode_output((do_call)(self.address.clone(), data)?).map_err(Self::as_string)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Auto-generated from: `{"constant":true,"inputs":[{"name":"_who","type":"address"},{"name":"_field","type":"string"}],"name":"getAddress","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"}`
|
||||
#[allow(dead_code)]
|
||||
pub fn get_address<F>(&self, do_call: &F, _who: &util::Address, _field: &str) -> Result<util::Address, String>
|
||||
where F: Fn(util::Address, Vec<u8>) -> Result<Vec<u8>, String> + Send {
|
||||
let call = self.contract.function("getAddress".into()).map_err(Self::as_string)?;
|
||||
let data = call.encode_call(
|
||||
vec![ethabi::Token::Address(_who.clone().0), ethabi::Token::String(_field.to_owned())]
|
||||
).map_err(Self::as_string)?;
|
||||
let output = call.decode_output((do_call)(self.address.clone(), data)?).map_err(Self::as_string)?;
|
||||
let mut result = output.into_iter().rev().collect::<Vec<_>>();
|
||||
Ok(({ let r = result.pop().ok_or("Invalid return arity")?; let r = r.to_address().ok_or("Invalid type returned")?; util::Address::from(r) }))
|
||||
}
|
||||
|
||||
/// Auto-generated from: `{"constant":false,"inputs":[{"name":"_who","type":"address"}],"name":"revoke","outputs":[],"payable":false,"type":"function"}`
|
||||
#[allow(dead_code)]
|
||||
pub fn revoke<F>(&self, do_call: &F, _who: &util::Address) -> Result<(), String>
|
||||
where F: Fn(util::Address, Vec<u8>) -> Result<Vec<u8>, String> + Send {
|
||||
let call = self.contract.function("revoke".into()).map_err(Self::as_string)?;
|
||||
let data = call.encode_call(
|
||||
vec![ethabi::Token::Address(_who.clone().0)]
|
||||
).map_err(Self::as_string)?;
|
||||
call.decode_output((do_call)(self.address.clone(), data)?).map_err(Self::as_string)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Auto-generated from: `{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"}`
|
||||
#[allow(dead_code)]
|
||||
pub fn owner<F>(&self, do_call: &F) -> Result<util::Address, String>
|
||||
where F: Fn(util::Address, Vec<u8>) -> Result<Vec<u8>, String> + Send {
|
||||
let call = self.contract.function("owner".into()).map_err(Self::as_string)?;
|
||||
let data = call.encode_call(
|
||||
vec![]
|
||||
).map_err(Self::as_string)?;
|
||||
let output = call.decode_output((do_call)(self.address.clone(), data)?).map_err(Self::as_string)?;
|
||||
let mut result = output.into_iter().rev().collect::<Vec<_>>();
|
||||
Ok(({ let r = result.pop().ok_or("Invalid return arity")?; let r = r.to_address().ok_or("Invalid type returned")?; util::Address::from(r) }))
|
||||
}
|
||||
|
||||
/// Auto-generated from: `{"constant":true,"inputs":[],"name":"delegate","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"}`
|
||||
#[allow(dead_code)]
|
||||
pub fn delegate<F>(&self, do_call: &F) -> Result<util::Address, String>
|
||||
where F: Fn(util::Address, Vec<u8>) -> Result<Vec<u8>, String> + Send {
|
||||
let call = self.contract.function("delegate".into()).map_err(Self::as_string)?;
|
||||
let data = call.encode_call(
|
||||
vec![]
|
||||
).map_err(Self::as_string)?;
|
||||
let output = call.decode_output((do_call)(self.address.clone(), data)?).map_err(Self::as_string)?;
|
||||
let mut result = output.into_iter().rev().collect::<Vec<_>>();
|
||||
Ok(({ let r = result.pop().ok_or("Invalid return arity")?; let r = r.to_address().ok_or("Invalid type returned")?; util::Address::from(r) }))
|
||||
}
|
||||
|
||||
/// Auto-generated from: `{"constant":true,"inputs":[{"name":"_who","type":"address"},{"name":"_field","type":"string"}],"name":"getUint","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"}`
|
||||
#[allow(dead_code)]
|
||||
pub fn get_uint<F>(&self, do_call: &F, _who: &util::Address, _field: &str) -> Result<util::U256, String>
|
||||
where F: Fn(util::Address, Vec<u8>) -> Result<Vec<u8>, String> + Send {
|
||||
let call = self.contract.function("getUint".into()).map_err(Self::as_string)?;
|
||||
let data = call.encode_call(
|
||||
vec![ethabi::Token::Address(_who.clone().0), ethabi::Token::String(_field.to_owned())]
|
||||
).map_err(Self::as_string)?;
|
||||
let output = call.decode_output((do_call)(self.address.clone(), data)?).map_err(Self::as_string)?;
|
||||
let mut result = output.into_iter().rev().collect::<Vec<_>>();
|
||||
Ok(({ let r = result.pop().ok_or("Invalid return arity")?; let r = r.to_uint().ok_or("Invalid type returned")?; util::U256::from(r.as_ref()) }))
|
||||
}
|
||||
|
||||
/// Auto-generated from: `{"constant":false,"inputs":[{"name":"_new","type":"address"}],"name":"setDelegate","outputs":[],"payable":false,"type":"function"}`
|
||||
#[allow(dead_code)]
|
||||
pub fn set_delegate<F>(&self, do_call: &F, _new: &util::Address) -> Result<(), String>
|
||||
where F: Fn(util::Address, Vec<u8>) -> Result<Vec<u8>, String> + Send {
|
||||
let call = self.contract.function("setDelegate".into()).map_err(Self::as_string)?;
|
||||
let data = call.encode_call(
|
||||
vec![ethabi::Token::Address(_new.clone().0)]
|
||||
).map_err(Self::as_string)?;
|
||||
call.decode_output((do_call)(self.address.clone(), data)?).map_err(Self::as_string)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Auto-generated from: `{"constant":true,"inputs":[{"name":"_who","type":"address"}],"name":"certified","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"}`
|
||||
#[allow(dead_code)]
|
||||
pub fn certified<F>(&self, do_call: &F, _who: &util::Address) -> Result<bool, String>
|
||||
where F: Fn(util::Address, Vec<u8>) -> Result<Vec<u8>, String> + Send {
|
||||
let call = self.contract.function("certified".into()).map_err(Self::as_string)?;
|
||||
let data = call.encode_call(
|
||||
vec![ethabi::Token::Address(_who.clone().0)]
|
||||
).map_err(Self::as_string)?;
|
||||
let output = call.decode_output((do_call)(self.address.clone(), data)?).map_err(Self::as_string)?;
|
||||
let mut result = output.into_iter().rev().collect::<Vec<_>>();
|
||||
Ok(({ let r = result.pop().ok_or("Invalid return arity")?; let r = r.to_bool().ok_or("Invalid type returned")?; r }))
|
||||
}
|
||||
|
||||
/// Auto-generated from: `{"constant":true,"inputs":[{"name":"_who","type":"address"},{"name":"_field","type":"string"}],"name":"get","outputs":[{"name":"","type":"bytes32"}],"payable":false,"type":"function"}`
|
||||
#[allow(dead_code)]
|
||||
pub fn get<F>(&self, do_call: &F, _who: &util::Address, _field: &str) -> Result<util::H256, String>
|
||||
where F: Fn(util::Address, Vec<u8>) -> Result<Vec<u8>, String> + Send {
|
||||
let call = self.contract.function("get".into()).map_err(Self::as_string)?;
|
||||
let data = call.encode_call(
|
||||
vec![ethabi::Token::Address(_who.clone().0), ethabi::Token::String(_field.to_owned())]
|
||||
).map_err(Self::as_string)?;
|
||||
let output = call.decode_output((do_call)(self.address.clone(), data)?).map_err(Self::as_string)?;
|
||||
let mut result = output.into_iter().rev().collect::<Vec<_>>();
|
||||
Ok(({ let r = result.pop().ok_or("Invalid return arity")?; let r = r.to_fixed_bytes().ok_or("Invalid type returned")?; util::H256::from_slice(r.as_ref()) }))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user