Big folder refactor
This commit is contained in:
54
crates/ethjson/src/blockchain/account.rs
Normal file
54
crates/ethjson/src/blockchain/account.rs
Normal 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
|
||||
}
|
||||
}
|
||||
74
crates/ethjson/src/blockchain/block.rs
Normal file
74
crates/ethjson/src/blockchain/block.rs
Normal 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
|
||||
}
|
||||
}
|
||||
202
crates/ethjson/src/blockchain/blockchain.rs
Normal file
202
crates/ethjson/src/blockchain/blockchain.rs
Normal 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
|
||||
}
|
||||
}
|
||||
93
crates/ethjson/src/blockchain/header.rs
Normal file
93
crates/ethjson/src/blockchain/header.rs
Normal 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
|
||||
}
|
||||
}
|
||||
35
crates/ethjson/src/blockchain/mod.rs
Normal file
35
crates/ethjson/src/blockchain/mod.rs
Normal 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,
|
||||
};
|
||||
76
crates/ethjson/src/blockchain/state.rs
Normal file
76
crates/ethjson/src/blockchain/state.rs
Normal 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()
|
||||
}
|
||||
}
|
||||
}
|
||||
44
crates/ethjson/src/blockchain/test.rs
Normal file
44
crates/ethjson/src/blockchain/test.rs
Normal 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)
|
||||
}
|
||||
}
|
||||
34
crates/ethjson/src/blockchain/transaction.rs
Normal file
34
crates/ethjson/src/blockchain/transaction.rs
Normal 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
130
crates/ethjson/src/bytes.rs
Normal 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
148
crates/ethjson/src/hash.rs
Normal 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
41
crates/ethjson/src/lib.rs
Normal 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
120
crates/ethjson/src/maybe.rs
Normal 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()
|
||||
))
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
||||
168
crates/ethjson/src/spec/account.rs
Normal file
168
crates/ethjson/src/spec/account.rs
Normal 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);
|
||||
}
|
||||
}
|
||||
114
crates/ethjson/src/spec/authority_round.rs
Normal file
114
crates/ethjson/src/spec/authority_round.rs
Normal 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()))
|
||||
);
|
||||
}
|
||||
}
|
||||
68
crates/ethjson/src/spec/basic_authority.rs
Normal file
68
crates/ethjson/src/spec/basic_authority.rs
Normal 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);
|
||||
}
|
||||
}
|
||||
392
crates/ethjson/src/spec/builtin.rs
Normal file
392
crates/ethjson/src/spec/builtin.rs
Normal 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{}),
|
||||
}
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
||||
55
crates/ethjson/src/spec/clique.rs
Normal file
55
crates/ethjson/src/spec/clique.rs
Normal 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));
|
||||
}
|
||||
}
|
||||
150
crates/ethjson/src/spec/engine.rs
Normal file
150
crates/ethjson/src/spec/engine.rs
Normal 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!(),
|
||||
};
|
||||
}
|
||||
}
|
||||
263
crates/ethjson/src/spec/ethash.rs
Normal file
263
crates/ethjson/src/spec/ethash.rs
Normal 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();
|
||||
}
|
||||
}
|
||||
115
crates/ethjson/src/spec/genesis.rs
Normal file
115
crates/ethjson/src/spec/genesis.rs
Normal 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()
|
||||
),
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
35
crates/ethjson/src/spec/instant_seal.rs
Normal file
35
crates/ethjson/src/spec/instant_seal.rs
Normal 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,
|
||||
}
|
||||
51
crates/ethjson/src/spec/mod.rs
Normal file
51
crates/ethjson/src/spec/mod.rs
Normal 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,
|
||||
};
|
||||
61
crates/ethjson/src/spec/null_engine.rs
Normal file
61
crates/ethjson/src/spec/null_engine.rs
Normal 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)))
|
||||
);
|
||||
}
|
||||
}
|
||||
207
crates/ethjson/src/spec/params.rs
Normal file
207
crates/ethjson/src/spec/params.rs
Normal 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();
|
||||
}
|
||||
}
|
||||
141
crates/ethjson/src/spec/seal.rs
Normal file
141
crates/ethjson/src/spec/seal.rs
Normal 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"))]
|
||||
}));
|
||||
}
|
||||
}
|
||||
240
crates/ethjson/src/spec/spec.rs
Normal file
240
crates/ethjson/src/spec/spec.rs
Normal 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
|
||||
}
|
||||
}
|
||||
54
crates/ethjson/src/spec/state.rs
Normal file
54
crates/ethjson/src/spec/state.rs
Normal 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()
|
||||
}
|
||||
}
|
||||
93
crates/ethjson/src/spec/validator_set.rs
Normal file
93
crates/ethjson/src/spec/validator_set.rs
Normal 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),
|
||||
}
|
||||
}
|
||||
}
|
||||
52
crates/ethjson/src/state/log.rs
Normal file
52
crates/ethjson/src/state/log.rs
Normal 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
|
||||
}
|
||||
}
|
||||
26
crates/ethjson/src/state/mod.rs
Normal file
26
crates/ethjson/src/state/mod.rs
Normal 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;
|
||||
156
crates/ethjson/src/state/state.rs
Normal file
156
crates/ethjson/src/state/state.rs
Normal 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
|
||||
}
|
||||
}
|
||||
217
crates/ethjson/src/state/test.rs
Normal file
217
crates/ethjson/src/state/test.rs
Normal 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
|
||||
}
|
||||
}
|
||||
64
crates/ethjson/src/state/transaction.rs
Normal file
64
crates/ethjson/src/state/transaction.rs
Normal 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
|
||||
}
|
||||
}
|
||||
241
crates/ethjson/src/test/mod.rs
Normal file
241
crates/ethjson/src/test/mod.rs
Normal 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,
|
||||
}
|
||||
23
crates/ethjson/src/transaction/mod.rs
Normal file
23
crates/ethjson/src/transaction/mod.rs
Normal 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};
|
||||
44
crates/ethjson/src/transaction/test.rs
Normal file
44
crates/ethjson/src/transaction/test.rs
Normal 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)
|
||||
}
|
||||
}
|
||||
69
crates/ethjson/src/transaction/transaction.rs
Normal file
69
crates/ethjson/src/transaction/transaction.rs
Normal 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
|
||||
}
|
||||
}
|
||||
82
crates/ethjson/src/transaction/txtest.rs
Normal file
82
crates/ethjson/src/transaction/txtest.rs
Normal 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
|
||||
}
|
||||
}
|
||||
179
crates/ethjson/src/trie/input.rs
Normal file
179
crates/ethjson/src/trie/input.rs
Normal 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);
|
||||
}
|
||||
}
|
||||
23
crates/ethjson/src/trie/mod.rs
Normal file
23
crates/ethjson/src/trie/mod.rs
Normal 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};
|
||||
44
crates/ethjson/src/trie/test.rs
Normal file
44
crates/ethjson/src/trie/test.rs
Normal 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)
|
||||
}
|
||||
}
|
||||
30
crates/ethjson/src/trie/trie.rs
Normal file
30
crates/ethjson/src/trie/trie.rs
Normal 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
176
crates/ethjson/src/uint.rs
Normal 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());
|
||||
}
|
||||
}
|
||||
93
crates/ethjson/src/vm/call.rs
Normal file
93
crates/ethjson/src/vm/call.rs
Normal 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)));
|
||||
}
|
||||
}
|
||||
58
crates/ethjson/src/vm/env.rs
Normal file
58
crates/ethjson/src/vm/env.rs
Normal 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
|
||||
}
|
||||
}
|
||||
25
crates/ethjson/src/vm/mod.rs
Normal file
25
crates/ethjson/src/vm/mod.rs
Normal 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};
|
||||
44
crates/ethjson/src/vm/test.rs
Normal file
44
crates/ethjson/src/vm/test.rs
Normal 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)
|
||||
}
|
||||
}
|
||||
64
crates/ethjson/src/vm/transaction.rs
Normal file
64
crates/ethjson/src/vm/transaction.rs
Normal 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
113
crates/ethjson/src/vm/vm.rs
Normal 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
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user