Big folder refactor

This commit is contained in:
Adria Massanet
2021-01-13 17:03:12 +00:00
committed by rakita
parent 0e5d6944b7
commit c46fe330dc
846 changed files with 255 additions and 39400 deletions

View File

@@ -0,0 +1,54 @@
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
// This file is part of OpenEthereum.
// OpenEthereum 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.
// OpenEthereum 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 OpenEthereum. If not, see <http://www.gnu.org/licenses/>.
//! Blockchain test account deserializer.
use bytes::Bytes;
use std::collections::BTreeMap;
use uint::Uint;
/// Blockchain test account deserializer.
#[derive(Debug, PartialEq, Deserialize, Clone)]
pub struct Account {
/// Balance.
pub balance: Uint,
/// Code.
pub code: Bytes,
/// Nonce.
pub nonce: Uint,
/// Storage.
pub storage: BTreeMap<Uint, Uint>,
}
#[cfg(test)]
mod tests {
use blockchain::account::Account;
use serde_json;
#[test]
fn account_deserialization() {
let s = r#"{
"balance" : "0x09184e72a078",
"code" : "0x600140600155",
"nonce" : "0x00",
"storage" : {
"0x01" : "0x9a10c2b5bb8f3c602e674006d9b21f09167df57c87a78a5ce96d4159ecb76520"
}
}"#;
let _deserialized: Account = serde_json::from_str(s).unwrap();
// TODO: validate all fields
}
}

View File

@@ -0,0 +1,74 @@
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
// This file is part of OpenEthereum.
// OpenEthereum 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.
// OpenEthereum 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 OpenEthereum. If not, see <http://www.gnu.org/licenses/>.
//! Blockchain test block deserializer.
use blockchain::{header::Header, transaction::Transaction};
use bytes::Bytes;
/// Blockchain test block deserializer.
#[derive(Debug, PartialEq, Deserialize)]
pub struct Block {
#[serde(rename = "blockHeader")]
header: Option<Header>,
rlp: Bytes,
transactions: Option<Vec<Transaction>>,
#[serde(rename = "uncleHeaders")]
uncles: Option<Vec<Header>>,
}
impl Block {
/// Returns block rlp.
pub fn rlp(&self) -> Vec<u8> {
self.rlp.clone().into()
}
}
#[cfg(test)]
mod tests {
use blockchain::block::Block;
use serde_json;
#[test]
fn block_deserialization() {
let s = r#"{
"blockHeader" : {
"bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"coinbase" : "8888f1f195afa192cfee860698584c030f4c9db1",
"difficulty" : "0x020000",
"extraData" : "0x",
"gasLimit" : "0x2fefba",
"gasUsed" : "0x00",
"hash" : "65ebf1b97fb89b14680267e0723d69267ec4bf9a96d4a60ffcb356ae0e81c18f",
"mixHash" : "13735ab4156c9b36327224d92e1692fab8fc362f8e0f868c94d421848ef7cd06",
"nonce" : "931dcc53e5edc514",
"number" : "0x01",
"parentHash" : "5a39ed1020c04d4d84539975b893a4e7c53eab6c2965db8bc3468093a31bc5ae",
"receiptTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
"stateRoot" : "c5c83ff43741f573a0c9b31d0e56fdd745f4e37d193c4e78544f302777aafcf3",
"timestamp" : "0x56850b7b",
"transactionsTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
"uncleHash" : "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"
},
"blocknumber" : "1",
"rlp" : "0xf901fcf901f7a05a39ed1020c04d4d84539975b893a4e7c53eab6c2965db8bc3468093a31bc5aea01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a0c5c83ff43741f573a0c9b31d0e56fdd745f4e37d193c4e78544f302777aafcf3a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302000001832fefba808456850b7b80a013735ab4156c9b36327224d92e1692fab8fc362f8e0f868c94d421848ef7cd0688931dcc53e5edc514c0c0",
"transactions" : [],
"uncleHeaders" : []
}"#;
let _deserialized: Block = serde_json::from_str(s).unwrap();
// TODO: validate all fields
}
}

View File

@@ -0,0 +1,202 @@
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
// This file is part of OpenEthereum.
// OpenEthereum 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.
// OpenEthereum 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 OpenEthereum. If not, see <http://www.gnu.org/licenses/>.
//! Blockchain deserialization.
use blockchain::{block::Block, header::Header, state::State};
use bytes::Bytes;
use hash::H256;
use spec::{Ethereum, ForkSpec, Genesis, Seal};
/// Json Block test possible engine kind.
#[derive(Debug, PartialEq, Deserialize)]
pub enum Engine {
/// Default (old) behaviour.
Ethash,
/// No check of block's difficulty and nonce for tests.
NoProof,
}
impl Default for Engine {
fn default() -> Self {
Engine::Ethash
}
}
/// Blockchain deserialization.
#[derive(Debug, PartialEq, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct BlockChain {
/// Genesis block header.
#[serde(rename = "genesisBlockHeader")]
pub genesis_block: Header,
/// Genesis block rlp.
#[serde(rename = "genesisRLP")]
pub genesis_rlp: Option<Bytes>,
/// Blocks.
pub blocks: Vec<Block>,
/// Post state.
pub post_state: Option<State>,
/// Pre state.
#[serde(rename = "pre")]
pub pre_state: State,
/// Hash of best block.
#[serde(rename = "lastblockhash")]
pub best_block: H256,
/// Network.
pub network: ForkSpec,
#[serde(default)]
#[serde(rename = "sealEngine")]
/// Engine
pub engine: Engine,
}
impl BlockChain {
/// Returns blocks rlp.
pub fn blocks_rlp(&self) -> Vec<Vec<u8>> {
self.blocks.iter().map(|block| block.rlp()).collect()
}
/// Returns spec compatible genesis struct.
pub fn genesis(&self) -> Genesis {
Genesis {
seal: Seal::Ethereum(Ethereum {
nonce: self.genesis_block.nonce.clone(),
mix_hash: self.genesis_block.mix_hash.clone(),
}),
difficulty: self.genesis_block.difficulty,
author: Some(self.genesis_block.author.clone()),
timestamp: Some(self.genesis_block.timestamp),
parent_hash: Some(self.genesis_block.parent_hash.clone()),
gas_limit: self.genesis_block.gas_limit,
transactions_root: Some(self.genesis_block.transactions_root.clone()),
receipts_root: Some(self.genesis_block.receipts_root.clone()),
state_root: Some(self.genesis_block.state_root.clone()),
gas_used: Some(self.genesis_block.gas_used),
extra_data: Some(self.genesis_block.extra_data.clone()),
}
}
}
#[cfg(test)]
mod tests {
use blockchain::blockchain::BlockChain;
use serde_json;
#[test]
fn blockchain_deserialization() {
let s = r#"{
"blocks" : [{
"blockHeader" : {
"bloom" : "00000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000040000000000000000000000000000000000000000000000000000000",
"coinbase" : "8888f1f195afa192cfee860698584c030f4c9db1",
"difficulty" : "0x020000",
"extraData" : "0x0102030405060708091011121314151617181920212223242526272829303132",
"gasLimit" : "0x2fefba",
"gasUsed" : "0x560b",
"hash" : "06b5b1742bde29468510c92641f36b719c61b3fc3e9a21c92a23978f4f7faa2a",
"mixHash" : "5266ca43e81d25925a9ba573c3e4f9180bc076d316d90e63c6f8708b272f5ce2",
"nonce" : "59ba4daed1898e21",
"number" : "0x01",
"parentHash" : "f052d217bd5275a5177a3c3b7debdfe2670f1c8394b2965ccd5c1883cc1a524d",
"receiptTrie" : "c7778a7376099ee2e5c455791c1885b5c361b95713fddcbe32d97fd01334d296",
"stateRoot" : "bac6177a79e910c98d86ec31a09ae37ac2de15b754fd7bed1ba52362c49416bf",
"timestamp" : "0x56850c2c",
"transactionsTrie" : "498785da562aa0c5dd5937cf15f22139b0b1bcf3b4fc48986e1bb1dae9292796",
"uncleHash" : "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"
},
"rlp" : "0xf90285f90219a0f052d217bd5275a5177a3c3b7debdfe2670f1c8394b2965ccd5c1883cc1a524da01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a0bac6177a79e910c98d86ec31a09ae37ac2de15b754fd7bed1ba52362c49416bfa0498785da562aa0c5dd5937cf15f22139b0b1bcf3b4fc48986e1bb1dae9292796a0c7778a7376099ee2e5c455791c1885b5c361b95713fddcbe32d97fd01334d296b90100000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000400000000000000000000000000000000000000000000000000000008302000001832fefba82560b8456850c2ca00102030405060708091011121314151617181920212223242526272829303132a05266ca43e81d25925a9ba573c3e4f9180bc076d316d90e63c6f8708b272f5ce28859ba4daed1898e21f866f864800a82c35094095e7baea6a6c7c4c2dfeb977efac326af552d8785012a05f200801ca0ee0b9ec878fbd4258a9473199d8ecc32996a20c323c004e79e0cda20e0418ce3a04e6bc63927d1510bab54f37e46fa036faf4b2c465d271920d9afea1fadf7bd21c0",
"transactions" : [
{
"data" : "0x00",
"gasLimit" : "0xc350",
"gasPrice" : "0x0a",
"nonce" : "0x00",
"r" : "0xee0b9ec878fbd4258a9473199d8ecc32996a20c323c004e79e0cda20e0418ce3",
"s" : "0x4e6bc63927d1510bab54f37e46fa036faf4b2c465d271920d9afea1fadf7bd21",
"to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87",
"v" : "0x1c",
"value" : "0x012a05f200"
}
],
"uncleHeaders" : [
]
}],
"network" : "Frontier",
"genesisBlockHeader" : {
"bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"coinbase" : "8888f1f195afa192cfee860698584c030f4c9db1",
"difficulty" : "0x020000",
"extraData" : "0x42",
"gasLimit" : "0x2fefd8",
"gasUsed" : "0x00",
"hash" : "f052d217bd5275a5177a3c3b7debdfe2670f1c8394b2965ccd5c1883cc1a524d",
"mixHash" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
"nonce" : "0102030405060708",
"number" : "0x00",
"parentHash" : "0000000000000000000000000000000000000000000000000000000000000000",
"receiptTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
"stateRoot" : "925002c3260b44e44c3edebad1cc442142b03020209df1ab8bb86752edbd2cd7",
"timestamp" : "0x54c98c81",
"transactionsTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
"uncleHash" : "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"
},
"genesisRLP" : "0xf901fcf901f7a00000000000000000000000000000000000000000000000000000000000000000a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a0925002c3260b44e44c3edebad1cc442142b03020209df1ab8bb86752edbd2cd7a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302000080832fefd8808454c98c8142a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421880102030405060708c0c0",
"lastblockhash" : "06b5b1742bde29468510c92641f36b719c61b3fc3e9a21c92a23978f4f7faa2a",
"postState" : {
"095e7baea6a6c7c4c2dfeb977efac326af552d87" : {
"balance" : "0x012a05f264",
"code" : "0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600052600060206000a1",
"nonce" : "0x00",
"storage" : {
}
},
"8888f1f195afa192cfee860698584c030f4c9db1" : {
"balance" : "0x4563918244f75c6e",
"code" : "0x",
"nonce" : "0x00",
"storage" : {
}
},
"a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
"balance" : "0x012a029592",
"code" : "0x",
"nonce" : "0x01",
"storage" : {
}
}
},
"pre" : {
"095e7baea6a6c7c4c2dfeb977efac326af552d87" : {
"balance" : "0x64",
"code" : "0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600052600060206000a1",
"nonce" : "0x00",
"storage" : {
}
},
"a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
"balance" : "0x02540be400",
"code" : "0x",
"nonce" : "0x00",
"storage" : {
}
}
}
}"#;
let _deserialized: BlockChain = serde_json::from_str(s).unwrap();
// TODO: validate all fields
}
}

View File

@@ -0,0 +1,93 @@
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
// This file is part of OpenEthereum.
// OpenEthereum 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.
// OpenEthereum 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 OpenEthereum. If not, see <http://www.gnu.org/licenses/>.
//! Blockchain test header deserializer.
use bytes::Bytes;
use hash::{Address, Bloom, H256, H64};
use uint::Uint;
/// Blockchain test header deserializer.
#[derive(Debug, PartialEq, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Header {
/// Blocks bloom.
pub bloom: Bloom,
/// Blocks author.
#[serde(rename = "coinbase")]
pub author: Address,
/// Difficulty.
pub difficulty: Uint,
/// Extra data.
pub extra_data: Bytes,
/// Gas limit.
pub gas_limit: Uint,
/// Gas used.
pub gas_used: Uint,
/// Hash.
pub hash: H256,
/// Mix hash.
pub mix_hash: H256,
/// Seal nonce.
pub nonce: H64,
/// Block number.
pub number: Uint,
/// Parent hash.
pub parent_hash: H256,
/// Receipt root.
#[serde(rename = "receiptTrie")]
pub receipts_root: H256,
/// State root.
pub state_root: H256,
/// Timestamp.
pub timestamp: Uint,
/// Transactions root.
#[serde(rename = "transactionsTrie")]
pub transactions_root: H256,
/// Uncles hash.
#[serde(rename = "uncleHash")]
pub uncles_hash: H256,
}
#[cfg(test)]
mod tests {
use blockchain::header::Header;
use serde_json;
#[test]
fn header_deserialization() {
let s = r#"{
"bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"coinbase" : "8888f1f195afa192cfee860698584c030f4c9db1",
"difficulty" : "0x020000",
"extraData" : "0x",
"gasLimit" : "0x2fefba",
"gasUsed" : "0x00",
"hash" : "65ebf1b97fb89b14680267e0723d69267ec4bf9a96d4a60ffcb356ae0e81c18f",
"mixHash" : "13735ab4156c9b36327224d92e1692fab8fc362f8e0f868c94d421848ef7cd06",
"nonce" : "931dcc53e5edc514",
"number" : "0x01",
"parentHash" : "5a39ed1020c04d4d84539975b893a4e7c53eab6c2965db8bc3468093a31bc5ae",
"receiptTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
"stateRoot" : "c5c83ff43741f573a0c9b31d0e56fdd745f4e37d193c4e78544f302777aafcf3",
"timestamp" : "0x56850b7b",
"transactionsTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
"uncleHash" : "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"
}"#;
let _deserialized: Header = serde_json::from_str(s).unwrap();
// TODO: validate all fields
}
}

View File

@@ -0,0 +1,35 @@
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
// This file is part of OpenEthereum.
// OpenEthereum 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.
// OpenEthereum 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 OpenEthereum. If not, see <http://www.gnu.org/licenses/>.
//! Blockchain test deserialization.
pub mod account;
pub mod block;
pub mod blockchain;
pub mod header;
pub mod state;
pub mod test;
pub mod transaction;
pub use self::{
account::Account,
block::Block,
blockchain::{BlockChain, Engine},
header::Header,
state::State,
test::Test,
transaction::Transaction,
};

View File

@@ -0,0 +1,76 @@
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
// This file is part of OpenEthereum.
// OpenEthereum 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.
// OpenEthereum 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 OpenEthereum. If not, see <http://www.gnu.org/licenses/>.
//! Blockchain test state deserializer.
use crate::{
bytes::Bytes,
hash::{Address, H256},
spec::{Account, Builtin},
};
use std::collections::BTreeMap;
#[derive(Clone, Debug, PartialEq, Deserialize)]
#[serde(untagged)]
pub enum HashOrMap {
/// When the `postState` is large, tests sometimes just include the state root of the last
/// successful block here.
Hash(H256),
/// The expected `postState` of a test
Map(BTreeMap<Address, Account>),
}
/// Blockchain state deserializer.
#[derive(Clone, Debug, PartialEq, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct State(pub HashOrMap);
impl State {
/// Returns all builtins.
pub fn builtins(&self) -> BTreeMap<Address, Builtin> {
match &self.0 {
HashOrMap::Hash(_) => BTreeMap::default(),
HashOrMap::Map(map) => map
.iter()
.filter_map(|(add, ref acc)| acc.builtin.clone().map(|b| (add.clone(), b.into())))
.collect(),
}
}
/// Returns all constructors.
pub fn constructors(&self) -> BTreeMap<Address, Bytes> {
match &self.0 {
HashOrMap::Hash(_) => BTreeMap::default(),
HashOrMap::Map(map) => map
.iter()
.filter_map(|(add, ref acc)| acc.constructor.clone().map(|b| (add.clone(), b)))
.collect(),
}
}
}
impl IntoIterator for State {
type Item = <BTreeMap<Address, Account> as IntoIterator>::Item;
type IntoIter = <BTreeMap<Address, Account> as IntoIterator>::IntoIter;
fn into_iter(self) -> Self::IntoIter {
if let HashOrMap::Map(m) = self.0 {
m.into_iter()
} else {
BTreeMap::default().into_iter()
}
}
}

View File

@@ -0,0 +1,44 @@
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
// This file is part of OpenEthereum.
// OpenEthereum 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.
// OpenEthereum 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 OpenEthereum. If not, see <http://www.gnu.org/licenses/>.
//! Blockchain test deserializer.
use blockchain::blockchain::BlockChain;
use serde_json::{self, Error};
use std::{collections::BTreeMap, io::Read};
/// Blockchain test deserializer.
#[derive(Debug, PartialEq, Deserialize)]
pub struct Test(BTreeMap<String, BlockChain>);
impl IntoIterator for Test {
type Item = <BTreeMap<String, BlockChain> as IntoIterator>::Item;
type IntoIter = <BTreeMap<String, BlockChain> as IntoIterator>::IntoIter;
fn into_iter(self) -> Self::IntoIter {
self.0.into_iter()
}
}
impl Test {
/// Loads test from json.
pub fn load<R>(reader: R) -> Result<Self, Error>
where
R: Read,
{
serde_json::from_reader(reader)
}
}

View File

@@ -0,0 +1,34 @@
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
// This file is part of OpenEthereum.
// OpenEthereum 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.
// OpenEthereum 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 OpenEthereum. If not, see <http://www.gnu.org/licenses/>.
//! Blockchain test transaction deserialization.
use bytes::Bytes;
use uint::Uint;
/// Blockchain test transaction deserialization.
#[derive(Debug, PartialEq, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Transaction {
data: Bytes,
gas_limit: Uint,
gas_price: Uint,
nonce: Uint,
r: Uint,
s: Uint,
v: Uint,
value: Uint,
}

130
crates/ethjson/src/bytes.rs Normal file
View File

@@ -0,0 +1,130 @@
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
// This file is part of OpenEthereum.
// OpenEthereum 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.
// OpenEthereum 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 OpenEthereum. If not, see <http://www.gnu.org/licenses/>.
//! Lenient bytes json deserialization for test json files.
use rustc_hex::FromHex;
use serde::{
de::{Error, Visitor},
Deserialize, Deserializer,
};
use std::{fmt, ops::Deref, str::FromStr};
/// Lenient bytes json deserialization for test json files.
#[derive(Default, Debug, PartialEq, Eq, Clone, PartialOrd, Ord)]
pub struct Bytes(Vec<u8>);
impl Bytes {
/// Creates bytes struct.
pub fn new(v: Vec<u8>) -> Self {
Bytes(v)
}
}
impl Into<Vec<u8>> for Bytes {
fn into(self) -> Vec<u8> {
self.0
}
}
impl Deref for Bytes {
type Target = [u8];
fn deref(&self) -> &[u8] {
&self.0
}
}
impl FromStr for Bytes {
type Err = String;
fn from_str(value: &str) -> Result<Self, Self::Err> {
let v = match value.len() {
0 => vec![],
2 if value.starts_with("0x") => vec![],
_ if value.starts_with("0x") && value.len() % 2 == 1 => {
let v = "0".to_owned() + &value[2..];
FromHex::from_hex(v.as_str()).unwrap_or(vec![])
}
_ if value.starts_with("0x") => FromHex::from_hex(&value[2..]).unwrap_or(vec![]),
_ => FromHex::from_hex(value).unwrap_or(vec![]),
};
Ok(Bytes(v))
}
}
impl<'a> Deserialize<'a> for Bytes {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'a>,
{
deserializer.deserialize_any(BytesVisitor)
}
}
struct BytesVisitor;
impl<'a> Visitor<'a> for BytesVisitor {
type Value = Bytes;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
write!(formatter, "a hex encoded string of bytes")
}
fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
where
E: Error,
{
Bytes::from_str(value).map_err(Error::custom)
}
fn visit_string<E>(self, value: String) -> Result<Self::Value, E>
where
E: Error,
{
self.visit_str(value.as_ref())
}
}
#[cfg(test)]
mod test {
use bytes::Bytes;
use serde_json;
#[test]
fn bytes_deserialization() {
let s = r#"["", "0x", "0x12", "1234", "0x001"]"#;
let deserialized: Vec<Bytes> = serde_json::from_str(s).unwrap();
assert_eq!(
deserialized,
vec![
Bytes(vec![]),
Bytes(vec![]),
Bytes(vec![0x12]),
Bytes(vec![0x12, 0x34]),
Bytes(vec![0, 1])
]
);
}
#[test]
fn bytes_into() {
let bytes = Bytes(vec![0xff, 0x11]);
let v: Vec<u8> = bytes.into();
assert_eq!(vec![0xff, 0x11], v);
}
}

148
crates/ethjson/src/hash.rs Normal file
View File

@@ -0,0 +1,148 @@
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
// This file is part of OpenEthereum.
// OpenEthereum 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.
// OpenEthereum 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 OpenEthereum. If not, see <http://www.gnu.org/licenses/>.
//! Lenient hash json deserialization for test json files.
use ethereum_types::{
Bloom as Hash2048, H160 as Hash160, H256 as Hash256, H520 as Hash520, H64 as Hash64,
};
use rustc_hex::ToHex;
use serde::{
de::{Error, Visitor},
Deserialize, Deserializer, Serialize, Serializer,
};
use std::{fmt, str::FromStr};
macro_rules! impl_hash {
($name: ident, $inner: ident) => {
/// Lenient hash json deserialization for test json files.
#[derive(Default, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, Clone)]
pub struct $name(pub $inner);
impl From<$name> for $inner {
fn from(other: $name) -> $inner {
other.0
}
}
impl From<$inner> for $name {
fn from(i: $inner) -> Self {
$name(i)
}
}
impl<'a> Deserialize<'a> for $name {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'a>,
{
struct HashVisitor;
impl<'b> Visitor<'b> for HashVisitor {
type Value = $name;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
write!(formatter, "a 0x-prefixed hex-encoded hash")
}
fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
where
E: Error,
{
let value = match value.len() {
0 => $inner::from(0),
2 if value == "0x" => $inner::from(0),
_ if value.starts_with("0x") => {
$inner::from_str(&value[2..]).map_err(|e| {
Error::custom(
format!("Invalid hex value {}: {}", value, e).as_str(),
)
})?
}
_ => $inner::from_str(value).map_err(|e| {
Error::custom(
format!("Invalid hex value {}: {}", value, e).as_str(),
)
})?,
};
Ok($name(value))
}
fn visit_string<E>(self, value: String) -> Result<Self::Value, E>
where
E: Error,
{
self.visit_str(value.as_ref())
}
}
deserializer.deserialize_any(HashVisitor)
}
}
impl Serialize for $name {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let mut hex = "0x".to_owned();
hex.push_str(&self.0.to_hex());
serializer.serialize_str(&hex)
}
}
};
}
impl_hash!(H64, Hash64);
impl_hash!(Address, Hash160);
impl_hash!(H256, Hash256);
impl_hash!(H520, Hash520);
impl_hash!(Bloom, Hash2048);
#[cfg(test)]
mod test {
use ethereum_types;
use hash::H256;
use serde_json;
use std::str::FromStr;
#[test]
fn hash_deserialization() {
let s = r#"["", "5a39ed1020c04d4d84539975b893a4e7c53eab6c2965db8bc3468093a31bc5ae"]"#;
let deserialized: Vec<H256> = serde_json::from_str(s).unwrap();
assert_eq!(
deserialized,
vec![
H256(ethereum_types::H256::from(0)),
H256(
ethereum_types::H256::from_str(
"5a39ed1020c04d4d84539975b893a4e7c53eab6c2965db8bc3468093a31bc5ae"
)
.unwrap()
)
]
);
}
#[test]
fn hash_into() {
assert_eq!(
ethereum_types::H256::from(0),
H256(ethereum_types::H256::from(0)).into()
);
}
}

41
crates/ethjson/src/lib.rs Normal file
View File

@@ -0,0 +1,41 @@
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
// This file is part of OpenEthereum.
// OpenEthereum 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.
// OpenEthereum 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 OpenEthereum. If not, see <http://www.gnu.org/licenses/>.
extern crate ethereum_types;
extern crate rustc_hex;
extern crate serde;
extern crate serde_json;
#[macro_use]
extern crate serde_derive;
#[cfg(test)]
extern crate macros;
#[cfg(test)]
#[macro_use]
extern crate maplit;
pub mod blockchain;
pub mod bytes;
pub mod hash;
pub mod maybe;
pub mod spec;
pub mod state;
pub mod test;
pub mod transaction;
pub mod trie;
pub mod uint;
pub mod vm;

120
crates/ethjson/src/maybe.rs Normal file
View File

@@ -0,0 +1,120 @@
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
// This file is part of OpenEthereum.
// OpenEthereum 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.
// OpenEthereum 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 OpenEthereum. If not, see <http://www.gnu.org/licenses/>.
//! Deserializer of empty string values into optionals.
use serde::{
de::{Error, IntoDeserializer, Visitor},
Deserialize, Deserializer,
};
use std::{fmt, marker::PhantomData};
/// Deserializer of empty string values into optionals.
#[derive(Debug, PartialEq, Clone)]
pub enum MaybeEmpty<T> {
/// Some.
Some(T),
/// None.
None,
}
impl<'a, T> Deserialize<'a> for MaybeEmpty<T>
where
T: Deserialize<'a>,
{
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'a>,
{
deserializer.deserialize_any(MaybeEmptyVisitor::new())
}
}
struct MaybeEmptyVisitor<T> {
_phantom: PhantomData<T>,
}
impl<T> MaybeEmptyVisitor<T> {
fn new() -> Self {
MaybeEmptyVisitor {
_phantom: PhantomData,
}
}
}
impl<'a, T> Visitor<'a> for MaybeEmptyVisitor<T>
where
T: Deserialize<'a>,
{
type Value = MaybeEmpty<T>;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
write!(formatter, "an empty string or string-encoded type")
}
fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
where
E: Error,
{
self.visit_string(value.to_owned())
}
fn visit_string<E>(self, value: String) -> Result<Self::Value, E>
where
E: Error,
{
match value.is_empty() {
true => Ok(MaybeEmpty::None),
false => T::deserialize(value.into_deserializer()).map(MaybeEmpty::Some),
}
}
}
impl<T> Into<Option<T>> for MaybeEmpty<T> {
fn into(self) -> Option<T> {
match self {
MaybeEmpty::Some(s) => Some(s),
MaybeEmpty::None => None,
}
}
}
#[cfg(test)]
mod tests {
use ethereum_types;
use hash::H256;
use maybe::MaybeEmpty;
use serde_json;
use std::str::FromStr;
#[test]
fn maybe_deserialization() {
let s = r#"["", "5a39ed1020c04d4d84539975b893a4e7c53eab6c2965db8bc3468093a31bc5ae"]"#;
let deserialized: Vec<MaybeEmpty<H256>> = serde_json::from_str(s).unwrap();
assert_eq!(
deserialized,
vec![
MaybeEmpty::None,
MaybeEmpty::Some(H256(
ethereum_types::H256::from_str(
"5a39ed1020c04d4d84539975b893a4e7c53eab6c2965db8bc3468093a31bc5ae"
)
.unwrap()
))
]
);
}
}

View File

@@ -0,0 +1,168 @@
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
// This file is part of OpenEthereum.
// OpenEthereum 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.
// OpenEthereum 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 OpenEthereum. If not, see <http://www.gnu.org/licenses/>.
//! Spec account deserialization.
use std::collections::BTreeMap;
use bytes::Bytes;
use spec::builtin::BuiltinCompat;
use uint::Uint;
/// Spec account.
#[derive(Clone, Debug, PartialEq, Deserialize)]
#[serde(deny_unknown_fields)]
#[serde(rename_all = "camelCase")]
pub struct Account {
/// Builtin contract.
pub builtin: Option<BuiltinCompat>,
/// Balance.
pub balance: Option<Uint>,
/// Nonce.
pub nonce: Option<Uint>,
/// Code.
pub code: Option<Bytes>,
/// Storage.
pub storage: Option<BTreeMap<Uint, Uint>>,
/// Constructor.
pub constructor: Option<Bytes>,
}
impl Account {
/// Returns true if account does not have nonce, balance, code and storage.
pub fn is_empty(&self) -> bool {
self.balance.is_none()
&& self.nonce.is_none()
&& self.code.is_none()
&& self.storage.is_none()
}
}
#[cfg(test)]
mod tests {
use bytes::Bytes;
use ethereum_types::U256;
use serde_json;
use spec::account::Account;
use std::collections::BTreeMap;
use uint::Uint;
#[test]
fn account_balance_missing_not_empty() {
let s = r#"{
"nonce": "0",
"code": "1234",
"storage": { "0x7fffffffffffffff7fffffffffffffff": "0x1" }
}"#;
let deserialized: Account = serde_json::from_str(s).unwrap();
assert!(!deserialized.is_empty());
}
#[test]
fn account_nonce_missing_not_empty() {
let s = r#"{
"balance": "1",
"code": "1234",
"storage": { "0x7fffffffffffffff7fffffffffffffff": "0x1" }
}"#;
let deserialized: Account = serde_json::from_str(s).unwrap();
assert!(!deserialized.is_empty());
}
#[test]
fn account_code_missing_not_empty() {
let s = r#"{
"balance": "1",
"nonce": "0",
"storage": { "0x7fffffffffffffff7fffffffffffffff": "0x1" }
}"#;
let deserialized: Account = serde_json::from_str(s).unwrap();
assert!(!deserialized.is_empty());
}
#[test]
fn account_storage_missing_not_empty() {
let s = r#"{
"balance": "1",
"nonce": "0",
"code": "1234"
}"#;
let deserialized: Account = serde_json::from_str(s).unwrap();
assert!(!deserialized.is_empty());
}
#[test]
fn account_empty() {
let s = r#"{
"builtin": {
"name": "ecrecover",
"pricing": {
"linear": {
"base": 3000,
"word": 0
}
}
}
}"#;
let deserialized: Account = serde_json::from_str(s).unwrap();
assert!(deserialized.is_empty());
}
#[test]
fn account_deserialization() {
let s = r#"{
"balance": "1",
"nonce": "0",
"code": "1234",
"builtin": {
"name": "ecrecover",
"pricing": {
"linear": {
"base": 3000,
"word": 0
}
}
}
}"#;
let deserialized: Account = serde_json::from_str(s).unwrap();
assert!(!deserialized.is_empty());
assert_eq!(deserialized.balance.unwrap(), Uint(U256::from(1)));
assert_eq!(deserialized.nonce.unwrap(), Uint(U256::from(0)));
assert_eq!(deserialized.code.unwrap(), Bytes::new(vec![0x12, 0x34]));
assert!(deserialized.builtin.is_some()); // Further tested in builtin.rs
}
#[test]
fn account_storage_deserialization() {
let s = r#"{
"balance": "1",
"nonce": "0",
"code": "1234",
"storage": { "0x7fffffffffffffff7fffffffffffffff": "0x1" }
}"#;
let deserialized: Account = serde_json::from_str(s).unwrap();
assert!(!deserialized.is_empty());
assert_eq!(deserialized.balance.unwrap(), Uint(U256::from(1)));
assert_eq!(deserialized.nonce.unwrap(), Uint(U256::from(0)));
assert_eq!(deserialized.code.unwrap(), Bytes::new(vec![0x12, 0x34]));
let mut storage = BTreeMap::new();
storage.insert(
Uint(U256::from("7fffffffffffffff7fffffffffffffff")),
Uint(U256::from(1)),
);
assert_eq!(deserialized.storage.unwrap(), storage);
}
}

View File

@@ -0,0 +1,114 @@
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
// This file is part of OpenEthereum.
// OpenEthereum 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.
// OpenEthereum 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 OpenEthereum. If not, see <http://www.gnu.org/licenses/>.
//! Authority params deserialization.
use super::ValidatorSet;
use bytes::Bytes;
use hash::Address;
use uint::Uint;
/// Authority params deserialization.
#[derive(Debug, PartialEq, Deserialize)]
#[serde(deny_unknown_fields)]
#[serde(rename_all = "camelCase")]
pub struct AuthorityRoundParams {
/// Block duration, in seconds.
pub step_duration: Uint,
/// Valid authorities
pub validators: ValidatorSet,
/// Starting step. Determined automatically if not specified.
/// To be used for testing only.
pub start_step: Option<Uint>,
/// Block at which score validation should start.
pub validate_score_transition: Option<Uint>,
/// Block from which monotonic steps start.
pub validate_step_transition: Option<Uint>,
/// Whether transitions should be immediate.
pub immediate_transitions: Option<bool>,
/// Reward per block in wei.
pub block_reward: Option<Uint>,
/// Block at which the block reward contract should start being used.
pub block_reward_contract_transition: Option<Uint>,
/// Block reward contract address (setting the block reward contract
/// overrides the static block reward definition).
pub block_reward_contract_address: Option<Address>,
/// Block reward code. This overrides the block reward contract address.
pub block_reward_contract_code: Option<Bytes>,
/// Block at which maximum uncle count should be considered.
pub maximum_uncle_count_transition: Option<Uint>,
/// Maximum number of accepted uncles.
pub maximum_uncle_count: Option<Uint>,
/// Block at which empty step messages should start.
pub empty_steps_transition: Option<Uint>,
/// Maximum number of accepted empty steps.
pub maximum_empty_steps: Option<Uint>,
/// Strict validation of empty steps transition block.
pub strict_empty_steps_transition: Option<Uint>,
}
/// Authority engine deserialization.
#[derive(Debug, PartialEq, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct AuthorityRound {
/// Ethash params.
pub params: AuthorityRoundParams,
}
#[cfg(test)]
mod tests {
use ethereum_types::{H160, U256};
use hash::Address;
use serde_json;
use spec::{authority_round::AuthorityRound, validator_set::ValidatorSet};
use uint::Uint;
#[test]
fn authority_round_deserialization() {
let s = r#"{
"params": {
"stepDuration": "0x02",
"validators": {
"list" : ["0xc6d9d2cd449a754c494264e1809c50e34d64562b"]
},
"startStep" : 24,
"validateStepTransition": 150,
"blockReward": 5000000,
"maximumUncleCountTransition": 10000000,
"maximumUncleCount": 5
}
}"#;
let deserialized: AuthorityRound = serde_json::from_str(s).unwrap();
assert_eq!(deserialized.params.step_duration, Uint(U256::from(0x02)));
assert_eq!(
deserialized.params.validators,
ValidatorSet::List(vec![Address(H160::from(
"0xc6d9d2cd449a754c494264e1809c50e34d64562b"
))])
);
assert_eq!(deserialized.params.start_step, Some(Uint(U256::from(24))));
assert_eq!(deserialized.params.immediate_transitions, None);
assert_eq!(
deserialized.params.maximum_uncle_count_transition,
Some(Uint(10_000_000.into()))
);
assert_eq!(
deserialized.params.maximum_uncle_count,
Some(Uint(5.into()))
);
}
}

View File

@@ -0,0 +1,68 @@
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
// This file is part of OpenEthereum.
// OpenEthereum 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.
// OpenEthereum 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 OpenEthereum. If not, see <http://www.gnu.org/licenses/>.
//! Authority params deserialization.
use super::ValidatorSet;
use uint::Uint;
/// Authority params deserialization.
#[derive(Debug, PartialEq, Deserialize)]
#[serde(deny_unknown_fields)]
#[serde(rename_all = "camelCase")]
pub struct BasicAuthorityParams {
/// Block duration.
pub duration_limit: Uint,
/// Valid authorities
pub validators: ValidatorSet,
}
/// Authority engine deserialization.
#[derive(Debug, PartialEq, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct BasicAuthority {
/// Ethash params.
pub params: BasicAuthorityParams,
}
#[cfg(test)]
mod tests {
use ethereum_types::{H160, U256};
use hash::Address;
use serde_json;
use spec::{basic_authority::BasicAuthority, validator_set::ValidatorSet};
use uint::Uint;
#[test]
fn basic_authority_deserialization() {
let s = r#"{
"params": {
"durationLimit": "0x0d",
"validators" : {
"list": ["0xc6d9d2cd449a754c494264e1809c50e34d64562b"]
}
}
}"#;
let deserialized: BasicAuthority = serde_json::from_str(s).unwrap();
assert_eq!(deserialized.params.duration_limit, Uint(U256::from(0x0d)));
let vs = ValidatorSet::List(vec![Address(H160::from(
"0xc6d9d2cd449a754c494264e1809c50e34d64562b",
))]);
assert_eq!(deserialized.params.validators, vs);
}
}

View File

@@ -0,0 +1,392 @@
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
// This file is part of OpenEthereum.
// OpenEthereum 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.
// OpenEthereum 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 OpenEthereum. If not, see <http://www.gnu.org/licenses/>.
//! Spec builtin deserialization.
use std::collections::BTreeMap;
use uint::Uint;
/// Linear pricing.
#[derive(Debug, PartialEq, Deserialize, Clone)]
#[serde(deny_unknown_fields)]
pub struct Linear {
/// Base price.
pub base: u64,
/// Price for word.
pub word: u64,
}
/// Pricing for modular exponentiation.
#[derive(Debug, PartialEq, Deserialize, Clone)]
#[serde(deny_unknown_fields)]
pub struct Modexp {
/// Price divisor.
pub divisor: u64,
}
/// Pricing for EIP2565 modular exponentiation.
#[derive(Debug, PartialEq, Deserialize, Clone)]
#[serde(deny_unknown_fields)]
pub struct Modexp2565 {}
/// Pricing for constant alt_bn128 operations (ECADD and ECMUL)
#[derive(Debug, PartialEq, Deserialize, Clone)]
#[serde(deny_unknown_fields)]
pub struct AltBn128ConstOperations {
/// price
pub price: u64,
}
/// Pricing for alt_bn128_pairing.
#[derive(Debug, PartialEq, Deserialize, Clone)]
#[serde(deny_unknown_fields)]
pub struct AltBn128Pairing {
/// Base price.
pub base: u64,
/// Price per point pair.
pub pair: u64,
}
/// Bls12 pairing price
#[derive(Debug, PartialEq, Deserialize, Clone)]
#[serde(deny_unknown_fields)]
pub struct Bls12Pairing {
/// Price per final exp
pub base: u64,
/// Price per pair (Miller loop)
pub pair: u64,
}
/// Pricing for constant Bls12 operations (ADD and MUL in G1 and G2, as well as mappings)
#[derive(Debug, PartialEq, Deserialize, Clone)]
#[serde(deny_unknown_fields)]
pub struct Bls12ConstOperations {
/// Fixed price.
pub price: u64,
}
/// Pricing for constant Bls12 operations (ADD and MUL in G1, as well as mappings)
#[derive(Debug, PartialEq, Deserialize, Clone)]
#[serde(deny_unknown_fields)]
pub struct Bls12G1Multiexp {
/// Base const of the operation (G1 or G2 multiplication)
pub base: u64,
}
/// Pricing for constant Bls12 operations (ADD and MUL in G2, as well as mappings)
#[derive(Debug, PartialEq, Deserialize, Clone)]
#[serde(deny_unknown_fields)]
pub struct Bls12G2Multiexp {
/// Base const of the operation (G1 or G2 multiplication)
pub base: u64,
}
/// Pricing variants.
#[derive(Debug, PartialEq, Deserialize, Clone)]
#[serde(deny_unknown_fields)]
#[serde(rename_all = "snake_case")]
pub enum Pricing {
/// Pricing for Blake2 compression function: each call costs the same amount per round.
Blake2F {
/// Price per round of Blake2 compression function.
gas_per_round: u64,
},
/// Linear pricing.
Linear(Linear),
/// Pricing for EIP198 modular exponentiation.
Modexp(Modexp),
/// Pricing for EIP2565 modular exponentiation.
Modexp2565(Modexp2565),
/// Pricing for alt_bn128_pairing exponentiation.
AltBn128Pairing(AltBn128Pairing),
/// Pricing for constant alt_bn128 operations
AltBn128ConstOperations(AltBn128ConstOperations),
/// Pricing of constant price bls12_381 operations
Bls12ConstOperations(Bls12ConstOperations),
/// Pricing of pairing bls12_381 operation
Bls12Pairing(Bls12Pairing),
/// Pricing of bls12_381 multiexp operations in G1
Bls12G1Multiexp(Bls12G1Multiexp),
/// Pricing of bls12_381 multiexp operations in G2
Bls12G2Multiexp(Bls12G2Multiexp),
}
/// Builtin compability layer
#[derive(Debug, PartialEq, Deserialize, Clone)]
#[serde(deny_unknown_fields)]
pub struct BuiltinCompat {
/// Builtin name.
name: String,
/// Builtin pricing.
pricing: PricingCompat,
/// Activation block.
activate_at: Option<Uint>,
}
/// Spec builtin.
#[derive(Debug, PartialEq, Clone)]
pub struct Builtin {
/// Builtin name.
pub name: String,
/// Builtin pricing.
pub pricing: BTreeMap<u64, PricingAt>,
}
impl From<BuiltinCompat> for Builtin {
fn from(legacy: BuiltinCompat) -> Self {
let pricing = match legacy.pricing {
PricingCompat::Single(pricing) => {
let mut map = BTreeMap::new();
let activate_at: u64 = legacy.activate_at.map_or(0, Into::into);
map.insert(
activate_at,
PricingAt {
info: None,
price: pricing,
},
);
map
}
PricingCompat::Multi(pricings) => {
pricings.into_iter().map(|(a, p)| (a.into(), p)).collect()
}
};
Self {
name: legacy.name,
pricing,
}
}
}
/// Compability layer for different pricings
#[derive(Debug, PartialEq, Deserialize, Clone)]
#[serde(rename_all = "snake_case")]
#[serde(deny_unknown_fields)]
#[serde(untagged)]
enum PricingCompat {
/// Single builtin
Single(Pricing),
/// Multiple builtins
Multi(BTreeMap<Uint, PricingAt>),
}
/// Price for a builtin, with the block number to activate it on
#[derive(Debug, PartialEq, Deserialize, Clone)]
#[serde(deny_unknown_fields)]
pub struct PricingAt {
/// Description of the activation, e.g. "PunyPony HF, March 12, 2025".
pub info: Option<String>,
/// Builtin pricing.
pub price: Pricing,
}
#[cfg(test)]
mod tests {
use super::{
AltBn128ConstOperations, BTreeMap, Bls12G1Multiexp, Bls12G2Multiexp, Builtin,
BuiltinCompat, Linear, Modexp, Modexp2565, Pricing, PricingAt,
};
use macros::map;
use serde_json;
#[test]
fn builtin_deserialization() {
let s = r#"{
"name": "ecrecover",
"pricing": { "linear": { "base": 3000, "word": 0 } }
}"#;
let builtin: Builtin = serde_json::from_str::<BuiltinCompat>(s).unwrap().into();
assert_eq!(builtin.name, "ecrecover");
assert_eq!(
builtin.pricing,
map![
0 => PricingAt {
info: None,
price: Pricing::Linear(Linear { base: 3000, word: 0 })
}
]
);
}
#[test]
fn deserialize_multiple_pricings() {
let s = r#"{
"name": "ecrecover",
"pricing": {
"0": {
"price": {"linear": { "base": 3000, "word": 0 }}
},
"500": {
"info": "enable fake EIP at block 500",
"price": {"linear": { "base": 10, "word": 0 }}
}
}
}"#;
let builtin: Builtin = serde_json::from_str::<BuiltinCompat>(s).unwrap().into();
assert_eq!(builtin.name, "ecrecover");
assert_eq!(
builtin.pricing,
map![
0 => PricingAt {
info: None,
price: Pricing::Linear(Linear { base: 3000, word: 0 })
},
500 => PricingAt {
info: Some(String::from("enable fake EIP at block 500")),
price: Pricing::Linear(Linear { base: 10, word: 0 })
}
]
);
}
#[test]
fn deserialization_blake2_f_builtin() {
let s = r#"{
"name": "blake2_f",
"activate_at": "0xffffff",
"pricing": { "blake2_f": { "gas_per_round": 123 } }
}"#;
let builtin: Builtin = serde_json::from_str::<BuiltinCompat>(s).unwrap().into();
assert_eq!(builtin.name, "blake2_f");
assert_eq!(
builtin.pricing,
map![
0xffffff => PricingAt {
info: None,
price: Pricing::Blake2F { gas_per_round: 123 }
}
]
);
}
#[test]
fn deserialization_alt_bn128_const_operations() {
let s = r#"{
"name": "alt_bn128_mul",
"pricing": {
"100500": {
"price": { "alt_bn128_const_operations": { "price": 123 }}
}
}
}"#;
let builtin: Builtin = serde_json::from_str::<BuiltinCompat>(s).unwrap().into();
assert_eq!(builtin.name, "alt_bn128_mul");
assert_eq!(
builtin.pricing,
map![
100500 => PricingAt {
info: None,
price: Pricing::AltBn128ConstOperations(AltBn128ConstOperations {
price: 123,
}),
}
]
);
}
#[test]
fn activate_at() {
let s = r#"{
"name": "late_start",
"activate_at": 100000,
"pricing": { "modexp": { "divisor": 5 } }
}"#;
let builtin: Builtin = serde_json::from_str::<BuiltinCompat>(s).unwrap().into();
assert_eq!(builtin.name, "late_start");
assert_eq!(
builtin.pricing,
map![
100_000 => PricingAt {
info: None,
price: Pricing::Modexp(Modexp { divisor: 5 })
}
]
);
}
#[test]
fn deserialization_bls12_381_multiexp_operation() {
let s = r#"{
"name": "bls12_381_g1_multiexp",
"pricing": {
"10000000": {
"price": { "bls12_g1_multiexp": { "base": 12000}}
}
}
}"#;
let builtin: Builtin = serde_json::from_str::<BuiltinCompat>(s).unwrap().into();
assert_eq!(builtin.name, "bls12_381_g1_multiexp");
assert_eq!(
builtin.pricing,
btreemap![
10000000 => PricingAt {
info: None,
price: Pricing::Bls12G1Multiexp(Bls12G1Multiexp{
base: 12000
}),
}
]
);
}
#[test]
fn deserialization_bls12_381_multiexp_operation_in_g2() {
let s = r#"{
"name": "bls12_381_g2_multiexp",
"pricing": {
"10000000": {
"price": { "bls12_g2_multiexp": { "base": 55000}}
}
}
}"#;
let builtin: Builtin = serde_json::from_str::<BuiltinCompat>(s).unwrap().into();
assert_eq!(builtin.name, "bls12_381_g2_multiexp");
assert_eq!(
builtin.pricing,
btreemap![
10000000 => PricingAt {
info: None,
price: Pricing::Bls12G2Multiexp(Bls12G2Multiexp{
base: 55000
}),
}
]
);
}
#[test]
fn deserialization_modexp2565() {
let s = r#"{
"name": "modexp",
"pricing": {
"10000000": {
"price": { "modexp2565": { } }
}
}
}"#;
let builtin: Builtin = serde_json::from_str::<BuiltinCompat>(s).unwrap().into();
assert_eq!(builtin.name, "modexp");
assert_eq!(
builtin.pricing,
btreemap![
10000000 => PricingAt {
info: None,
price: Pricing::Modexp2565(Modexp2565{}),
}
]
);
}
}

View File

@@ -0,0 +1,55 @@
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
// This file is part of OpenEthereum.
// OpenEthereum 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.
// OpenEthereum 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 OpenEthereum. If not, see <http://www.gnu.org/licenses/>.
//! Clique params deserialization.
use std::num::NonZeroU64;
/// Clique params deserialization.
#[derive(Debug, PartialEq, Deserialize)]
pub struct CliqueParams {
/// period as defined in EIP
pub period: Option<u64>,
/// epoch length as defined in EIP
pub epoch: Option<NonZeroU64>,
}
/// Clique engine deserialization.
#[derive(Debug, PartialEq, Deserialize)]
pub struct Clique {
/// CliqueEngine params
pub params: CliqueParams,
}
#[cfg(test)]
mod tests {
use super::*;
use serde_json;
#[test]
fn clique_deserialization() {
let s = r#"{
"params": {
"period": 5,
"epoch": 30000
}
}"#;
let deserialized: Clique = serde_json::from_str(s).unwrap();
assert_eq!(deserialized.params.period, Some(5u64));
assert_eq!(deserialized.params.epoch, NonZeroU64::new(30000));
}
}

View File

@@ -0,0 +1,150 @@
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
// This file is part of OpenEthereum.
// OpenEthereum 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.
// OpenEthereum 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 OpenEthereum. If not, see <http://www.gnu.org/licenses/>.
//! Engine deserialization.
use super::{AuthorityRound, BasicAuthority, Clique, Ethash, InstantSeal, NullEngine};
/// Engine deserialization.
#[derive(Debug, PartialEq, Deserialize)]
#[serde(deny_unknown_fields)]
#[serde(rename_all = "camelCase")]
pub enum Engine {
/// Null engine.
Null(NullEngine),
/// Instantly sealing engine.
InstantSeal(Option<InstantSeal>),
/// Ethash engine.
#[serde(rename = "Ethash")]
Ethash(Ethash),
/// BasicAuthority engine.
BasicAuthority(BasicAuthority),
/// AuthorityRound engine.
AuthorityRound(AuthorityRound),
/// Clique engine.
Clique(Clique),
}
#[cfg(test)]
mod tests {
use serde_json;
use spec::Engine;
#[test]
fn engine_deserialization() {
let s = r#"{
"null": {
"params": {
"blockReward": "0x0d"
}
}
}"#;
let deserialized: Engine = serde_json::from_str(s).unwrap();
match deserialized {
Engine::Null(_) => {} // unit test in its own file.
_ => panic!(),
}
let s = r#"{
"instantSeal": {"params": {}}
}"#;
let deserialized: Engine = serde_json::from_str(s).unwrap();
match deserialized {
Engine::InstantSeal(_) => {} // instant seal is unit tested in its own file.
_ => panic!(),
};
let s = r#"{
"instantSeal": null
}"#;
let deserialized: Engine = serde_json::from_str(s).unwrap();
match deserialized {
Engine::InstantSeal(_) => {} // instant seal is unit tested in its own file.
_ => panic!(),
};
let s = r#"{
"Ethash": {
"params": {
"minimumDifficulty": "0x020000",
"difficultyBoundDivisor": "0x0800",
"durationLimit": "0x0d",
"homesteadTransition" : "0x",
"daoHardforkTransition": "0xffffffffffffffff",
"daoHardforkBeneficiary": "0x0000000000000000000000000000000000000000",
"daoHardforkAccounts": []
}
}
}"#;
let deserialized: Engine = serde_json::from_str(s).unwrap();
match deserialized {
Engine::Ethash(_) => {} // ethash is unit tested in its own file.
_ => panic!(),
};
let s = r#"{
"basicAuthority": {
"params": {
"durationLimit": "0x0d",
"validators" : {
"list": ["0xc6d9d2cd449a754c494264e1809c50e34d64562b"]
}
}
}
}"#;
let deserialized: Engine = serde_json::from_str(s).unwrap();
match deserialized {
Engine::BasicAuthority(_) => {} // basicAuthority is unit tested in its own file.
_ => panic!(),
};
let s = r#"{
"authorityRound": {
"params": {
"stepDuration": "0x02",
"validators": {
"list" : ["0xc6d9d2cd449a754c494264e1809c50e34d64562b"]
},
"startStep" : 24,
"validateStepTransition": 150
}
}
}"#;
let deserialized: Engine = serde_json::from_str(s).unwrap();
match deserialized {
Engine::AuthorityRound(_) => {} // AuthorityRound is unit tested in its own file.
_ => panic!(),
};
let s = r#"{
"clique": {
"params": {
"period": 15,
"epoch": 30000
}
}
}"#;
let deserialized: Engine = serde_json::from_str(s).unwrap();
match deserialized {
Engine::Clique(_) => {} // Clique is unit tested in its own file.
_ => panic!(),
};
}
}

View File

@@ -0,0 +1,263 @@
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
// This file is part of OpenEthereum.
// OpenEthereum 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.
// OpenEthereum 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 OpenEthereum. If not, see <http://www.gnu.org/licenses/>.
//! Ethash params deserialization.
use bytes::Bytes;
use hash::Address;
use std::collections::BTreeMap;
use uint::{self, Uint};
/// Deserializable doppelganger of block rewards for EthashParams
#[derive(Clone, Debug, PartialEq, Deserialize)]
#[serde(deny_unknown_fields)]
#[serde(untagged)]
pub enum BlockReward {
Single(Uint),
Multi(BTreeMap<Uint, Uint>),
}
/// Deserializable doppelganger of EthashParams.
#[derive(Clone, Debug, PartialEq, Deserialize)]
#[serde(deny_unknown_fields)]
#[serde(rename_all = "camelCase")]
pub struct EthashParams {
/// See main EthashParams docs.
#[serde(deserialize_with = "uint::validate_non_zero")]
pub minimum_difficulty: Uint,
/// See main EthashParams docs.
#[serde(deserialize_with = "uint::validate_non_zero")]
pub difficulty_bound_divisor: Uint,
/// See main EthashParams docs.
#[serde(default, deserialize_with = "uint::validate_optional_non_zero")]
pub difficulty_increment_divisor: Option<Uint>,
/// See main EthashParams docs.
#[serde(default, deserialize_with = "uint::validate_optional_non_zero")]
pub metropolis_difficulty_increment_divisor: Option<Uint>,
/// See main EthashParams docs.
pub duration_limit: Option<Uint>,
/// See main EthashParams docs.
pub homestead_transition: Option<Uint>,
/// Reward per block in wei.
pub block_reward: Option<BlockReward>,
/// Block at which the block reward contract should start being used.
pub block_reward_contract_transition: Option<Uint>,
/// Block reward contract address (setting the block reward contract
/// overrides all other block reward parameters).
pub block_reward_contract_address: Option<Address>,
/// Block reward code. This overrides the block reward contract address.
pub block_reward_contract_code: Option<Bytes>,
/// See main EthashParams docs.
pub dao_hardfork_transition: Option<Uint>,
/// See main EthashParams docs.
pub dao_hardfork_beneficiary: Option<Address>,
/// See main EthashParams docs.
pub dao_hardfork_accounts: Option<Vec<Address>>,
/// See main EthashParams docs.
pub difficulty_hardfork_transition: Option<Uint>,
/// See main EthashParams docs.
#[serde(default, deserialize_with = "uint::validate_optional_non_zero")]
pub difficulty_hardfork_bound_divisor: Option<Uint>,
/// See main EthashParams docs.
pub bomb_defuse_transition: Option<Uint>,
/// See main EthashParams docs.
pub eip100b_transition: Option<Uint>,
/// See main EthashParams docs.
pub ecip1017_era_rounds: Option<Uint>,
/// Delays of difficulty bombs.
pub difficulty_bomb_delays: Option<BTreeMap<Uint, Uint>>,
/// EXPIP-2 block height
pub expip2_transition: Option<Uint>,
/// EXPIP-2 duration limit
pub expip2_duration_limit: Option<Uint>,
/// Block to transition to progpow
#[serde(rename = "progpowTransition")]
pub progpow_transition: Option<Uint>,
}
/// Ethash engine deserialization.
#[derive(Debug, PartialEq, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct Ethash {
/// Ethash params.
pub params: EthashParams,
}
#[cfg(test)]
mod tests {
use ethereum_types::{H160, U256};
use hash::Address;
use serde_json;
use spec::ethash::{BlockReward, Ethash, EthashParams};
use uint::Uint;
#[test]
fn ethash_deserialization() {
let s = r#"{
"params": {
"minimumDifficulty": "0x020000",
"difficultyBoundDivisor": "0x0800",
"durationLimit": "0x0d",
"homesteadTransition": "0x42",
"blockReward": "0x100",
"daoHardforkTransition": "0x08",
"daoHardforkBeneficiary": "0xabcabcabcabcabcabcabcabcabcabcabcabcabca",
"daoHardforkAccounts": [
"0x304a554a310c7e546dfe434669c62820b7d83490",
"0x914d1b8b43e92723e64fd0a06f5bdb8dd9b10c79",
"0xfe24cdd8648121a43a7c86d289be4dd2951ed49f",
"0x17802f43a0137c506ba92291391a8a8f207f487d",
"0xb136707642a4ea12fb4bae820f03d2562ebff487",
"0xdbe9b615a3ae8709af8b93336ce9b477e4ac0940",
"0xf14c14075d6c4ed84b86798af0956deef67365b5",
"0xca544e5c4687d109611d0f8f928b53a25af72448",
"0xaeeb8ff27288bdabc0fa5ebb731b6f409507516c",
"0xcbb9d3703e651b0d496cdefb8b92c25aeb2171f7",
"0xaccc230e8a6e5be9160b8cdf2864dd2a001c28b6",
"0x2b3455ec7fedf16e646268bf88846bd7a2319bb2",
"0x4613f3bca5c44ea06337a9e439fbc6d42e501d0a",
"0xd343b217de44030afaa275f54d31a9317c7f441e",
"0x84ef4b2357079cd7a7c69fd7a37cd0609a679106",
"0xda2fef9e4a3230988ff17df2165440f37e8b1708",
"0xf4c64518ea10f995918a454158c6b61407ea345c",
"0x7602b46df5390e432ef1c307d4f2c9ff6d65cc97",
"0xbb9bc244d798123fde783fcc1c72d3bb8c189413",
"0x807640a13483f8ac783c557fcdf27be11ea4ac7a"
],
"difficultyHardforkTransition": "0x59d9",
"difficultyHardforkBoundDivisor": "0x0200",
"bombDefuseTransition": "0x41",
"eip100bTransition": "0x42"
}
}"#;
let deserialized: Ethash = serde_json::from_str(s).unwrap();
assert_eq!(
deserialized,
Ethash {
params: EthashParams {
minimum_difficulty: Uint(U256::from(0x020000)),
difficulty_bound_divisor: Uint(U256::from(0x0800)),
difficulty_increment_divisor: None,
metropolis_difficulty_increment_divisor: None,
duration_limit: Some(Uint(U256::from(0x0d))),
homestead_transition: Some(Uint(U256::from(0x42))),
block_reward: Some(BlockReward::Single(Uint(U256::from(0x100)))),
block_reward_contract_address: None,
block_reward_contract_code: None,
block_reward_contract_transition: None,
dao_hardfork_transition: Some(Uint(U256::from(0x08))),
dao_hardfork_beneficiary: Some(Address(H160::from(
"0xabcabcabcabcabcabcabcabcabcabcabcabcabca"
))),
dao_hardfork_accounts: Some(vec![
Address(H160::from("0x304a554a310c7e546dfe434669c62820b7d83490")),
Address(H160::from("0x914d1b8b43e92723e64fd0a06f5bdb8dd9b10c79")),
Address(H160::from("0xfe24cdd8648121a43a7c86d289be4dd2951ed49f")),
Address(H160::from("0x17802f43a0137c506ba92291391a8a8f207f487d")),
Address(H160::from("0xb136707642a4ea12fb4bae820f03d2562ebff487")),
Address(H160::from("0xdbe9b615a3ae8709af8b93336ce9b477e4ac0940")),
Address(H160::from("0xf14c14075d6c4ed84b86798af0956deef67365b5")),
Address(H160::from("0xca544e5c4687d109611d0f8f928b53a25af72448")),
Address(H160::from("0xaeeb8ff27288bdabc0fa5ebb731b6f409507516c")),
Address(H160::from("0xcbb9d3703e651b0d496cdefb8b92c25aeb2171f7")),
Address(H160::from("0xaccc230e8a6e5be9160b8cdf2864dd2a001c28b6")),
Address(H160::from("0x2b3455ec7fedf16e646268bf88846bd7a2319bb2")),
Address(H160::from("0x4613f3bca5c44ea06337a9e439fbc6d42e501d0a")),
Address(H160::from("0xd343b217de44030afaa275f54d31a9317c7f441e")),
Address(H160::from("0x84ef4b2357079cd7a7c69fd7a37cd0609a679106")),
Address(H160::from("0xda2fef9e4a3230988ff17df2165440f37e8b1708")),
Address(H160::from("0xf4c64518ea10f995918a454158c6b61407ea345c")),
Address(H160::from("0x7602b46df5390e432ef1c307d4f2c9ff6d65cc97")),
Address(H160::from("0xbb9bc244d798123fde783fcc1c72d3bb8c189413")),
Address(H160::from("0x807640a13483f8ac783c557fcdf27be11ea4ac7a")),
]),
difficulty_hardfork_transition: Some(Uint(U256::from(0x59d9))),
difficulty_hardfork_bound_divisor: Some(Uint(U256::from(0x0200))),
bomb_defuse_transition: Some(Uint(U256::from(0x41))),
eip100b_transition: Some(Uint(U256::from(0x42))),
ecip1017_era_rounds: None,
expip2_transition: None,
expip2_duration_limit: None,
progpow_transition: None,
difficulty_bomb_delays: None,
}
}
);
}
#[test]
fn ethash_deserialization_missing_optionals() {
let s = r#"{
"params": {
"difficultyBoundDivisor": "0x0800",
"minimumDifficulty": "0x020000"
}
}"#;
let deserialized: Ethash = serde_json::from_str(s).unwrap();
assert_eq!(
deserialized,
Ethash {
params: EthashParams {
minimum_difficulty: Uint(U256::from(0x020000)),
difficulty_bound_divisor: Uint(U256::from(0x0800)),
difficulty_increment_divisor: None,
metropolis_difficulty_increment_divisor: None,
duration_limit: None,
homestead_transition: None,
block_reward: None,
block_reward_contract_address: None,
block_reward_contract_code: None,
block_reward_contract_transition: None,
dao_hardfork_transition: None,
dao_hardfork_beneficiary: None,
dao_hardfork_accounts: None,
difficulty_hardfork_transition: None,
difficulty_hardfork_bound_divisor: None,
bomb_defuse_transition: None,
eip100b_transition: None,
ecip1017_era_rounds: None,
expip2_transition: None,
expip2_duration_limit: None,
progpow_transition: None,
difficulty_bomb_delays: None,
}
}
);
}
#[test]
#[should_panic(expected = "a non-zero value")]
fn test_zero_value_divisor() {
let s = r#"{
"params": {
"difficultyBoundDivisor": "0x0",
"minimumDifficulty": "0x020000"
}
}"#;
let _deserialized: Ethash = serde_json::from_str(s).unwrap();
}
}

View File

@@ -0,0 +1,115 @@
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
// This file is part of OpenEthereum.
// OpenEthereum 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.
// OpenEthereum 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 OpenEthereum. If not, see <http://www.gnu.org/licenses/>.
//! Spec genesis deserialization.
use bytes::Bytes;
use hash::{Address, H256};
use spec::Seal;
use uint::{self, Uint};
/// Spec genesis.
#[derive(Debug, PartialEq, Deserialize)]
#[serde(deny_unknown_fields)]
#[serde(rename_all = "camelCase")]
pub struct Genesis {
/// Seal.
pub seal: Seal,
/// Difficulty.
pub difficulty: Uint,
/// Block author, defaults to 0.
pub author: Option<Address>,
/// Block timestamp, defaults to 0.
pub timestamp: Option<Uint>,
/// Parent hash, defaults to 0.
pub parent_hash: Option<H256>,
/// Gas limit.
#[serde(deserialize_with = "uint::validate_non_zero")]
pub gas_limit: Uint,
/// Transactions root.
pub transactions_root: Option<H256>,
/// Receipts root.
pub receipts_root: Option<H256>,
/// State root.
pub state_root: Option<H256>,
/// Gas used.
pub gas_used: Option<Uint>,
/// Extra data.
pub extra_data: Option<Bytes>,
}
#[cfg(test)]
mod tests {
use bytes::Bytes;
use ethereum_types::{H160, H256 as Eth256, H64 as Eth64, U256};
use hash::{Address, H256, H64};
use serde_json;
use spec::{genesis::Genesis, Ethereum, Seal};
use std::str::FromStr;
use uint::Uint;
#[test]
fn genesis_deserialization() {
let s = r#"{
"difficulty": "0x400000000",
"seal": {
"ethereum": {
"mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"nonce": "0x00006d6f7264656e"
}
},
"author": "0x1000000000000000000000000000000000000001",
"timestamp": "0x07",
"parentHash": "0x9000000000000000000000000000000000000000000000000000000000000000",
"extraData": "0x11bbe8db4e347b4e8c937c1c8370e4b5ed33adb3db69cbdb7a38e1e50b1b82fa",
"gasLimit": "0x1388",
"stateRoot": "0xd7f8974fb5ac78d9ac099b9ad5018bedc2ce0a72dad1827a1709da30580f0544"
}"#;
let deserialized: Genesis = serde_json::from_str(s).unwrap();
assert_eq!(
deserialized,
Genesis {
seal: Seal::Ethereum(Ethereum {
nonce: H64(Eth64::from("0x00006d6f7264656e")),
mix_hash: H256(Eth256::from(
"0x0000000000000000000000000000000000000000000000000000000000000000"
))
}),
difficulty: Uint(U256::from(0x400000000u64)),
author: Some(Address(H160::from(
"0x1000000000000000000000000000000000000001"
))),
timestamp: Some(Uint(U256::from(0x07))),
parent_hash: Some(H256(Eth256::from(
"0x9000000000000000000000000000000000000000000000000000000000000000"
))),
gas_limit: Uint(U256::from(0x1388)),
transactions_root: None,
receipts_root: None,
state_root: Some(H256(Eth256::from(
"0xd7f8974fb5ac78d9ac099b9ad5018bedc2ce0a72dad1827a1709da30580f0544"
))),
gas_used: None,
extra_data: Some(
Bytes::from_str(
"0x11bbe8db4e347b4e8c937c1c8370e4b5ed33adb3db69cbdb7a38e1e50b1b82fa"
)
.unwrap()
),
}
);
}
}

View File

@@ -0,0 +1,35 @@
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
// This file is part of OpenEthereum.
// OpenEthereum 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.
// OpenEthereum 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 OpenEthereum. If not, see <http://www.gnu.org/licenses/>.
//! Instant seal engine params deserialization.
/// Instant seal engine params deserialization.
#[derive(Debug, PartialEq, Deserialize)]
#[serde(deny_unknown_fields)]
#[serde(rename_all = "camelCase")]
pub struct InstantSealParams {
/// Whether to enable millisecond timestamp.
#[serde(default)]
pub millisecond_timestamp: bool,
}
/// Instant seal engine descriptor.
#[derive(Debug, PartialEq, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct InstantSeal {
/// Instant seal parameters.
pub params: InstantSealParams,
}

View File

@@ -0,0 +1,51 @@
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
// This file is part of OpenEthereum.
// OpenEthereum 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.
// OpenEthereum 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 OpenEthereum. If not, see <http://www.gnu.org/licenses/>.
//! Spec deserialization.
pub mod account;
pub mod authority_round;
pub mod basic_authority;
pub mod builtin;
pub mod clique;
pub mod engine;
pub mod ethash;
pub mod genesis;
pub mod instant_seal;
pub mod null_engine;
pub mod params;
pub mod seal;
pub mod spec;
pub mod state;
pub mod validator_set;
pub use self::{
account::Account,
authority_round::{AuthorityRound, AuthorityRoundParams},
basic_authority::{BasicAuthority, BasicAuthorityParams},
builtin::{Builtin, Linear, Pricing},
clique::{Clique, CliqueParams},
engine::Engine,
ethash::{BlockReward, Ethash, EthashParams},
genesis::Genesis,
instant_seal::{InstantSeal, InstantSealParams},
null_engine::{NullEngine, NullEngineParams},
params::Params,
seal::{AuthorityRoundSeal, Ethereum, Seal, TendermintSeal},
spec::{ForkSpec, Spec},
state::State,
validator_set::ValidatorSet,
};

View File

@@ -0,0 +1,61 @@
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
// This file is part of OpenEthereum.
// OpenEthereum 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.
// OpenEthereum 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 OpenEthereum. If not, see <http://www.gnu.org/licenses/>.
//! Null engine params deserialization.
use uint::Uint;
/// Authority params deserialization.
#[derive(Debug, PartialEq, Deserialize)]
#[serde(deny_unknown_fields)]
#[serde(rename_all = "camelCase")]
pub struct NullEngineParams {
/// Block reward.
pub block_reward: Option<Uint>,
/// Immediate finalization.
pub immediate_finalization: Option<bool>,
}
/// Null engine descriptor
#[derive(Debug, PartialEq, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct NullEngine {
/// Ethash params.
pub params: NullEngineParams,
}
#[cfg(test)]
mod tests {
use super::*;
use ethereum_types::U256;
use serde_json;
use uint::Uint;
#[test]
fn null_engine_deserialization() {
let s = r#"{
"params": {
"blockReward": "0x0d"
}
}"#;
let deserialized: NullEngine = serde_json::from_str(s).unwrap();
assert_eq!(
deserialized.params.block_reward,
Some(Uint(U256::from(0x0d)))
);
}
}

View File

@@ -0,0 +1,207 @@
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
// This file is part of OpenEthereum.
// OpenEthereum 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.
// OpenEthereum 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 OpenEthereum. If not, see <http://www.gnu.org/licenses/>.
//! Spec params deserialization.
use bytes::Bytes;
use hash::{Address, H256};
use uint::{self, Uint};
/// Spec params.
#[derive(Debug, PartialEq, Deserialize)]
#[serde(deny_unknown_fields)]
#[serde(rename_all = "camelCase")]
pub struct Params {
/// Account start nonce, defaults to 0.
pub account_start_nonce: Option<Uint>,
/// Maximum size of extra data.
pub maximum_extra_data_size: Uint,
/// Minimum gas limit.
pub min_gas_limit: Uint,
/// Network id.
#[serde(rename = "networkID")]
pub network_id: Uint,
/// Chain id.
#[serde(rename = "chainID")]
pub chain_id: Option<Uint>,
/// Name of the main ("eth") subprotocol.
pub subprotocol_name: Option<String>,
/// Option fork block number to check.
pub fork_block: Option<Uint>,
/// Expected fork block hash.
#[serde(rename = "forkCanonHash")]
pub fork_hash: Option<H256>,
/// See main EthashParams docs.
pub eip150_transition: Option<Uint>,
/// See main EthashParams docs.
pub eip160_transition: Option<Uint>,
/// See main EthashParams docs.
pub eip161abc_transition: Option<Uint>,
/// See main EthashParams docs.
pub eip161d_transition: Option<Uint>,
/// See `CommonParams` docs.
pub eip98_transition: Option<Uint>,
/// See `CommonParams` docs.
pub eip155_transition: Option<Uint>,
/// See `CommonParams` docs.
pub validate_chain_id_transition: Option<Uint>,
/// See `CommonParams` docs.
pub validate_receipts_transition: Option<Uint>,
/// See `CommonParams` docs.
pub eip140_transition: Option<Uint>,
/// See `CommonParams` docs.
pub eip210_transition: Option<Uint>,
/// See `CommonParams` docs.
pub eip210_contract_address: Option<Address>,
/// See `CommonParams` docs.
pub eip210_contract_code: Option<Bytes>,
/// See `CommonParams` docs.
pub eip210_contract_gas: Option<Uint>,
/// See `CommonParams` docs.
pub eip211_transition: Option<Uint>,
/// See `CommonParams` docs.
pub eip145_transition: Option<Uint>,
/// See `CommonParams` docs.
pub eip214_transition: Option<Uint>,
/// See `CommonParams` docs.
pub eip658_transition: Option<Uint>,
/// See `CommonParams` docs.
pub eip1052_transition: Option<Uint>,
/// See `CommonParams` docs.
pub eip1283_transition: Option<Uint>,
/// See `CommonParams` docs.
pub eip1283_disable_transition: Option<Uint>,
/// See `CommonParams` docs.
pub eip1283_reenable_transition: Option<Uint>,
/// See `CommonParams` docs.
pub eip1014_transition: Option<Uint>,
/// See `CommonParams` docs.
pub eip1706_transition: Option<Uint>,
/// See `CommonParams` docs.
pub eip1344_transition: Option<Uint>,
/// See `CommonParams` docs.
pub eip1884_transition: Option<Uint>,
/// See `CommonParams` docs.
pub eip2028_transition: Option<Uint>,
/// See `CommonParams` docs.
pub eip2315_transition: Option<Uint>,
/// See `CommonParams` docs.
pub eip2929_transition: Option<Uint>,
/// See `CommonParams` docs.
pub eip2930_transition: Option<Uint>,
/// See `CommonParams` docs.
pub dust_protection_transition: Option<Uint>,
/// See `CommonParams` docs.
pub nonce_cap_increment: Option<Uint>,
/// See `CommonParams` docs.
pub remove_dust_contracts: Option<bool>,
/// See `CommonParams` docs.
#[serde(deserialize_with = "uint::validate_non_zero")]
pub gas_limit_bound_divisor: Uint,
/// See `CommonParams` docs.
pub registrar: Option<Address>,
/// Apply reward flag
pub apply_reward: Option<bool>,
/// Node permission contract address.
pub node_permission_contract: Option<Address>,
/// See main EthashParams docs.
pub max_code_size: Option<Uint>,
/// Maximum size of transaction RLP payload.
pub max_transaction_size: Option<Uint>,
/// See main EthashParams docs.
pub max_code_size_transition: Option<Uint>,
/// Transaction permission contract address.
pub transaction_permission_contract: Option<Address>,
/// Block at which the transaction permission contract should start being used.
pub transaction_permission_contract_transition: Option<Uint>,
/// Wasm activation block height, if not activated from start
pub wasm_activation_transition: Option<Uint>,
/// Wasm deactivation block height, if activated.
pub wasm_disable_transition: Option<Uint>,
/// KIP4 activiation block height.
pub kip4_transition: Option<Uint>,
/// KIP6 activiation block height.
pub kip6_transition: Option<Uint>,
}
#[cfg(test)]
mod tests {
use ethereum_types::U256;
use serde_json;
use spec::params::Params;
use uint::Uint;
#[test]
fn params_deserialization() {
let s = r#"{
"maximumExtraDataSize": "0x20",
"networkID" : "0x1",
"chainID" : "0x15",
"subprotocolName" : "exp",
"minGasLimit": "0x1388",
"accountStartNonce": "0x01",
"gasLimitBoundDivisor": "0x20",
"maxCodeSize": "0x1000",
"wasmActivationTransition": "0x1010",
"wasmDisableTransition": "0x2010"
}"#;
let deserialized: Params = serde_json::from_str(s).unwrap();
assert_eq!(deserialized.maximum_extra_data_size, Uint(U256::from(0x20)));
assert_eq!(deserialized.network_id, Uint(U256::from(0x1)));
assert_eq!(deserialized.chain_id, Some(Uint(U256::from(0x15))));
assert_eq!(deserialized.subprotocol_name, Some("exp".to_owned()));
assert_eq!(deserialized.min_gas_limit, Uint(U256::from(0x1388)));
assert_eq!(
deserialized.account_start_nonce,
Some(Uint(U256::from(0x01)))
);
assert_eq!(deserialized.gas_limit_bound_divisor, Uint(U256::from(0x20)));
assert_eq!(deserialized.max_code_size, Some(Uint(U256::from(0x1000))));
assert_eq!(
deserialized.wasm_activation_transition,
Some(Uint(U256::from(0x1010)))
);
assert_eq!(
deserialized.wasm_disable_transition,
Some(Uint(U256::from(0x2010)))
);
}
#[test]
#[should_panic(expected = "a non-zero value")]
fn test_zero_value_divisor() {
let s = r#"{
"maximumExtraDataSize": "0x20",
"networkID" : "0x1",
"chainID" : "0x15",
"subprotocolName" : "exp",
"minGasLimit": "0x1388",
"accountStartNonce": "0x01",
"gasLimitBoundDivisor": "0x0",
"maxCodeSize": "0x1000"
}"#;
let _deserialized: Params = serde_json::from_str(s).unwrap();
}
}

View File

@@ -0,0 +1,141 @@
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
// This file is part of OpenEthereum.
// OpenEthereum 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.
// OpenEthereum 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 OpenEthereum. If not, see <http://www.gnu.org/licenses/>.
//! Spec seal deserialization.
use bytes::Bytes;
use hash::*;
use uint::Uint;
/// Ethereum seal.
#[derive(Debug, PartialEq, Deserialize)]
#[serde(deny_unknown_fields)]
#[serde(rename_all = "camelCase")]
pub struct Ethereum {
/// Seal nonce.
pub nonce: H64,
/// Seal mix hash.
pub mix_hash: H256,
}
/// AuthorityRound seal.
#[derive(Debug, PartialEq, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct AuthorityRoundSeal {
/// Seal step.
pub step: Uint,
/// Seal signature.
pub signature: H520,
}
/// Tendermint seal.
#[derive(Debug, PartialEq, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct TendermintSeal {
/// Seal round.
pub round: Uint,
/// Proposal seal signature.
pub proposal: H520,
/// Proposal seal signature.
pub precommits: Vec<H520>,
}
/// Seal variants.
#[derive(Debug, PartialEq, Deserialize)]
#[serde(deny_unknown_fields)]
#[serde(rename_all = "camelCase")]
pub enum Seal {
/// Ethereum seal.
Ethereum(Ethereum),
/// AuthorityRound seal.
AuthorityRound(AuthorityRoundSeal),
/// Tendermint seal.
Tendermint(TendermintSeal),
/// Generic seal.
Generic(Bytes),
}
#[cfg(test)]
mod tests {
use bytes::Bytes;
use ethereum_types::{H256 as Eth256, H520 as Eth520, H64 as Eth64, U256};
use hash::*;
use serde_json;
use spec::{AuthorityRoundSeal, Ethereum, Seal, TendermintSeal};
use uint::Uint;
#[test]
fn seal_deserialization() {
let s = r#"[{
"ethereum": {
"nonce": "0x0000000000000042",
"mixHash": "0x1000000000000000000000000000000000000000000000000000000000000001"
}
},{
"generic": "0xe011bbe8db4e347b4e8c937c1c8370e4b5ed33adb3db69cbdb7a38e1e50b1b82fa"
},{
"authorityRound": {
"step": "0x0",
"signature": "0x2000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002"
}
},{
"tendermint": {
"round": "0x3",
"proposal": "0x3000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003",
"precommits": [
"0x4000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004"
]
}
}]"#;
let deserialized: Vec<Seal> = serde_json::from_str(s).unwrap();
assert_eq!(deserialized.len(), 4);
// [0]
assert_eq!(
deserialized[0],
Seal::Ethereum(Ethereum {
nonce: H64(Eth64::from("0x0000000000000042")),
mix_hash: H256(Eth256::from(
"0x1000000000000000000000000000000000000000000000000000000000000001"
))
})
);
// [1]
assert_eq!(
deserialized[1],
Seal::Generic(Bytes::new(vec![
0xe0, 0x11, 0xbb, 0xe8, 0xdb, 0x4e, 0x34, 0x7b, 0x4e, 0x8c, 0x93, 0x7c, 0x1c, 0x83,
0x70, 0xe4, 0xb5, 0xed, 0x33, 0xad, 0xb3, 0xdb, 0x69, 0xcb, 0xdb, 0x7a, 0x38, 0xe1,
0xe5, 0x0b, 0x1b, 0x82, 0xfa
]))
);
// [2]
assert_eq!(deserialized[2], Seal::AuthorityRound(AuthorityRoundSeal {
step: Uint(U256::from(0x0)),
signature: H520(Eth520::from("0x2000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002"))
}));
// [3]
assert_eq!(deserialized[3], Seal::Tendermint(TendermintSeal {
round: Uint(U256::from(0x3)),
proposal: H520(Eth520::from("0x3000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003")),
precommits: vec![H520(Eth520::from("0x4000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004"))]
}));
}
}

View File

@@ -0,0 +1,240 @@
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
// This file is part of OpenEthereum.
// OpenEthereum 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.
// OpenEthereum 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 OpenEthereum. If not, see <http://www.gnu.org/licenses/>.
//! Spec deserialization.
use serde_json::{self, Error};
use spec::{Engine, Genesis, Params, State};
use std::io::Read;
/// Fork spec definition
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Deserialize)]
pub enum ForkSpec {
EIP150,
EIP158,
Frontier,
Homestead,
Byzantium,
Constantinople,
ConstantinopleFix,
Istanbul,
EIP158ToByzantiumAt5,
FrontierToHomesteadAt5,
HomesteadToDaoAt5,
HomesteadToEIP150At5,
ByzantiumToConstantinopleAt5,
ByzantiumToConstantinopleFixAt5,
Berlin,
Yolo3,
}
/// Spec deserialization.
#[derive(Debug, PartialEq, Deserialize)]
#[serde(deny_unknown_fields)]
#[serde(rename_all = "camelCase")]
pub struct Spec {
/// Spec name.
pub name: String,
/// Special fork name.
pub data_dir: Option<String>,
/// Engine.
pub engine: Engine,
/// Spec params.
pub params: Params,
/// Genesis header.
pub genesis: Genesis,
/// Genesis state.
pub accounts: State,
/// Boot nodes.
pub nodes: Option<Vec<String>>,
}
impl Spec {
/// Loads test from json.
pub fn load<R>(reader: R) -> Result<Self, Error>
where
R: Read,
{
serde_json::from_reader(reader)
}
}
#[cfg(test)]
mod tests {
use serde_json;
use spec::spec::Spec;
#[test]
fn should_error_on_unknown_fields() {
let s = r#"{
"name": "Morden",
"dataDir": "morden",
"engine": {
"Ethash": {
"params": {
"minimumDifficulty": "0x020000",
"difficultyBoundDivisor": "0x0800",
"durationLimit": "0x0d",
"homesteadTransition" : "0x",
"daoHardforkTransition": "0xffffffffffffffff",
"daoHardforkBeneficiary": "0x0000000000000000000000000000000000000000",
"daoHardforkAccounts": []
}
}
},
"params": {
"accountStartNonce": "0x0100000",
"maximumExtraDataSize": "0x20",
"minGasLimit": "0x1388",
"networkID" : "0x2",
"forkBlock": "0xffffffffffffffff",
"forkCanonHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"gasLimitBoundDivisor": "0x20",
"unknownField": "0x0"
},
"genesis": {
"seal": {
"ethereum": {
"mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"nonce": "0x00006d6f7264656e"
}
},
"difficulty": "0x20000",
"author": "0x0000000000000000000000000000000000000000",
"timestamp": "0x00",
"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"extraData": "0x",
"gasLimit": "0x2fefd8"
},
"nodes": [
"enode://b1217cbaa440e35ed471157123fe468e19e8b5ad5bedb4b1fdbcbdab6fb2f5ed3e95dd9c24a22a79fdb2352204cea207df27d92bfd21bfd41545e8b16f637499@104.44.138.37:30303"
],
"accounts": {
"0000000000000000000000000000000000000001": { "balance": "1", "nonce": "1048576", "builtin": { "name": "ecrecover", "pricing": { "linear": { "base": 3000, "word": 0 } } } },
"0000000000000000000000000000000000000002": { "balance": "1", "nonce": "1048576", "builtin": { "name": "sha256", "pricing": { "linear": { "base": 60, "word": 12 } } } },
"0000000000000000000000000000000000000003": { "balance": "1", "nonce": "1048576", "builtin": { "name": "ripemd160", "pricing": { "linear": { "base": 600, "word": 120 } } } },
"0000000000000000000000000000000000000004": { "balance": "1", "nonce": "1048576", "builtin": { "name": "identity", "pricing": { "linear": { "base": 15, "word": 3 } } } },
"102e61f5d8f9bc71d0ad4a084df4e65e05ce0e1c": { "balance": "1606938044258990275541962092341162602522202993782792835301376", "nonce": "1048576" }
}
}"#;
let result: Result<Spec, _> = serde_json::from_str(s);
assert!(result.is_err());
}
#[test]
fn spec_deserialization() {
let s = r#"{
"name": "Morden",
"dataDir": "morden",
"engine": {
"Ethash": {
"params": {
"minimumDifficulty": "0x020000",
"difficultyBoundDivisor": "0x0800",
"durationLimit": "0x0d",
"homesteadTransition" : "0x",
"daoHardforkTransition": "0xffffffffffffffff",
"daoHardforkBeneficiary": "0x0000000000000000000000000000000000000000",
"daoHardforkAccounts": []
}
}
},
"params": {
"accountStartNonce": "0x0100000",
"maximumExtraDataSize": "0x20",
"minGasLimit": "0x1388",
"networkID" : "0x2",
"forkBlock": "0xffffffffffffffff",
"forkCanonHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"gasLimitBoundDivisor": "0x20"
},
"genesis": {
"seal": {
"ethereum": {
"mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"nonce": "0x00006d6f7264656e"
}
},
"difficulty": "0x20000",
"author": "0x0000000000000000000000000000000000000000",
"timestamp": "0x00",
"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"extraData": "0x",
"gasLimit": "0x2fefd8"
},
"nodes": [
"enode://b1217cbaa440e35ed471157123fe468e19e8b5ad5bedb4b1fdbcbdab6fb2f5ed3e95dd9c24a22a79fdb2352204cea207df27d92bfd21bfd41545e8b16f637499@104.44.138.37:30303"
],
"accounts": {
"0000000000000000000000000000000000000001": {
"balance": "1",
"nonce": "1048576",
"builtin": {
"name": "ecrecover",
"pricing": {
"linear": {
"base": 3000,
"word": 0
}
}
}
},
"0000000000000000000000000000000000000002": {
"balance": "1",
"nonce": "1048576",
"builtin": {
"name": "sha256",
"pricing": {
"linear": {
"base": 60,
"word": 12
}
}
}
},
"0000000000000000000000000000000000000003": {
"balance": "1",
"nonce": "1048576",
"builtin": {
"name": "ripemd160",
"pricing": {
"linear": {
"base": 600,
"word": 120
}
}
}
},
"0000000000000000000000000000000000000004": {
"balance": "1",
"nonce": "1048576",
"builtin": {
"name": "identity",
"pricing": {
"linear": {
"base": 15,
"word": 3
}
}
}
},
"102e61f5d8f9bc71d0ad4a084df4e65e05ce0e1c": { "balance": "1606938044258990275541962092341162602522202993782792835301376", "nonce": "1048576" }
}
}"#;
let _deserialized: Spec = serde_json::from_str(s).unwrap();
// TODO: validate all fields
}
}

View File

@@ -0,0 +1,54 @@
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
// This file is part of OpenEthereum.
// OpenEthereum 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.
// OpenEthereum 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 OpenEthereum. If not, see <http://www.gnu.org/licenses/>.
//! Blockchain test state deserializer.
use bytes::Bytes;
use hash::Address;
use spec::{Account, Builtin};
use std::collections::BTreeMap;
/// Blockchain test state deserializer.
#[derive(Debug, PartialEq, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct State(BTreeMap<Address, Account>);
impl State {
/// Returns all builtins.
pub fn builtins(&self) -> BTreeMap<Address, Builtin> {
self.0
.iter()
.filter_map(|(add, ref acc)| acc.builtin.clone().map(|b| (add.clone(), b.into())))
.collect()
}
/// Returns all constructors.
pub fn constructors(&self) -> BTreeMap<Address, Bytes> {
self.0
.iter()
.filter_map(|(add, ref acc)| acc.constructor.clone().map(|b| (add.clone(), b)))
.collect()
}
}
impl IntoIterator for State {
type Item = <BTreeMap<Address, Account> as IntoIterator>::Item;
type IntoIter = <BTreeMap<Address, Account> as IntoIterator>::IntoIter;
fn into_iter(self) -> Self::IntoIter {
self.0.into_iter()
}
}

View File

@@ -0,0 +1,93 @@
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
// This file is part of OpenEthereum.
// OpenEthereum 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.
// OpenEthereum 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 OpenEthereum. If not, see <http://www.gnu.org/licenses/>.
//! Validator set deserialization.
use hash::Address;
use std::collections::BTreeMap;
use uint::Uint;
/// Different ways of specifying validators.
#[derive(Debug, PartialEq, Deserialize)]
#[serde(deny_unknown_fields)]
#[serde(rename_all = "camelCase")]
pub enum ValidatorSet {
/// A simple list of authorities.
List(Vec<Address>),
/// Address of a contract that indicates the list of authorities.
SafeContract(Address),
/// Address of a contract that indicates the list of authorities and enables reporting of theor misbehaviour using transactions.
Contract(Address),
/// A map of starting blocks for each validator set.
Multi(BTreeMap<Uint, ValidatorSet>),
}
#[cfg(test)]
mod tests {
use ethereum_types::{H160, U256};
use hash::Address;
use serde_json;
use spec::validator_set::ValidatorSet;
use uint::Uint;
#[test]
fn validator_set_deserialization() {
let s = r#"[{
"list": ["0xc6d9d2cd449a754c494264e1809c50e34d64562b"]
}, {
"safeContract": "0xc6d9d2cd449a754c494264e1809c50e34d64562b"
}, {
"contract": "0xc6d9d2cd449a754c494264e1809c50e34d64562b"
}, {
"multi": {
"0": { "list": ["0xc6d9d2cd449a754c494264e1809c50e34d64562b"] },
"10": { "list": ["0xd6d9d2cd449a754c494264e1809c50e34d64562b"] },
"20": { "contract": "0xc6d9d2cd449a754c494264e1809c50e34d64562b" }
}
}]"#;
let deserialized: Vec<ValidatorSet> = serde_json::from_str(s).unwrap();
assert_eq!(deserialized.len(), 4);
assert_eq!(
deserialized[0],
ValidatorSet::List(vec![Address(H160::from(
"0xc6d9d2cd449a754c494264e1809c50e34d64562b"
))])
);
assert_eq!(
deserialized[1],
ValidatorSet::SafeContract(Address(H160::from(
"0xc6d9d2cd449a754c494264e1809c50e34d64562b"
)))
);
assert_eq!(
deserialized[2],
ValidatorSet::Contract(Address(H160::from(
"0xc6d9d2cd449a754c494264e1809c50e34d64562b"
)))
);
match deserialized[3] {
ValidatorSet::Multi(ref map) => {
assert_eq!(map.len(), 3);
assert!(map.contains_key(&Uint(U256::from(0))));
assert!(map.contains_key(&Uint(U256::from(10))));
assert!(map.contains_key(&Uint(U256::from(20))));
}
_ => assert!(false),
}
}
}

View File

@@ -0,0 +1,52 @@
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
// This file is part of OpenEthereum.
// OpenEthereum 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.
// OpenEthereum 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 OpenEthereum. If not, see <http://www.gnu.org/licenses/>.
//! State test log deserialization.
use bytes::Bytes;
use hash::{Address, Bloom, H256};
/// State test log deserialization.
#[derive(Debug, PartialEq, Deserialize)]
pub struct Log {
/// Address.
pub address: Address,
/// Topics.
pub topics: Vec<H256>,
/// Data.
pub data: Bytes,
/// Bloom.
pub bloom: Bloom,
}
#[cfg(test)]
mod tests {
use serde_json;
use state::Log;
#[test]
fn log_deserialization() {
let s = r#"{
"address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6",
"bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008800000000000000000020000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000",
"data" : "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
"topics" : [
"0000000000000000000000000000000000000000000000000000000000000000"
]
}"#;
let _deserialized: Log = serde_json::from_str(s).unwrap();
// TODO: validate all fields
}
}

View File

@@ -0,0 +1,26 @@
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
// This file is part of OpenEthereum.
// OpenEthereum 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.
// OpenEthereum 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 OpenEthereum. If not, see <http://www.gnu.org/licenses/>.
//! State test deserialization.
pub mod log;
pub mod state;
pub mod test;
pub mod transaction;
pub use self::{log::Log, state::State, test::Test, transaction::Transaction};
pub use blockchain::State as AccountState;
pub use vm::Env;

View File

@@ -0,0 +1,156 @@
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
// This file is part of OpenEthereum.
// OpenEthereum 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.
// OpenEthereum 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 OpenEthereum. If not, see <http://www.gnu.org/licenses/>.
//! State test deserialization.
use bytes::Bytes;
use hash::H256;
use state::{AccountState, Env, Log, Transaction};
/// State test deserialization.
#[derive(Debug, PartialEq, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct State {
/// Environment.
pub env: Env,
/// Output.
#[serde(rename = "out")]
pub output: Bytes,
/// Pre state.
#[serde(rename = "pre")]
pub pre_state: AccountState,
/// Post state.
#[serde(rename = "post")]
pub post_state: AccountState,
/// Post state root.
pub post_state_root: H256,
/// Transaction.
pub transaction: Transaction,
/// Logs.
pub logs: Vec<Log>,
}
#[cfg(test)]
mod tests {
use serde_json;
use state::State;
#[test]
fn state_deserialization() {
let s = r#"{
"env" : {
"currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba",
"currentDifficulty" : "0x0100",
"currentGasLimit" : "0x01c9c380",
"currentNumber" : "0x00",
"currentTimestamp" : "0x01",
"previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6"
},
"logs" : [
],
"out" : "0x",
"post" : {
"1000000000000000000000000000000000000000" : {
"balance" : "0x0de0b6b3a763ffff",
"code" : "0x6040600060406000600173100000000000000000000000000000000000000162055730f1600055",
"nonce" : "0x00",
"storage" : {
"0x00" : "0x01"
}
},
"1000000000000000000000000000000000000001" : {
"balance" : "0x0de0b6b3a763ffff",
"code" : "0x604060006040600060027310000000000000000000000000000000000000026203d090f1600155",
"nonce" : "0x00",
"storage" : {
"0x01" : "0x01"
}
},
"1000000000000000000000000000000000000002" : {
"balance" : "0x02",
"code" : "0x600160025533600455346007553060e6553260e8553660ec553860ee553a60f055",
"nonce" : "0x00",
"storage" : {
"0x02" : "0x01",
"0x04" : "0x1000000000000000000000000000000000000001",
"0x07" : "0x02",
"0xe6" : "0x1000000000000000000000000000000000000002",
"0xe8" : "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b",
"0xec" : "0x40",
"0xee" : "0x21",
"0xf0" : "0x01"
}
},
"2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" : {
"balance" : "0x039455",
"code" : "0x",
"nonce" : "0x00",
"storage" : {
}
},
"a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
"balance" : "0x0de0b6b3a7606bab",
"code" : "0x",
"nonce" : "0x01",
"storage" : {
}
}
},
"postStateRoot" : "8f8ed2aed2973e159fa5486f47c6ebf15c5058f8e2350286b84b569bc6ce2d25",
"pre" : {
"1000000000000000000000000000000000000000" : {
"balance" : "0x0de0b6b3a7640000",
"code" : "0x6040600060406000600173100000000000000000000000000000000000000162055730f1600055",
"nonce" : "0x00",
"storage" : {
}
},
"1000000000000000000000000000000000000001" : {
"balance" : "0x0de0b6b3a7640000",
"code" : "0x604060006040600060027310000000000000000000000000000000000000026203d090f1600155",
"nonce" : "0x00",
"storage" : {
}
},
"1000000000000000000000000000000000000002" : {
"balance" : "0x00",
"code" : "0x600160025533600455346007553060e6553260e8553660ec553860ee553a60f055",
"nonce" : "0x00",
"storage" : {
}
},
"a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
"balance" : "0x0de0b6b3a7640000",
"code" : "0x",
"nonce" : "0x00",
"storage" : {
}
}
},
"transaction" : {
"data" : "",
"gasLimit" : "0x2dc6c0",
"gasPrice" : "0x01",
"nonce" : "0x00",
"secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8",
"to" : "1000000000000000000000000000000000000000",
"value" : "0x00"
}
}"#;
let _deserialized: State = serde_json::from_str(s).unwrap();
// TODO: validate all fields
}
}

View File

@@ -0,0 +1,217 @@
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
// This file is part of OpenEthereum.
// OpenEthereum 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.
// OpenEthereum 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 OpenEthereum. If not, see <http://www.gnu.org/licenses/>.
//! General test deserialization.
use bytes::Bytes;
use hash::{Address, H256};
use maybe::MaybeEmpty;
use serde_json::{self, Error};
use spec::ForkSpec;
use state::{AccountState, Env, Transaction};
use std::{collections::BTreeMap, io::Read};
use uint::Uint;
/// State test deserializer.
#[derive(Debug, PartialEq, Deserialize)]
pub struct Test(BTreeMap<String, State>);
impl IntoIterator for Test {
type Item = <BTreeMap<String, State> as IntoIterator>::Item;
type IntoIter = <BTreeMap<String, State> as IntoIterator>::IntoIter;
fn into_iter(self) -> Self::IntoIter {
self.0.into_iter()
}
}
impl Test {
/// Loads test from json.
pub fn load<R>(reader: R) -> Result<Self, Error>
where
R: Read,
{
serde_json::from_reader(reader)
}
}
/// State test deserialization.
#[derive(Debug, PartialEq, Deserialize)]
pub struct State {
/// Environment.
pub env: Env,
/// Pre state.
#[serde(rename = "pre")]
pub pre_state: AccountState,
/// Post state.
#[serde(rename = "post")]
pub post_states: BTreeMap<ForkSpec, Vec<PostStateResult>>,
/// Transaction.
pub transaction: MultiTransaction,
}
/// State test transaction deserialization.
#[derive(Debug, PartialEq, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct MultiTransaction {
/// Transaction data set.
pub data: Vec<Bytes>,
/// Gas limit set.
pub gas_limit: Vec<Uint>,
/// Gas price.
pub gas_price: Uint,
/// Nonce.
pub nonce: Uint,
/// Secret key.
#[serde(rename = "secretKey")]
pub secret: Option<H256>,
/// To.
pub to: MaybeEmpty<Address>,
/// Value set.
pub value: Vec<Uint>,
}
impl MultiTransaction {
/// Build transaction with given indexes.
pub fn select(&self, indexes: &PostStateIndexes) -> Transaction {
Transaction {
data: self.data[indexes.data as usize].clone(),
gas_limit: self.gas_limit[indexes.gas as usize].clone(),
gas_price: self.gas_price.clone(),
nonce: self.nonce.clone(),
secret: self.secret.clone(),
to: self.to.clone(),
value: self.value[indexes.value as usize].clone(),
}
}
}
/// State test indexes deserialization.
#[derive(Debug, PartialEq, Deserialize)]
pub struct PostStateIndexes {
/// Index into transaction data set.
pub data: u64,
/// Index into transaction gas limit set.
pub gas: u64,
/// Index into transaction value set.
pub value: u64,
}
/// State test indexed state result deserialization.
#[derive(Debug, PartialEq, Deserialize)]
pub struct PostStateResult {
/// Post state hash
pub hash: H256,
/// Indexes
pub indexes: PostStateIndexes,
}
#[cfg(test)]
mod tests {
use super::{MultiTransaction, State};
use serde_json;
#[test]
fn multi_transaction_deserialization() {
let s = r#"{
"data" : [ "" ],
"gasLimit" : [ "0x2dc6c0", "0x222222" ],
"gasPrice" : "0x01",
"nonce" : "0x00",
"secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8",
"to" : "1000000000000000000000000000000000000000",
"value" : [ "0x00", "0x01", "0x02" ]
}"#;
let _deserialized: MultiTransaction = serde_json::from_str(s).unwrap();
}
#[test]
fn state_deserialization() {
let s = r#"{
"env" : {
"currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba",
"currentDifficulty" : "0x0100",
"currentGasLimit" : "0x01c9c380",
"currentNumber" : "0x00",
"currentTimestamp" : "0x01",
"previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6"
},
"post" : {
"EIP150" : [
{
"hash" : "3e6dacc1575c6a8c76422255eca03529bbf4c0dda75dfc110b22d6dc4152396f",
"indexes" : { "data" : 0, "gas" : 0, "value" : 0 }
},
{
"hash" : "99a450d8ce5b987a71346d8a0a1203711f770745c7ef326912e46761f14cd764",
"indexes" : { "data" : 0, "gas" : 0, "value" : 1 }
}
],
"EIP158" : [
{
"hash" : "3e6dacc1575c6a8c76422255eca03529bbf4c0dda75dfc110b22d6dc4152396f",
"indexes" : { "data" : 0, "gas" : 0, "value" : 0 }
},
{
"hash" : "99a450d8ce5b987a71346d8a0a1203711f770745c7ef326912e46761f14cd764",
"indexes" : { "data" : 0, "gas" : 0, "value" : 1 }
}
]
},
"pre" : {
"1000000000000000000000000000000000000000" : {
"balance" : "0x0de0b6b3a7640000",
"code" : "0x6040600060406000600173100000000000000000000000000000000000000162055730f1600055",
"nonce" : "0x00",
"storage" : {
}
},
"1000000000000000000000000000000000000001" : {
"balance" : "0x0de0b6b3a7640000",
"code" : "0x604060006040600060027310000000000000000000000000000000000000026203d090f1600155",
"nonce" : "0x00",
"storage" : {
}
},
"1000000000000000000000000000000000000002" : {
"balance" : "0x00",
"code" : "0x600160025533600455346007553060e6553260e8553660ec553860ee553a60f055",
"nonce" : "0x00",
"storage" : {
}
},
"a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
"balance" : "0x0de0b6b3a7640000",
"code" : "0x",
"nonce" : "0x00",
"storage" : {
}
}
},
"transaction" : {
"data" : [ "" ],
"gasLimit" : [ "285000", "100000", "6000" ],
"gasPrice" : "0x01",
"nonce" : "0x00",
"secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8",
"to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87",
"value" : [ "10", "0" ]
}
}"#;
let _deserialized: State = serde_json::from_str(s).unwrap();
// TODO: validate all fields
}
}

View File

@@ -0,0 +1,64 @@
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
// This file is part of OpenEthereum.
// OpenEthereum 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.
// OpenEthereum 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 OpenEthereum. If not, see <http://www.gnu.org/licenses/>.
//! State test transaction deserialization.
use bytes::Bytes;
use hash::{Address, H256};
use maybe::MaybeEmpty;
use uint::Uint;
/// State test transaction deserialization.
#[derive(Debug, PartialEq, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Transaction {
/// Transaction data.
pub data: Bytes,
/// Gas limit.
pub gas_limit: Uint,
/// Gas price.
pub gas_price: Uint,
/// Nonce.
pub nonce: Uint,
/// Secret key.
#[serde(rename = "secretKey")]
pub secret: Option<H256>,
/// To.
pub to: MaybeEmpty<Address>,
/// Value.
pub value: Uint,
}
#[cfg(test)]
mod tests {
use serde_json;
use state::Transaction;
#[test]
fn transaction_deserialization() {
let s = r#"{
"data" : "",
"gasLimit" : "0x2dc6c0",
"gasPrice" : "0x01",
"nonce" : "0x00",
"secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8",
"to" : "1000000000000000000000000000000000000000",
"value" : "0x00"
}"#;
let _deserialized: Transaction = serde_json::from_str(s).unwrap();
// TODO: validate all fields
}
}

View File

@@ -0,0 +1,241 @@
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
// This file is part of OpenEthereum.
// OpenEthereum 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.
// OpenEthereum 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 OpenEthereum. If not, see <http://www.gnu.org/licenses/>.
//! Additional test structures deserialization.
use hash::H256;
use serde_json::{self, Error};
use std::{collections::BTreeMap, io::Read, path::PathBuf};
use uint::Uint;
/// Blockchain test header deserializer.
#[derive(Debug, PartialEq, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct DifficultyTestCase {
/// Parent timestamp.
pub parent_timestamp: Uint,
/// Parent difficulty.
pub parent_difficulty: Uint,
/// Parent uncle hash.
pub parent_uncles: H256,
/// Current timestamp.
pub current_timestamp: Uint,
/// Current difficulty.
pub current_difficulty: Uint,
/// Current block number.
pub current_block_number: Uint,
}
/// Blockchain test deserializer.
#[derive(Debug, PartialEq, Deserialize)]
pub struct DifficultyTest(BTreeMap<String, DifficultyTestCase>);
impl IntoIterator for DifficultyTest {
type Item = <BTreeMap<String, DifficultyTestCase> as IntoIterator>::Item;
type IntoIter = <BTreeMap<String, DifficultyTestCase> as IntoIterator>::IntoIter;
fn into_iter(self) -> Self::IntoIter {
self.0.into_iter()
}
}
impl DifficultyTest {
/// Loads test from json.
pub fn load<R>(reader: R) -> Result<Self, Error>
where
R: Read,
{
serde_json::from_reader(reader)
}
}
/// Test to skip (only if issue ongoing)
#[derive(Debug, PartialEq, Deserialize)]
pub struct SkipStates {
/// Block tests
pub block: Vec<BlockSkipStates>,
/// State tests
pub state: Vec<StateSkipStates>,
}
/// Block test to skip.
#[derive(Debug, PartialEq, Deserialize)]
pub struct BlockSkipStates {
/// Issue reference.
pub reference: String,
/// Test failing name.
pub failing: String,
/// Items failing for the test.
pub subtests: Vec<String>,
}
/// State test to skip.
#[derive(Debug, PartialEq, Deserialize)]
pub struct StateSkipStates {
/// Issue reference.
pub reference: String,
/// Test failing name.
pub failing: String,
/// Items failing for the test.
pub subtests: BTreeMap<String, StateSkipSubStates>,
}
/// State subtest to skip.
#[derive(Debug, PartialEq, Deserialize)]
pub struct StateSkipSubStates {
/// State test number of this item. Or '*' for all state.
pub subnumbers: Vec<String>,
/// Chain for this items.
pub chain: String,
}
impl SkipStates {
/// Loads skip states from json.
pub fn load<R>(reader: R) -> Result<Self, Error>
where
R: Read,
{
serde_json::from_reader(reader)
}
/// Empty skip states.
pub fn empty() -> Self {
SkipStates {
block: Vec::new(),
state: Vec::new(),
}
}
}
/// Describes a github.com/ethereum/tests suite
#[derive(Debug, PartialEq, Deserialize)]
pub struct EthereumTestSuite {
/// Blockchain tests
pub chain: Vec<ChainTests>,
/// State tests
pub state: Vec<StateTests>,
/// Difficulty tests
pub difficulty: Vec<DifficultyTests>,
/// Executive tests
pub executive: Vec<ExecutiveTests>,
/// Transaction tests
pub transaction: Vec<TransactionTests>,
/// Trie tests
pub trie: Vec<TrieTests>,
}
/// Chain spec used in tests
#[derive(Debug, PartialEq, Deserialize)]
pub enum TestChainSpec {
/// Foundation
Foundation,
/// ByzantiumTest
ByzantiumTest,
/// FrontierTest
FrontierTest,
/// HomesteadTest
HomesteadTest,
}
/// Kind of trie used in test
#[derive(Debug, PartialEq, Deserialize)]
pub enum TestTrieSpec {
/// Generic
Generic,
/// Secure
Secure,
}
/// A set of blockchain tests
#[derive(Debug, PartialEq, Deserialize)]
pub struct ChainTests {
/// Path of the json tests
pub path: PathBuf,
/// Tests to skip
pub skip: Vec<ChainTestSkip>,
}
/// Tests to skip in chain tests
#[derive(Debug, PartialEq, Deserialize)]
pub struct ChainTestSkip {
/// Issue reference.
pub reference: String,
/// Test names to skip
pub names: Vec<String>,
/// Test paths to skip
pub paths: Vec<String>,
}
/// A set of state tests
#[derive(Debug, PartialEq, Deserialize)]
pub struct StateTests {
/// Path of the json tests
pub path: PathBuf,
/// Tests to skip
pub skip: Vec<StateTestSkip>,
}
/// State test to skip
#[derive(Debug, PartialEq, Deserialize)]
pub struct StateTestSkip {
/// Issue reference.
pub reference: String,
/// Paths to skip
pub paths: Vec<String>,
/// Test names to skip
pub names: BTreeMap<String, StateSkipSubStates1>,
}
/// State subtest to skip.
#[derive(Debug, PartialEq, Deserialize)]
pub struct StateSkipSubStates1 {
/// State test number of this item. Or '*' for all state.
pub subnumbers: Vec<String>,
/// Chain for this items.
pub chain: String,
}
/// A set of difficulty tests
#[derive(Debug, PartialEq, Deserialize)]
pub struct DifficultyTests {
/// Path of the json tests
pub path: Vec<PathBuf>,
/// Chain spec to use
pub chainspec: TestChainSpec,
}
/// A set of executive tests
#[derive(Debug, PartialEq, Deserialize)]
pub struct ExecutiveTests {
/// Path of the json tests
pub path: PathBuf,
}
/// A set of transaction tests
#[derive(Debug, PartialEq, Deserialize)]
pub struct TransactionTests {
/// Path of the json tests
pub path: PathBuf,
}
/// A set of trie tests
#[derive(Debug, PartialEq, Deserialize)]
pub struct TrieTests {
/// Path of the json tests
pub path: Vec<PathBuf>,
/// Trie spec to use
pub triespec: TestTrieSpec,
}

View File

@@ -0,0 +1,23 @@
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
// This file is part of OpenEthereum.
// OpenEthereum 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.
// OpenEthereum 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 OpenEthereum. If not, see <http://www.gnu.org/licenses/>.
//! Transaction test deserialization.
mod test;
mod transaction;
mod txtest;
pub use self::{test::Test, transaction::Transaction, txtest::TransactionTest};

View File

@@ -0,0 +1,44 @@
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
// This file is part of OpenEthereum.
// OpenEthereum 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.
// OpenEthereum 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 OpenEthereum. If not, see <http://www.gnu.org/licenses/>.
//! TransactionTest test deserializer.
use serde_json::{self, Error};
use std::{collections::BTreeMap, io::Read};
use transaction::TransactionTest;
/// TransactionTest test deserializer.
#[derive(Debug, Deserialize)]
pub struct Test(BTreeMap<String, TransactionTest>);
impl IntoIterator for Test {
type Item = <BTreeMap<String, TransactionTest> as IntoIterator>::Item;
type IntoIter = <BTreeMap<String, TransactionTest> as IntoIterator>::IntoIter;
fn into_iter(self) -> Self::IntoIter {
self.0.into_iter()
}
}
impl Test {
/// Loads test from json.
pub fn load<R>(reader: R) -> Result<Self, Error>
where
R: Read,
{
serde_json::from_reader(reader)
}
}

View File

@@ -0,0 +1,69 @@
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
// This file is part of OpenEthereum.
// OpenEthereum 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.
// OpenEthereum 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 OpenEthereum. If not, see <http://www.gnu.org/licenses/>.
//! Transaction test transaction deserialization.
use bytes::Bytes;
use hash::Address;
use maybe::MaybeEmpty;
use uint::Uint;
/// Transaction test transaction deserialization.
#[derive(Debug, PartialEq, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Transaction {
/// Transaction data.
pub data: Bytes,
/// Gas limit.
pub gas_limit: Uint,
/// Gas price.
pub gas_price: Uint,
/// Nonce.
pub nonce: Uint,
/// To.
pub to: MaybeEmpty<Address>,
/// Value.
pub value: Uint,
/// R.
pub r: Uint,
/// S.
pub s: Uint,
/// V.
pub v: Uint,
}
#[cfg(test)]
mod tests {
use serde_json;
use transaction::Transaction;
#[test]
fn transaction_deserialization() {
let s = r#"{
"data" : "0x",
"gasLimit" : "0xf388",
"gasPrice" : "0x09184e72a000",
"nonce" : "0x00",
"r" : "0x2c",
"s" : "0x04",
"to" : "",
"v" : "0x1b",
"value" : "0x00"
}"#;
let _deserialized: Transaction = serde_json::from_str(s).unwrap();
// TODO: validate all fields
}
}

View File

@@ -0,0 +1,82 @@
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
// This file is part of OpenEthereum.
// OpenEthereum 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.
// OpenEthereum 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 OpenEthereum. If not, see <http://www.gnu.org/licenses/>.
//! Transaction test deserialization.
use bytes::Bytes;
use hash::{Address, H256};
use spec::ForkSpec;
use std::collections::BTreeMap;
/// Transaction test deserialization.
#[derive(Debug, Deserialize)]
pub struct TransactionTest {
pub rlp: Bytes,
pub _info: ::serde::de::IgnoredAny,
#[serde(flatten)]
pub post_state: BTreeMap<ForkSpec, PostState>,
}
/// TransactionTest post state.
#[derive(Debug, PartialEq, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct PostState {
/// Transaction sender.
pub sender: Option<Address>,
/// Transaction hash.
pub hash: Option<H256>,
}
#[cfg(test)]
mod tests {
use serde_json;
use transaction::TransactionTest;
#[test]
fn transaction_deserialization() {
let s = r#"{
"Byzantium" : {
"hash" : "4782cb5edcaeda1f0aef204b161214f124cefade9e146245183abbb9ca01bca5",
"sender" : "2ea991808ba979ba103147edfd72304ebd95c028"
},
"Constantinople" : {
"hash" : "4782cb5edcaeda1f0aef204b161214f124cefade9e146245183abbb9ca01bca5",
"sender" : "2ea991808ba979ba103147edfd72304ebd95c028"
},
"EIP150" : {
},
"EIP158" : {
"hash" : "4782cb5edcaeda1f0aef204b161214f124cefade9e146245183abbb9ca01bca5",
"sender" : "2ea991808ba979ba103147edfd72304ebd95c028"
},
"Frontier" : {
},
"Homestead" : {
},
"_info" : {
"comment" : "",
"filledwith" : "cpp-1.3.0+commit.1829957d.Linux.g++",
"lllcversion" : "Version: 0.4.18-develop.2017.10.11+commit.81f9f86c.Linux.g++",
"source" : "src/TransactionTestsFiller/ttVValue/V_equals37Filler.json",
"sourceHash" : "89ef69312d4c0b4e3742da501263d23d2a64f180258ac93940997ac6a17b9b19"
},
"rlp" : "0xf865808698852840a46f82d6d894095e7baea6a6c7c4c2dfeb977efac326af552d87808025a098ff921201554726367d2be8c804a7ff89ccf285ebc57dff8ae4c44b9c19ac4aa01887321be575c8095f789dd4c743dfe42c1820f9231f98a962b210e3ac2452a3"
}"#;
let _deserialized: TransactionTest = serde_json::from_str(s).unwrap();
// TODO: validate all fields
}
}

View File

@@ -0,0 +1,179 @@
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
// This file is part of OpenEthereum.
// OpenEthereum 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.
// OpenEthereum 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 OpenEthereum. If not, see <http://www.gnu.org/licenses/>.
//! Trie test input deserialization.
use bytes::Bytes;
use serde::{
de::{Error as ErrorTrait, MapAccess, SeqAccess, Visitor},
Deserialize, Deserializer,
};
use std::{collections::BTreeMap, fmt, str::FromStr};
/// Trie test input.
#[derive(Debug, PartialEq)]
pub struct Input {
/// Input params.
pub data: BTreeMap<Bytes, Option<Bytes>>,
}
impl<'a> Deserialize<'a> for Input {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'a>,
{
deserializer.deserialize_any(InputVisitor)
}
}
struct InputVisitor;
impl<'a> Visitor<'a> for InputVisitor {
type Value = Input;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
write!(formatter, "a map of bytes into bytes")
}
fn visit_map<V>(self, mut visitor: V) -> Result<Self::Value, V::Error>
where
V: MapAccess<'a>,
{
let mut result = BTreeMap::new();
loop {
let key_str: Option<String> = visitor.next_key()?;
let key = match key_str {
Some(ref k) if k.starts_with("0x") => {
Bytes::from_str(k).map_err(V::Error::custom)?
}
Some(k) => Bytes::new(k.into_bytes()),
None => {
break;
}
};
let val_str: Option<String> = visitor.next_value()?;
let val = match val_str {
Some(ref v) if v.starts_with("0x") => {
Some(Bytes::from_str(v).map_err(V::Error::custom)?)
}
Some(v) => Some(Bytes::new(v.into_bytes())),
None => None,
};
result.insert(key, val);
}
let input = Input { data: result };
Ok(input)
}
fn visit_seq<V>(self, mut visitor: V) -> Result<Self::Value, V::Error>
where
V: SeqAccess<'a>,
{
let mut result = BTreeMap::new();
loop {
let keyval: Option<Vec<Option<String>>> = visitor.next_element()?;
let keyval = match keyval {
Some(k) => k,
_ => {
break;
}
};
if keyval.len() != 2 {
return Err(V::Error::custom("Invalid key value pair."));
}
let ref key_str: Option<String> = keyval[0];
let ref val_str: Option<String> = keyval[1];
let key = match *key_str {
Some(ref k) if k.starts_with("0x") => {
Bytes::from_str(k).map_err(V::Error::custom)?
}
Some(ref k) => Bytes::new(k.clone().into_bytes()),
None => {
break;
}
};
let val = match *val_str {
Some(ref v) if v.starts_with("0x") => {
Some(Bytes::from_str(v).map_err(V::Error::custom)?)
}
Some(ref v) => Some(Bytes::new(v.clone().into_bytes())),
None => None,
};
result.insert(key, val);
}
let input = Input { data: result };
Ok(input)
}
}
#[cfg(test)]
mod tests {
use super::Input;
use bytes::Bytes;
use serde_json;
use std::collections::BTreeMap;
#[test]
fn input_deserialization_from_map() {
let s = r#"{
"0x0045" : "0x0123456789",
"be" : "e",
"0x0a" : null
}"#;
let input: Input = serde_json::from_str(s).unwrap();
let mut map = BTreeMap::new();
map.insert(
Bytes::new(vec![0, 0x45]),
Some(Bytes::new(vec![0x01, 0x23, 0x45, 0x67, 0x89])),
);
map.insert(Bytes::new(vec![0x62, 0x65]), Some(Bytes::new(vec![0x65])));
map.insert(Bytes::new(vec![0x0a]), None);
assert_eq!(input.data, map);
}
#[test]
fn input_deserialization_from_array() {
let s = r#"[
["0x0045", "0x0123456789"],
["be", "e"],
["0x0a", null]
]"#;
let input: Input = serde_json::from_str(s).unwrap();
let mut map = BTreeMap::new();
map.insert(
Bytes::new(vec![0, 0x45]),
Some(Bytes::new(vec![0x01, 0x23, 0x45, 0x67, 0x89])),
);
map.insert(Bytes::new(vec![0x62, 0x65]), Some(Bytes::new(vec![0x65])));
map.insert(Bytes::new(vec![0x0a]), None);
assert_eq!(input.data, map);
}
}

View File

@@ -0,0 +1,23 @@
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
// This file is part of OpenEthereum.
// OpenEthereum 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.
// OpenEthereum 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 OpenEthereum. If not, see <http://www.gnu.org/licenses/>.
//! Trie test deserialization.
mod input;
mod test;
mod trie;
pub use self::{input::Input, test::Test, trie::Trie};

View File

@@ -0,0 +1,44 @@
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
// This file is part of OpenEthereum.
// OpenEthereum 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.
// OpenEthereum 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 OpenEthereum. If not, see <http://www.gnu.org/licenses/>.
//! TransactionTest test deserializer.
use serde_json::{self, Error};
use std::{collections::BTreeMap, io::Read};
use trie::Trie;
/// TransactionTest test deserializer.
#[derive(Debug, PartialEq, Deserialize)]
pub struct Test(BTreeMap<String, Trie>);
impl IntoIterator for Test {
type Item = <BTreeMap<String, Trie> as IntoIterator>::Item;
type IntoIter = <BTreeMap<String, Trie> as IntoIterator>::IntoIter;
fn into_iter(self) -> Self::IntoIter {
self.0.into_iter()
}
}
impl Test {
/// Loads test from json.
pub fn load<R>(reader: R) -> Result<Self, Error>
where
R: Read,
{
serde_json::from_reader(reader)
}
}

View File

@@ -0,0 +1,30 @@
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
// This file is part of OpenEthereum.
// OpenEthereum 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.
// OpenEthereum 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 OpenEthereum. If not, see <http://www.gnu.org/licenses/>.
//! Trie test deserialization.
use hash::H256;
use trie::Input;
/// Trie test deserialization.
#[derive(Debug, Deserialize, PartialEq)]
pub struct Trie {
/// Trie test input.
#[serde(rename = "in")]
pub input: Input,
/// Trie root hash.
pub root: H256,
}

176
crates/ethjson/src/uint.rs Normal file
View File

@@ -0,0 +1,176 @@
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
// This file is part of OpenEthereum.
// OpenEthereum 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.
// OpenEthereum 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 OpenEthereum. If not, see <http://www.gnu.org/licenses/>.
//! Lenient uint json deserialization for test json files.
use ethereum_types::U256;
use serde::{
de::{Error, Unexpected, Visitor},
Deserialize, Deserializer, Serialize, Serializer,
};
use std::{fmt, str::FromStr};
/// Lenient uint json deserialization for test json files.
#[derive(Default, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy)]
pub struct Uint(pub U256);
impl Into<U256> for Uint {
fn into(self) -> U256 {
self.0
}
}
impl Into<u64> for Uint {
fn into(self) -> u64 {
u64::from(self.0)
}
}
impl Into<usize> for Uint {
fn into(self) -> usize {
// TODO: clean it after util conversions refactored.
u64::from(self.0) as usize
}
}
impl Into<u8> for Uint {
fn into(self) -> u8 {
u64::from(self.0) as u8
}
}
impl Serialize for Uint {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
self.0.to_string().serialize(serializer)
}
}
impl<'a> Deserialize<'a> for Uint {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'a>,
{
deserializer.deserialize_any(UintVisitor)
}
}
struct UintVisitor;
impl<'a> Visitor<'a> for UintVisitor {
type Value = Uint;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
write!(formatter, "a hex encoded or decimal uint")
}
fn visit_u64<E>(self, value: u64) -> Result<Self::Value, E>
where
E: Error,
{
Ok(Uint(U256::from(value)))
}
fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
where
E: Error,
{
let value = match value.len() {
0 => U256::from(0),
2 if value.starts_with("0x") => U256::from(0),
_ if value.starts_with("0x") => U256::from_str(&value[2..]).map_err(|e| {
Error::custom(format!("Invalid hex value {}: {}", value, e).as_str())
})?,
_ => U256::from_dec_str(value).map_err(|e| {
Error::custom(format!("Invalid decimal value {}: {:?}", value, e).as_str())
})?,
};
Ok(Uint(value))
}
fn visit_string<E>(self, value: String) -> Result<Self::Value, E>
where
E: Error,
{
self.visit_str(value.as_ref())
}
}
/// Deserialize and validate that the value is non-zero
pub fn validate_non_zero<'de, D>(d: D) -> Result<Uint, D::Error>
where
D: Deserializer<'de>,
{
let value = Uint::deserialize(d)?;
if value == Uint(U256::from(0)) {
return Err(Error::invalid_value(
Unexpected::Unsigned(value.into()),
&"a non-zero value",
));
}
Ok(value)
}
/// Deserialize and validate that the value is non-zero
pub fn validate_optional_non_zero<'de, D>(d: D) -> Result<Option<Uint>, D::Error>
where
D: Deserializer<'de>,
{
let value: Option<Uint> = Option::deserialize(d)?;
if let Some(value) = value {
if value == Uint(U256::from(0)) {
return Err(Error::invalid_value(
Unexpected::Unsigned(value.into()),
&"a non-zero value",
));
}
}
Ok(value)
}
#[cfg(test)]
mod test {
use ethereum_types::U256;
use serde_json;
use uint::Uint;
#[test]
fn uint_deserialization() {
let s = r#"["0xa", "10", "", "0x", 0]"#;
let deserialized: Vec<Uint> = serde_json::from_str(s).unwrap();
assert_eq!(
deserialized,
vec![
Uint(U256::from(10)),
Uint(U256::from(10)),
Uint(U256::from(0)),
Uint(U256::from(0)),
Uint(U256::from(0))
]
);
}
#[test]
fn uint_into() {
assert_eq!(U256::from(10), Uint(U256::from(10)).into());
}
}

View File

@@ -0,0 +1,93 @@
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
// This file is part of OpenEthereum.
// OpenEthereum 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.
// OpenEthereum 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 OpenEthereum. If not, see <http://www.gnu.org/licenses/>.
//! Vm call deserialization.
use bytes::Bytes;
use hash::Address;
use maybe::MaybeEmpty;
use uint::Uint;
/// Vm call deserialization.
#[derive(Debug, PartialEq, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Call {
/// Call data.
pub data: Bytes,
/// Call destination.
pub destination: MaybeEmpty<Address>,
/// Gas limit.
pub gas_limit: Uint,
/// Call value.
pub value: Uint,
}
#[cfg(test)]
mod tests {
use ethereum_types::{H160 as Hash160, U256};
use hash::Address;
use maybe::MaybeEmpty;
use serde_json;
use std::str::FromStr;
use uint::Uint;
use vm::Call;
#[test]
fn call_deserialization_empty_dest() {
let s = r#"{
"data" : "0x1111222233334444555566667777888899990000aaaabbbbccccddddeeeeffff",
"destination" : "",
"gasLimit" : "0x1748766aa5",
"value" : "0x00"
}"#;
let call: Call = serde_json::from_str(s).unwrap();
assert_eq!(
&call.data[..],
&[
0x11, 0x11, 0x22, 0x22, 0x33, 0x33, 0x44, 0x44, 0x55, 0x55, 0x66, 0x66, 0x77, 0x77,
0x88, 0x88, 0x99, 0x99, 0x00, 0x00, 0xaa, 0xaa, 0xbb, 0xbb, 0xcc, 0xcc, 0xdd, 0xdd,
0xee, 0xee, 0xff, 0xff
]
);
assert_eq!(call.destination, MaybeEmpty::None);
assert_eq!(call.gas_limit, Uint(U256::from(0x1748766aa5u64)));
assert_eq!(call.value, Uint(U256::from(0)));
}
#[test]
fn call_deserialization_full_dest() {
let s = r#"{
"data" : "0x1234",
"destination" : "5a39ed1020c04d4d84539975b893a4e7c53eab6c",
"gasLimit" : "0x1748766aa5",
"value" : "0x00"
}"#;
let call: Call = serde_json::from_str(s).unwrap();
assert_eq!(&call.data[..], &[0x12, 0x34]);
assert_eq!(
call.destination,
MaybeEmpty::Some(Address(
Hash160::from_str("5a39ed1020c04d4d84539975b893a4e7c53eab6c").unwrap()
))
);
assert_eq!(call.gas_limit, Uint(U256::from(0x1748766aa5u64)));
assert_eq!(call.value, Uint(U256::from(0)));
}
}

View File

@@ -0,0 +1,58 @@
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
// This file is part of OpenEthereum.
// OpenEthereum 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.
// OpenEthereum 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 OpenEthereum. If not, see <http://www.gnu.org/licenses/>.
//! Vm environment.
use hash::Address;
use uint::Uint;
/// Vm environment.
#[derive(Debug, PartialEq, Deserialize)]
pub struct Env {
/// Address.
#[serde(rename = "currentCoinbase")]
pub author: Address,
/// Difficulty
#[serde(rename = "currentDifficulty")]
pub difficulty: Uint,
/// Gas limit.
#[serde(rename = "currentGasLimit")]
pub gas_limit: Uint,
/// Number.
#[serde(rename = "currentNumber")]
pub number: Uint,
/// Timestamp.
#[serde(rename = "currentTimestamp")]
pub timestamp: Uint,
}
#[cfg(test)]
mod tests {
use serde_json;
use vm::Env;
#[test]
fn env_deserialization() {
let s = r#"{
"currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba",
"currentDifficulty" : "0x0100",
"currentGasLimit" : "0x0f4240",
"currentNumber" : "0x00",
"currentTimestamp" : "0x01"
}"#;
let _deserialized: Env = serde_json::from_str(s).unwrap();
// TODO: validate all fields
}
}

View File

@@ -0,0 +1,25 @@
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
// This file is part of OpenEthereum.
// OpenEthereum 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.
// OpenEthereum 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 OpenEthereum. If not, see <http://www.gnu.org/licenses/>.
//! Vm test loader.
pub mod call;
pub mod env;
pub mod test;
pub mod transaction;
pub mod vm;
pub use self::{call::Call, env::Env, test::Test, transaction::Transaction, vm::Vm};

View File

@@ -0,0 +1,44 @@
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
// This file is part of OpenEthereum.
// OpenEthereum 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.
// OpenEthereum 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 OpenEthereum. If not, see <http://www.gnu.org/licenses/>.
//! Vm test deserializer.
use serde_json::{self, Error};
use std::{collections::BTreeMap, io::Read};
use vm::Vm;
/// Vm test deserializer.
#[derive(Debug, PartialEq, Deserialize)]
pub struct Test(BTreeMap<String, Vm>);
impl IntoIterator for Test {
type Item = <BTreeMap<String, Vm> as IntoIterator>::Item;
type IntoIter = <BTreeMap<String, Vm> as IntoIterator>::IntoIter;
fn into_iter(self) -> Self::IntoIter {
self.0.into_iter()
}
}
impl Test {
/// Loads test from json.
pub fn load<R>(reader: R) -> Result<Self, Error>
where
R: Read,
{
serde_json::from_reader(reader)
}
}

View File

@@ -0,0 +1,64 @@
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
// This file is part of OpenEthereum.
// OpenEthereum 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.
// OpenEthereum 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 OpenEthereum. If not, see <http://www.gnu.org/licenses/>.
//! Executed transaction.
use bytes::Bytes;
use hash::Address;
use uint::Uint;
/// Executed transaction.
#[derive(Debug, PartialEq, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Transaction {
/// Contract address.
pub address: Address,
/// Transaction sender.
#[serde(rename = "caller")]
pub sender: Address,
/// Contract code.
pub code: Bytes,
/// Input data.
pub data: Bytes,
/// Gas.
pub gas: Uint,
/// Gas price.
pub gas_price: Uint,
/// Transaction origin.
pub origin: Address,
/// Sent value.
pub value: Uint,
}
#[cfg(test)]
mod tests {
use serde_json;
use vm::Transaction;
#[test]
fn transaction_deserialization() {
let s = r#"{
"address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6",
"caller" : "cd1722f2947def4cf144679da39c4c32bdc35681",
"code" : "0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01600055",
"data" : "0x",
"gas" : "0x0186a0",
"gasPrice" : "0x5af3107a4000",
"origin" : "cd1722f2947def4cf144679da39c4c32bdc35681",
"value" : "0x0de0b6b3a7640000"
}"#;
let _deserialized: Transaction = serde_json::from_str(s).unwrap();
}
}

113
crates/ethjson/src/vm/vm.rs Normal file
View File

@@ -0,0 +1,113 @@
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
// This file is part of OpenEthereum.
// OpenEthereum 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.
// OpenEthereum 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 OpenEthereum. If not, see <http://www.gnu.org/licenses/>.
//! Vm execution env.
use blockchain::State;
use bytes::Bytes;
use hash::H256;
use uint::Uint;
use vm::{Call, Env, Transaction};
/// Represents vm execution environment before and after execution of transaction.
#[derive(Debug, PartialEq, Deserialize)]
pub struct Vm {
/// Contract calls made internaly by executed transaction.
#[serde(rename = "callcreates")]
pub calls: Option<Vec<Call>>,
/// Env info.
pub env: Env,
/// Executed transaction
#[serde(rename = "exec")]
pub transaction: Transaction,
/// Gas left after transaction execution.
#[serde(rename = "gas")]
pub gas_left: Option<Uint>,
/// Hash of logs created during execution of transaction.
pub logs: Option<H256>,
/// Transaction output.
#[serde(rename = "out")]
pub output: Option<Bytes>,
/// Post execution vm state.
#[serde(rename = "post")]
pub post_state: Option<State>,
/// Pre execution vm state.
#[serde(rename = "pre")]
pub pre_state: State,
}
impl Vm {
/// Returns true if transaction execution run out of gas.
pub fn out_of_gas(&self) -> bool {
self.calls.is_none()
}
}
#[cfg(test)]
mod tests {
use serde_json;
use vm::Vm;
#[test]
fn vm_deserialization() {
let s = r#"{
"callcreates" : [
],
"env" : {
"currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba",
"currentDifficulty" : "0x0100",
"currentGasLimit" : "0x0f4240",
"currentNumber" : "0x00",
"currentTimestamp" : "0x01"
},
"exec" : {
"address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6",
"caller" : "cd1722f2947def4cf144679da39c4c32bdc35681",
"code" : "0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01600055",
"data" : "0x",
"gas" : "0x0186a0",
"gasPrice" : "0x5af3107a4000",
"origin" : "cd1722f2947def4cf144679da39c4c32bdc35681",
"value" : "0x0de0b6b3a7640000"
},
"gas" : "0x013874",
"logs" : "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
"out" : "0x",
"network" : "Frontier",
"post" : {
"0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : {
"balance" : "0x0de0b6b3a7640000",
"code" : "0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01600055",
"nonce" : "0x00",
"storage" : {
"0x00" : "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe"
}
}
},
"pre" : {
"0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : {
"balance" : "0x0de0b6b3a7640000",
"code" : "0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01600055",
"nonce" : "0x00",
"storage" : {
}
}
}
}"#;
let _deserialized: Vm = serde_json::from_str(s).unwrap();
// TODO: validate all fields
}
}