mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-13 04:41:02 +00:00
Block builder (substrate)
This commit is contained in:
@@ -0,0 +1,89 @@
|
||||
// Copyright 2017 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Substrate.
|
||||
|
||||
// Substrate 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.
|
||||
|
||||
// Substrate 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 Substrate. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! Utility struct to build a block.
|
||||
|
||||
use std::vec::Vec;
|
||||
use codec::{Joiner, Slicable};
|
||||
use state_machine::{self, CodeExecutor};
|
||||
use primitives::{Header, Block};
|
||||
use primitives::block::Transaction;
|
||||
use {backend, error, BlockId, BlockStatus, Client};
|
||||
use triehash::ordered_trie_root;
|
||||
|
||||
/// Utility for building new (valid) blocks from a stream of transactions.
|
||||
pub struct BlockBuilder<B, E> where
|
||||
B: backend::Backend,
|
||||
E: CodeExecutor + Clone,
|
||||
error::Error: From<<<B as backend::Backend>::State as state_machine::backend::Backend>::Error>,
|
||||
{
|
||||
header: Header,
|
||||
transactions: Vec<Transaction>,
|
||||
executor: E,
|
||||
state: B::State,
|
||||
changes: state_machine::OverlayedChanges,
|
||||
}
|
||||
|
||||
impl<B, E> BlockBuilder<B, E> where
|
||||
B: backend::Backend,
|
||||
E: CodeExecutor + Clone,
|
||||
error::Error: From<<<B as backend::Backend>::State as state_machine::backend::Backend>::Error>,
|
||||
{
|
||||
/// Create a new instance of builder from the given client.
|
||||
pub fn new(client: &Client<B, E>) -> error::Result<Self> {
|
||||
let best = (client.info().map(|i| i.chain.best_number)?..1)
|
||||
.find(|&n| if let Ok(BlockStatus::InChain) = client.block_status(&BlockId::Number(n))
|
||||
{ true } else { false })
|
||||
.unwrap_or(0);
|
||||
|
||||
Ok(BlockBuilder {
|
||||
header: Header {
|
||||
number: best + 1,
|
||||
parent_hash: client.block_hash(best)?.expect("We already ascertained this is InChain before; qed"),
|
||||
state_root: Default::default(),
|
||||
transaction_root: Default::default(),
|
||||
digest: Default::default(),
|
||||
},
|
||||
transactions: Default::default(),
|
||||
executor: client.clone_executor(),
|
||||
state: client.state_at(&BlockId::Number(best))?,
|
||||
changes: Default::default(),
|
||||
})
|
||||
}
|
||||
|
||||
/// Push a transaction onto the block's list of transactions. This will ensure the transaction
|
||||
/// can be validly executed (by executing it); if it is invalid, it'll be returned along with
|
||||
/// the error. Otherwise, it will return a mutable reference to self (in order to chain).
|
||||
pub fn push(&mut self, tx: Transaction) -> error::Result<()> {
|
||||
let output = state_machine::execute(&self.state, &mut self.changes, &self.executor, "execute_transaction",
|
||||
&vec![].and(&self.header).and(&tx))?;
|
||||
self.header = Header::decode(&mut &output[..]).expect("Header came straight out of runtime do must be valid");
|
||||
self.transactions.push(tx);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Consume the builder to return a valid `Block` containing all pushed transactions.
|
||||
pub fn bake(mut self) -> error::Result<Block> {
|
||||
self.header.transaction_root = ordered_trie_root(self.transactions.iter().map(Slicable::encode)).0.into();
|
||||
let output = state_machine::execute(&self.state, &mut self.changes, &self.executor, "finalise_block",
|
||||
&self.header.encode())?;
|
||||
self.header = Header::decode(&mut &output[..]).expect("Header came straight out of runtime do must be valid");
|
||||
Ok(Block {
|
||||
header: self.header,
|
||||
transactions: self.transactions,
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -39,9 +39,11 @@ pub mod blockchain;
|
||||
pub mod backend;
|
||||
pub mod in_mem;
|
||||
pub mod genesis;
|
||||
pub mod block_builder;
|
||||
|
||||
pub use blockchain::Info as ChainInfo;
|
||||
pub use blockchain::BlockId;
|
||||
pub use block_builder::BlockBuilder;
|
||||
|
||||
use primitives::{block, AuthorityId};
|
||||
use primitives::storage::{StorageKey, StorageData};
|
||||
@@ -59,6 +61,7 @@ pub struct Client<B, E> where B: backend::Backend {
|
||||
}
|
||||
|
||||
/// Client info
|
||||
// TODO: split queue info from chain info and amalgamate into single struct.
|
||||
#[derive(Debug)]
|
||||
pub struct ClientInfo {
|
||||
/// Best block hash.
|
||||
@@ -167,6 +170,11 @@ impl<B, E> Client<B, E> where
|
||||
self.storage(id, &StorageKey(b":code".to_vec())).map(|data| data.0)
|
||||
}
|
||||
|
||||
/// Clone a new instance of Executor.
|
||||
pub fn clone_executor(&self) -> E where E: Clone {
|
||||
self.executor.clone()
|
||||
}
|
||||
|
||||
/// Get the current set of authorities from storage.
|
||||
pub fn authorities_at(&self, id: &BlockId) -> error::Result<Vec<AuthorityId>> {
|
||||
let state = self.state_at(id)?;
|
||||
@@ -183,10 +191,8 @@ impl<B, E> Client<B, E> where
|
||||
/// No changes are made.
|
||||
pub fn call(&self, id: &BlockId, method: &str, call_data: &[u8]) -> error::Result<CallResult> {
|
||||
let mut changes = state_machine::OverlayedChanges::default();
|
||||
let state = self.state_at(id)?;
|
||||
|
||||
let return_data = state_machine::execute(
|
||||
&state,
|
||||
&self.state_at(id)?,
|
||||
&mut changes,
|
||||
&self.executor,
|
||||
method,
|
||||
@@ -195,6 +201,11 @@ impl<B, E> Client<B, E> where
|
||||
Ok(CallResult { return_data, changes })
|
||||
}
|
||||
|
||||
/// Create a new block, built on the head of the chain.
|
||||
pub fn new_block(&self) -> error::Result<BlockBuilder<B, E>> where E: Clone {
|
||||
BlockBuilder::new(self)
|
||||
}
|
||||
|
||||
/// Queue a block for import.
|
||||
pub fn import_block(&self, header: block::Header, body: Option<block::Body>) -> error::Result<ImportResult> {
|
||||
// TODO: import lock
|
||||
|
||||
@@ -17,19 +17,18 @@
|
||||
//! Block and header type definitions.
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
use bytes;
|
||||
use rstd::vec::Vec;
|
||||
use {bytes, Hash};
|
||||
use codec::{Input, Slicable};
|
||||
use hash::H256;
|
||||
|
||||
/// Used to refer to a block number.
|
||||
pub type Number = u64;
|
||||
|
||||
/// Hash used to refer to a block hash.
|
||||
pub type HeaderHash = H256;
|
||||
pub type HeaderHash = Hash;
|
||||
|
||||
/// Hash used to refer to a transaction hash.
|
||||
pub type TransactionHash = H256;
|
||||
pub type TransactionHash = Hash;
|
||||
|
||||
/// Simple generic transaction type.
|
||||
#[derive(PartialEq, Eq, Clone)]
|
||||
@@ -127,9 +126,9 @@ pub struct Header {
|
||||
/// Block number.
|
||||
pub number: Number,
|
||||
/// State root after this transition.
|
||||
pub state_root: H256,
|
||||
pub state_root: Hash,
|
||||
/// The root of the trie that represents this block's transactions, indexed by a 32-byte integer.
|
||||
pub transaction_root: H256,
|
||||
pub transaction_root: Hash,
|
||||
/// The digest of activity on the block.
|
||||
pub digest: Digest,
|
||||
}
|
||||
|
||||
@@ -90,8 +90,10 @@ mod tests;
|
||||
|
||||
pub use self::hash::{H160, H256};
|
||||
pub use self::uint::{U256, U512};
|
||||
|
||||
pub use block::{Block, Header};
|
||||
|
||||
/// General hash type.
|
||||
pub type Hash = H256;
|
||||
|
||||
/// An identifier for an authority in the consensus algorithm. The same as ed25519::Public.
|
||||
pub type AuthorityId = [u8; 32];
|
||||
|
||||
Reference in New Issue
Block a user