vapjson/spec/
spec.rs

1// Copyright 2015-2020 Parity Technologies (UK) Ltd.
2// This file is part of Tetsy Vapory.
3
4// Tetsy Vapory is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8
9// Tetsy Vapory is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12// GNU General Public License for more details.
13
14// You should have received a copy of the GNU General Public License
15// along with Tetsy Vapory.  If not, see <http://www.gnu.org/licenses/>.
16
17//! Spec deserialization.
18
19use std::io::Read;
20use crate::spec::{Params, Genesis, Engine, State, HardcodedSync};
21use serde::Deserialize;
22use serde_json::Error;
23
24/// Fork spec definition
25#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Deserialize)]
26pub enum ForkSpec {
27	/// EIP 150 Tangerine Whistle: Gas cost changes for IO-heavy operations (#2,463,000, 2016-10-18)
28	EIP150,
29	/// EIP 158/EIP 161 Spurious Dragon: State trie clearing (#2,675,000, 2016-11-22)
30	EIP158,
31	/// Frontier (#1, 2015-07-30)
32	Frontier,
33	/// Homestead (#1,150,000, 2016-03-14)
34	Homestead,
35	/// Byzantium Metropolis phase 1 (#4,370,000, 2017-10-16)
36	Byzantium,
37	/// Constantinople Metropolis phase 2 (#7,280,000, 2019-02-28)
38	Constantinople,
39	/// Constantinople transition test-net
40	ConstantinopleFix,
41	/// Istanbul (To be announced)
42	Istanbul,
43	/// Byzantium transition test-net
44	EIP158ToByzantiumAt5,
45	/// Homestead transition test-net
46	FrontierToHomesteadAt5,
47	/// Homestead transition test-net
48	HomesteadToDaoAt5,
49	/// EIP158/EIP161 transition test-net
50	HomesteadToEIP150At5,
51}
52
53/// Spec deserialization.
54#[derive(Debug, PartialEq, Deserialize)]
55#[serde(deny_unknown_fields)]
56#[serde(rename_all = "camelCase")]
57pub struct Spec {
58	/// Spec name.
59	pub name: String,
60	/// Special fork name.
61	pub data_dir: Option<String>,
62	/// Engine.
63	pub engine: Engine,
64	/// Spec params.
65	pub params: Params,
66	/// Genesis header.
67	pub genesis: Genesis,
68	/// Genesis state.
69	pub accounts: State,
70	/// Boot nodes.
71	pub nodes: Option<Vec<String>>,
72	/// Hardcoded synchronization for the light client.
73	pub hardcoded_sync: Option<HardcodedSync>,
74}
75
76impl Spec {
77	/// Loads test from json.
78	pub fn load<R>(reader: R) -> Result<Self, Error> where R: Read {
79		serde_json::from_reader(reader)
80	}
81}
82
83#[cfg(test)]
84mod tests {
85	use super::Spec;
86
87	#[test]
88	fn should_error_on_unknown_fields() {
89		let s = r#"{
90		"name": "Morden",
91		"dataDir": "morden",
92		"engine": {
93			"Vapash": {
94				"params": {
95					"minimumDifficulty": "0x020000",
96					"difficultyBoundDivisor": "0x0800",
97					"durationLimit": "0x0d",
98					"homesteadTransition" : "0x",
99					"daoHardforkTransition": "0xffffffffffffffff",
100					"daoHardforkBeneficiary": "0x0000000000000000000000000000000000000000",
101					"daoHardforkAccounts": []
102				}
103			}
104		},
105		"params": {
106			"accountStartNonce": "0x0100000",
107			"maximumExtraDataSize": "0x20",
108			"minGasLimit": "0x1388",
109			"networkID" : "0x2",
110			"forkBlock": "0xffffffffffffffff",
111			"forkCanonHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
112			"gasLimitBoundDivisor": "0x20",
113			"unknownField": "0x0"
114		},
115		"genesis": {
116			"seal": {
117				"vapory": {
118					"mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
119					"nonce": "0x00006d6f7264656e"
120				}
121			},
122			"difficulty": "0x20000",
123			"author": "0x0000000000000000000000000000000000000000",
124			"timestamp": "0x00",
125			"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
126			"extraData": "0x",
127			"gasLimit": "0x2fefd8"
128		},
129		"nodes": [
130			"enode://b1217cbaa440e35ed471157123fe468e19e8b5ad5bedb4b1fdbcbdab6fb2f5ed3e95dd9c24a22a79fdb2352204cea207df27d92bfd21bfd41545e8b16f637499@104.44.138.37:30303"
131		],
132		"accounts": {
133			"0000000000000000000000000000000000000001": { "balance": "1", "nonce": "1048576", "builtin": { "name": "ecrecover", "pricing": { "linear": { "base": 3000, "word": 0 } } } },
134			"0000000000000000000000000000000000000002": { "balance": "1", "nonce": "1048576", "builtin": { "name": "sha256", "pricing": { "linear": { "base": 60, "word": 12 } } } },
135			"0000000000000000000000000000000000000003": { "balance": "1", "nonce": "1048576", "builtin": { "name": "ripemd160", "pricing": { "linear": { "base": 600, "word": 120 } } } },
136			"0000000000000000000000000000000000000004": { "balance": "1", "nonce": "1048576", "builtin": { "name": "identity", "pricing": { "linear": { "base": 15, "word": 3 } } } },
137			"102e61f5d8f9bc71d0ad4a084df4e65e05ce0e1c": { "balance": "1606938044258990275541962092341162602522202993782792835301376", "nonce": "1048576" }
138		},
139		"hardcodedSync": {
140			"header": "f901f9a0d405da4e66f1445d455195229624e133f5baafe72b5cf7b3c36c12c8146e98b7a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a05fb2b4bfdef7b314451cb138a534d225c922fc0e5fbe25e451142732c3e25c25a088d2ec6b9860aae1a2c3b299f72b6a5d70d7f7ba4722c78f2c49ba96273c2158a007c6fdfa8eea7e86b81f5b0fc0f78f90cc19f4aa60d323151e0cac660199e9a1b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302008003832fefba82524d84568e932a80a0a0349d8c3df71f1a48a9df7d03fd5f14aeee7d91332c009ecaff0a71ead405bd88ab4e252a7e8c2a23",
141			"totalDifficulty": "0x400000000",
142			"CHTs": [
143			"0x11bbe8db4e347b4e8c937c1c8370e4b5ed33adb3db69cbdb7a38e1e50b1b82fa",
144			"0xd7f8974fb5ac78d9ac099b9ad5018bedc2ce0a72dad1827a1709da30580f0544"
145			]
146		}
147		}"#;
148		let result: Result<Spec, _> = serde_json::from_str(s);
149		assert!(result.is_err());
150	}
151
152	#[test]
153	fn spec_deserialization() {
154		let s = r#"{
155		"name": "Morden",
156		"dataDir": "morden",
157		"engine": {
158			"Vapash": {
159				"params": {
160					"minimumDifficulty": "0x020000",
161					"difficultyBoundDivisor": "0x0800",
162					"durationLimit": "0x0d",
163					"homesteadTransition" : "0x",
164					"daoHardforkTransition": "0xffffffffffffffff",
165					"daoHardforkBeneficiary": "0x0000000000000000000000000000000000000000",
166					"daoHardforkAccounts": []
167				}
168			}
169		},
170		"params": {
171			"accountStartNonce": "0x0100000",
172			"maximumExtraDataSize": "0x20",
173			"minGasLimit": "0x1388",
174			"networkID" : "0x2",
175			"forkBlock": "0xffffffffffffffff",
176			"forkCanonHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
177			"gasLimitBoundDivisor": "0x20"
178		},
179		"genesis": {
180			"seal": {
181				"vapory": {
182					"mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
183					"nonce": "0x00006d6f7264656e"
184				}
185			},
186			"difficulty": "0x20000",
187			"author": "0x0000000000000000000000000000000000000000",
188			"timestamp": "0x00",
189			"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
190			"extraData": "0x",
191			"gasLimit": "0x2fefd8"
192		},
193		"nodes": [
194			"enode://b1217cbaa440e35ed471157123fe468e19e8b5ad5bedb4b1fdbcbdab6fb2f5ed3e95dd9c24a22a79fdb2352204cea207df27d92bfd21bfd41545e8b16f637499@104.44.138.37:30303"
195		],
196		"accounts": {
197			"0000000000000000000000000000000000000001": {
198				"balance": "1",
199				"nonce": "1048576",
200				"builtin": {
201					"name": "ecrecover",
202					"pricing": {
203						"linear": {
204							"base": 3000,
205							"word": 0
206						}
207					}
208				}
209			},
210			"0000000000000000000000000000000000000002": {
211				"balance": "1",
212				"nonce": "1048576",
213				"builtin": {
214					"name": "sha256",
215					"pricing": {
216						"linear": {
217							"base": 60,
218							"word": 12
219						}
220					}
221				}
222			},
223			"0000000000000000000000000000000000000003": {
224				"balance": "1",
225				"nonce": "1048576",
226				"builtin": {
227					"name": "ripemd160",
228					"pricing": {
229						"linear": {
230							"base": 600,
231							"word": 120
232						}
233					}
234				}
235			},
236			"0000000000000000000000000000000000000004": {
237				"balance": "1",
238				"nonce": "1048576",
239				"builtin": {
240					"name": "identity",
241					"pricing": {
242						"linear": {
243							"base": 15,
244							"word": 3
245						}
246					}
247				}
248			},
249			"102e61f5d8f9bc71d0ad4a084df4e65e05ce0e1c": { "balance": "1606938044258990275541962092341162602522202993782792835301376", "nonce": "1048576" }
250		},
251		"hardcodedSync": {
252			"header": "f901f9a0d405da4e66f1445d455195229624e133f5baafe72b5cf7b3c36c12c8146e98b7a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a05fb2b4bfdef7b314451cb138a534d225c922fc0e5fbe25e451142732c3e25c25a088d2ec6b9860aae1a2c3b299f72b6a5d70d7f7ba4722c78f2c49ba96273c2158a007c6fdfa8eea7e86b81f5b0fc0f78f90cc19f4aa60d323151e0cac660199e9a1b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302008003832fefba82524d84568e932a80a0a0349d8c3df71f1a48a9df7d03fd5f14aeee7d91332c009ecaff0a71ead405bd88ab4e252a7e8c2a23",
253			"totalDifficulty": "0x400000000",
254			"CHTs": [
255				"0x11bbe8db4e347b4e8c937c1c8370e4b5ed33adb3db69cbdb7a38e1e50b1b82fa",
256				"0xd7f8974fb5ac78d9ac099b9ad5018bedc2ce0a72dad1827a1709da30580f0544"
257			]
258		}
259		}"#;
260		let _deserialized: Spec = serde_json::from_str(s).unwrap();
261		// TODO: validate all fields
262	}
263}