openethereum/ethcore/engines/authority-round/src/util.rs
Andreas Fackler 2b1d148ceb Add randomness contract support to AuthorityRound. (#10946)
* Add randomness contract support to Authority Round.

Changes have been cherry-picked from poanetwork's aura-pos branch.
Most of the work has been done by @mbr.

* Address review comments for randomness contract.

Co-Authored-By: David <dvdplm@gmail.com>

* Rename revealSecret to revealNumber

* Update Randomness contract bytecode

* Use H256, rename secret to random number.

* Use get_commit_and_cipher

* Clean up Miner::prepare_block.

* Remove is_reveal_phase call.

* Add more comments, require randomness contract map.

* Simplify run_randomness_phase

* Address review comments.

* Remove Client::transact_contract.
2019-12-17 11:34:14 +01:00

95 lines
3.1 KiB
Rust

// Copyright 2015-2019 Parity Technologies (UK) Ltd.
// This file is part of Parity Ethereum.
// Parity Ethereum 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 Ethereum 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 Ethereum. If not, see <http://www.gnu.org/licenses/>.
//! Utility functions.
//!
//! Contains small functions used by the AuRa engine that are not strictly limited to that scope.
use std::fmt;
use client_traits::EngineClient;
use common_types::ids::BlockId;
use ethabi;
use ethereum_types::Address;
/// A contract bound to a client and block number.
///
/// A bound contract is a combination of a `Client` reference, a `BlockId` and a contract `Address`.
/// These three parts are enough to call a contract's function; return values are automatically
/// decoded.
pub struct BoundContract<'a> {
client: &'a dyn EngineClient,
block_id: BlockId,
contract_addr: Address,
}
/// Contract call failed error.
#[derive(Debug)]
pub enum CallError {
/// The call itself failed.
CallFailed(String),
/// Decoding the return value failed or the decoded value was a failure.
DecodeFailed(ethabi::Error),
/// The passed in client reference could not be upgraded to a `BlockchainClient`.
NotFullClient,
}
impl<'a> fmt::Debug for BoundContract<'a> {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
fmt.debug_struct("BoundContract")
.field("client", &(self.client as *const dyn EngineClient))
.field("block_id", &self.block_id)
.field("contract_addr", &self.contract_addr)
.finish()
}
}
impl<'a> BoundContract<'a> {
/// Create a new `BoundContract`.
pub fn new(client: &dyn EngineClient, block_id: BlockId, contract_addr: Address) -> BoundContract {
BoundContract {
client,
block_id,
contract_addr,
}
}
/// Perform a function call to an Ethereum machine that doesn't create a transaction or change the state.
///
/// Runs a constant function call on `client`. The `call` value can be serialized by calling any
/// api function generated by the `use_contract!` macro. This does not create any transactions, it only produces a
/// result based on the state at the current block: It is constant in the sense that it does not alter the EVM
/// state.
pub fn call_const<D>(&self, call: (ethabi::Bytes, D)) -> Result<D::Output, CallError>
where
D: ethabi::FunctionOutputDecoder,
{
let (data, output_decoder) = call;
let call_return = self
.client
.as_full_client()
.ok_or(CallError::NotFullClient)?
.call_contract(self.block_id, self.contract_addr, data)
.map_err(CallError::CallFailed)?;
// Decode the result and return it.
output_decoder
.decode(call_return.as_slice())
.map_err(CallError::DecodeFailed)
}
}