2017-01-22 16:15:22 +01:00
// Copyright 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/>.
2017-03-08 14:41:24 +01:00
use types ::ids ::BlockId ;
2017-01-22 16:15:22 +01:00
use client ::MiningBlockChainClient ;
use transaction ::SignedTransaction ;
use util ::{ U256 , Uint , Mutex } ;
const SERVICE_TRANSACTION_CONTRACT_REGISTRY_NAME : & 'static str = " service_transaction_checker " ;
/// Service transactions checker.
#[ derive(Default) ]
pub struct ServiceTransactionChecker {
contract : Mutex < Option < provider ::Contract > > ,
}
impl ServiceTransactionChecker {
/// Try to create instance, reading contract address from given chain client.
pub fn update_from_chain_client ( & self , client : & MiningBlockChainClient ) {
let mut contract = self . contract . lock ( ) ;
if contract . is_none ( ) {
* contract = client . registry_address ( SERVICE_TRANSACTION_CONTRACT_REGISTRY_NAME . to_owned ( ) )
. and_then ( | contract_addr | {
trace! ( target : " txqueue " , " Configuring for service transaction checker contract from {} " , contract_addr ) ;
Some ( provider ::Contract ::new ( contract_addr ) )
} )
}
}
/// Checks if service transaction can be appended to the transaction queue.
pub fn check ( & self , client : & MiningBlockChainClient , tx : & SignedTransaction ) -> Result < bool , String > {
debug_assert_eq! ( tx . gas_price , U256 ::zero ( ) ) ;
if let Some ( ref contract ) = * self . contract . lock ( ) {
2017-03-08 14:41:24 +01:00
let do_call = | a , d | client . call_contract ( BlockId ::Latest , a , d ) ;
2017-01-22 16:15:22 +01:00
contract . certified ( & do_call , & tx . sender ( ) )
} 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 } ;
2017-03-11 19:58:15 +01:00
use util ::{ Uint } ;
2017-01-22 16:15:22 +01:00
pub struct Contract {
contract : ethabi ::Contract ,
address : util ::Address ,
2017-03-11 19:58:15 +01:00
2017-01-22 16:15:22 +01:00
}
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 ,
2017-03-11 19:58:15 +01:00
2017-01-22 16:15:22 +01:00
}
}
fn as_string < T : fmt ::Debug > ( e : T ) -> String { format! ( " {:?} " , e ) }
2017-03-11 19:58:15 +01:00
2017-01-22 16:15:22 +01:00
/// 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 ) ? ;
2017-03-11 19:58:15 +01:00
2017-01-22 16:15:22 +01:00
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 ) ? ;
2017-03-11 19:58:15 +01:00
2017-01-22 16:15:22 +01:00
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 ) ? ;
2017-03-11 19:58:15 +01:00
2017-01-22 16:15:22 +01:00
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 ) ? ;
2017-03-11 19:58:15 +01:00
2017-01-22 16:15:22 +01:00
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 ( ) ) } ) )
}
}
}