// Copyright 2015-2018 Parity Technologies (UK) Ltd. // This file is part of Parity. // Parity is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // Parity is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // You should have received a copy of the GNU General Public License // along with Parity. If not, see . //! General test deserialization. use std::io::Read; use std::collections::BTreeMap; use uint::Uint; use bytes::Bytes; use hash::{Address, H256}; use spec::ForkSpec; use state::{Env, AccountState, Transaction}; use maybe::MaybeEmpty; use serde_json::{self, Error}; /// State test deserializer. #[derive(Debug, PartialEq, Deserialize)] pub struct Test(BTreeMap); impl IntoIterator for Test { type Item = as IntoIterator>::Item; type IntoIter = as IntoIterator>::IntoIter; fn into_iter(self) -> Self::IntoIter { self.0.into_iter() } } impl Test { /// Loads test from json. pub fn load(reader: R) -> Result 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>, /// Transaction. pub transaction: MultiTransaction, } /// State test transaction deserialization. #[derive(Debug, PartialEq, Deserialize)] pub struct MultiTransaction { /// Transaction data set. pub data: Vec, /// Gas limit set. #[serde(rename="gasLimit")] pub gas_limit: Vec, /// Gas price. #[serde(rename="gasPrice")] pub gas_price: Uint, /// Nonce. pub nonce: Uint, /// Secret key. #[serde(rename="secretKey")] pub secret: Option, /// To. pub to: MaybeEmpty
, /// Value set. pub value: Vec, } 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 serde_json; use super::{MultiTransaction, State}; #[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 } }