Merge branch 'master' into secretstore_kovan
This commit is contained in:
@@ -11,7 +11,6 @@ ansi_term = "0.9"
|
||||
bloomchain = "0.1"
|
||||
bn = { git = "https://github.com/paritytech/bn" }
|
||||
byteorder = "1.0"
|
||||
clippy = { version = "0.0.103", optional = true}
|
||||
common-types = { path = "types" }
|
||||
crossbeam = "0.2.9"
|
||||
ethash = { path = "../ethash" }
|
||||
@@ -83,6 +82,5 @@ evm-debug-tests = ["evm-debug"]
|
||||
slow-blocks = [] # Use SLOW_TX_DURATION="50" (compile time!) to track transactions over 50ms
|
||||
json-tests = []
|
||||
test-heavy = []
|
||||
dev = ["clippy"]
|
||||
default = []
|
||||
benches = []
|
||||
|
||||
@@ -32,7 +32,6 @@ macro_rules! overflowing {
|
||||
}}
|
||||
}
|
||||
|
||||
#[cfg_attr(feature="dev", allow(enum_variant_names))]
|
||||
enum Request<Cost: ::evm::CostType> {
|
||||
Gas(Cost),
|
||||
GasMem(Cost, Cost),
|
||||
@@ -101,7 +100,6 @@ impl<Gas: evm::CostType> Gasometer<Gas> {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(feature="dev", allow(cyclomatic_complexity))]
|
||||
/// Determine how much gas is used by the given instruction, given the machine's state.
|
||||
///
|
||||
/// We guarantee that the final element of the returned tuple (`provided`) will be `Some`
|
||||
|
||||
@@ -66,7 +66,6 @@ struct CodeReader<'a> {
|
||||
code: &'a [u8]
|
||||
}
|
||||
|
||||
#[cfg_attr(feature="dev", allow(len_without_is_empty))]
|
||||
impl<'a> CodeReader<'a> {
|
||||
|
||||
/// Create new code reader - starting at position 0.
|
||||
@@ -287,7 +286,6 @@ impl<Cost: CostType> Interpreter<Cost> {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(feature="dev", allow(too_many_arguments))]
|
||||
fn exec_instruction(
|
||||
&mut self,
|
||||
gas: Cost,
|
||||
|
||||
72
ethcore/res/ethereum/ellaism.json
Normal file
72
ethcore/res/ethereum/ellaism.json
Normal file
@@ -0,0 +1,72 @@
|
||||
{
|
||||
"name": "Ellaism",
|
||||
"dataDir": "ellaism",
|
||||
"engine": {
|
||||
"Ethash": {
|
||||
"params": {
|
||||
"minimumDifficulty": "0x020000",
|
||||
"difficultyBoundDivisor": "0x0800",
|
||||
"durationLimit": "0x0d",
|
||||
"blockReward": "0x4563918244F40000",
|
||||
"homesteadTransition": "0x0",
|
||||
"bombDefuseTransition": "0x0",
|
||||
"eip150Transition": "0x0",
|
||||
"eip160Transition": "0x0",
|
||||
"ecip1017EraRounds": 10000000,
|
||||
|
||||
"eip161abcTransition": "0x7fffffffffffffff",
|
||||
"eip161dTransition": "0x7fffffffffffffff"
|
||||
}
|
||||
}
|
||||
},
|
||||
"params": {
|
||||
"gasLimitBoundDivisor": "0x0400",
|
||||
"registrar": "0x3bb2bb5c6c9c9b7f4EF430b47Dc7e026310042ea",
|
||||
"accountStartNonce": "0x00",
|
||||
"maximumExtraDataSize": "0x20",
|
||||
"minGasLimit": "0x1388",
|
||||
"networkID": "0x40",
|
||||
"chainID": "0x40",
|
||||
"eip155Transition": "0x0",
|
||||
"eip98Transition": "0x7fffffffffffff",
|
||||
"eip86Transition": "0x7fffffffffffff"
|
||||
},
|
||||
"genesis": {
|
||||
"seal": {
|
||||
"ethereum": {
|
||||
"nonce": "0x0000000000000040",
|
||||
"mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000"
|
||||
}
|
||||
},
|
||||
"difficulty": "0x40000000",
|
||||
"author": "0x0000000000000000000000000000000000000000",
|
||||
"timestamp": "0x00",
|
||||
"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"extraData": "0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"gasLimit": "0x1388"
|
||||
},
|
||||
"nodes": [
|
||||
"enode://98b48cc7149326d00a57994ad55014a095a3e5cd4f0144cd7b034fb667d8e8017082bd90047d72c4403798b8ece11a33bd2e344d6500faba30889ebcfa5316fa@172.104.163.204:30303",
|
||||
"enode://834246cc2a7584df29ccdcf3b5366f118a0e291264980376769e809665a02c4caf0d68c43eecf8390dbeaf861823b05583807af0a62542a1f3f717046b958a76@45.77.106.33:30303",
|
||||
"enode://d1373d7187a20d695220fafb5746a289786bad92469d6bbe800f07572f8f444479f507cfcb8fcd8f5bee5dd44efb6185df4a1e4f1a7170408ada9876ef5b3fe4@178.79.189.58:30303",
|
||||
"enode://d8059dcb137cb52b8960ca82613eeba1d121105572decd8f1d3ea22b09070645eeab548d2a3cd2914f206e1331c7870bd2bd5a231ebac6b3d4886ec3b8e627e5@173.212.216.105:30303",
|
||||
"enode://5a89c8664d29a321fd4cb1b55b0f0be832ce376b5e7feb14a2073fdbd9bd7b7394169ed289dd991112b42ecfb74ea36e436bc72a1c99dcdb50d96eaf3b0ed254@213.136.91.42:30303",
|
||||
"enode://9215ad77bd081e35013cb42a8ceadff9d8e94a78fcc680dff1752a54e7484badff0904e331c4b40a68be593782e55acfd800f076d22f9d2832e8483733ade149@213.14.82.125:30303",
|
||||
"enode://07913818dafbadf44d4fc796fa414ec1d720ecfb087eff37efbe7134556658e92351559de788fa319c291e40b915cc26d902069d03bd935553d4efa688bdbbf8@45.32.19.37:30303",
|
||||
"enode://645a59b6e6e20ed8864767a1d0c731f89ae276ed4e04c4f10becce655532d95cbe1bc9e2da3f13a6564f9ca8fe46fab2781a380b3a89148bccac883d6068f684@45.77.159.123:30303",
|
||||
"enode://7c2f43b2e7fded9469917311574d267427e62cd12e1864effd15f31c1246e4e955463d843acaa37309693a515df7986cb6d160b7e85a4ca2779a798a72d90850@108.61.194.191:30303",
|
||||
"enode://5dd35866da95aea15211fb1f98684f6e8c4e355e6aa3cc17585680ed53fa164477b8c52cb6ca4b24ec4d80f3d48ff9212b53feb131d825c7945a3abaaf02d24d@178.79.189.58:60606",
|
||||
"enode://6c585c18024eb902ca093278af73b04863ac904caabc39ac2920c23532307c572ad92afd828a990c980d272b1f26307f2409cc97aec3ff9fe866732cae49a8c2@144.217.163.224:31337",
|
||||
"enode://edd90c4cc64528802ad52fd127d80b641ff80fd43fa5292fb111c8bd2914482dffee288fd1b0d26440c6b2c669b10a53cbcd37c895ba0d6194110e100a965b2d@188.166.179.159:30303",
|
||||
"enode://d19783546438e8bfc11a35457ff1f47871a2ce4801b9b2dbe7606321a9ce29007305497eb8c98d7ae9dc5a913ee5533c3691b1080f7066697c4276e6140d2eac@45.77.47.184:30303",
|
||||
"enode://13ed57615447bc9bf1da4e28249369babc00d2530d6c103c12350453e469a5e90cbcdb787c436977467f5864be6e64f2520180fc60b841c8c3daf84df9450190@104.207.152.17:30303",
|
||||
"enode://59c228a6a0939a0b53edf6924bc7bd1384652dc1da0777495acd0707975f485f54a77c7b2dcbeece9340a43ccd9c7ea70f0cdfe48936537d238b50e5cb5dc0b2@45.77.233.0:30303",
|
||||
"enode://9d960373335c1cc38ca696dea8f2893e2a071c8f21524f21e8aae22be032acc3b67797b1d21e866f9d832943ae7d9555b8466c6ab34f473d21e547114952df37@213.32.53.183:30303"
|
||||
],
|
||||
"accounts": {
|
||||
"0000000000000000000000000000000000000001": { "builtin": { "name": "ecrecover", "pricing": { "linear": { "base": 3000, "word": 0 } } } },
|
||||
"0000000000000000000000000000000000000002": { "builtin": { "name": "sha256", "pricing": { "linear": { "base": 60, "word": 12 } } } },
|
||||
"0000000000000000000000000000000000000003": { "builtin": { "name": "ripemd160", "pricing": { "linear": { "base": 600, "word": 120 } } } },
|
||||
"0000000000000000000000000000000000000004": { "builtin": { "name": "identity", "pricing": { "linear": { "base": 15, "word": 3 } } } }
|
||||
}
|
||||
}
|
||||
@@ -173,6 +173,11 @@
|
||||
"stateRoot": "0xd7f8974fb5ac78d9ac099b9ad5018bedc2ce0a72dad1827a1709da30580f0544"
|
||||
},
|
||||
"nodes": [
|
||||
"enode://5a62f19d35c0da8b576c9414568c728d4744e6e9d436c0f9db27456400011414f515871f13a6b8e0468534b5116cfe765d7630f680f1707a38467940a9f62511@45.55.33.62:30303",
|
||||
"enode://605e04a43b1156966b3a3b66b980c87b7f18522f7f712035f84576016be909a2798a438b2b17b1a8c58db314d88539a77419ca4be36148c086900fba487c9d39@188.166.255.12:30303",
|
||||
"enode://dc72806c3aa8fda207c8c018aba8d6cf143728b3628b6ded8d5e8cdeb8aa05cbd53f710ecd014c9a8f0d1e98f2874bff8afb15a229202f510a9c0258d1f6d109@159.203.210.80:30303",
|
||||
"enode://01f76fa0561eca2b9a7e224378dd854278735f1449793c46ad0c4e79e8775d080c21dcc455be391e90a98153c3b05dcc8935c8440de7b56fe6d67251e33f4e3c@51.15.42.252:30303",
|
||||
"enode://2c9059f05c352b29d559192fe6bca272d965c9f2290632a2cfda7f83da7d2634f3ec45ae3a72c54dd4204926fb8082dcf9686e0d7504257541c86fc8569bcf4b@163.172.171.38:30303",
|
||||
"enode://efe4f2493f4aff2d641b1db8366b96ddacfe13e7a6e9c8f8f8cf49f9cdba0fdf3258d8c8f8d0c5db529f8123c8f1d95f36d54d590ca1bb366a5818b9a4ba521c@163.172.187.252:30303",
|
||||
"enode://cd6611461840543d5b9c56fbf088736154c699c43973b3a1a32390cf27106f87e58a818a606ccb05f3866de95a4fe860786fea71bf891ea95f234480d3022aa3@163.172.157.114:30303",
|
||||
"enode://bcc7240543fe2cf86f5e9093d05753dd83343f8fda7bf0e833f65985c73afccf8f981301e13ef49c4804491eab043647374df1c4adf85766af88a624ecc3330e@136.243.154.244:30303",
|
||||
@@ -184,13 +189,7 @@
|
||||
"enode://a979fb575495b8d6db44f750317d0f4622bf4c2aa3365d6af7c284339968eef29b69ad0dce72a4d8db5ebb4968de0e3bec910127f134779fbcb0cb6d3331163c@52.16.188.185:30303",
|
||||
"enode://de471bccee3d042261d52e9bff31458daecc406142b401d4cd848f677479f73104b9fdeb090af9583d3391b7f10cb2ba9e26865dd5fca4fcdc0fb1e3b723c786@54.94.239.50:30303",
|
||||
"enode://1118980bf48b0a3640bdba04e0fe78b1add18e1cd99bf22d53daac1fd9972ad650df52176e7c7d89d1114cfef2bc23a2959aa54998a46afcf7d91809f0855082@52.74.57.123:30303",
|
||||
"enode://4cd540b2c3292e17cff39922e864094bf8b0741fcc8c5dcea14957e389d7944c70278d872902e3d0345927f621547efa659013c400865485ab4bfa0c6596936f@138.201.144.135:30303",
|
||||
|
||||
"enode://89d5dc2a81e574c19d0465f497c1af96732d1b61a41de89c2a37f35707689ac416529fae1038809852b235c2d30fd325abdc57c122feeefbeaaf802cc7e9580d@45.55.33.62:30303",
|
||||
"enode://605e04a43b1156966b3a3b66b980c87b7f18522f7f712035f84576016be909a2798a438b2b17b1a8c58db314d88539a77419ca4be36148c086900fba487c9d39@188.166.255.12:30303",
|
||||
"enode://016b20125f447a3b203a3cae953b2ede8ffe51290c071e7599294be84317635730c397b8ff74404d6be412d539ee5bb5c3c700618723d3b53958c92bd33eaa82@159.203.210.80:30303",
|
||||
"enode://01f76fa0561eca2b9a7e224378dd854278735f1449793c46ad0c4e79e8775d080c21dcc455be391e90a98153c3b05dcc8935c8440de7b56fe6d67251e33f4e3c@51.15.42.252:30303",
|
||||
"enode://8d91c8137890d29110b9463882f17ae4e279cd2c90cf56573187ed1c8546fca5f590a9f05e9f108eb1bd91767ed01ede4daad9e001b61727885eaa246ddb39c2@163.172.171.38:30303"
|
||||
"enode://4cd540b2c3292e17cff39922e864094bf8b0741fcc8c5dcea14957e389d7944c70278d872902e3d0345927f621547efa659013c400865485ab4bfa0c6596936f@138.201.144.135:30303"
|
||||
],
|
||||
"accounts": {
|
||||
"0000000000000000000000000000000000000001": { "builtin": { "name": "ecrecover", "pricing": { "linear": { "base": 3000, "word": 0 } } } },
|
||||
|
||||
@@ -12,19 +12,17 @@
|
||||
"0x00427feae2419c15b89d1c21af10d1b6650a4d3d",
|
||||
"0x4Ed9B08e6354C70fE6F8CB0411b0d3246b424d6c",
|
||||
"0x0020ee4Be0e2027d76603cB751eE069519bA81A1",
|
||||
|
||||
"0x0010f94b296a852aaac52ea6c5ac72e03afd032d",
|
||||
|
||||
"0x007733a1FE69CF3f2CF989F81C7b4cAc1693387A",
|
||||
"0x00E6d2b931F55a3f1701c7389d592a7778897879",
|
||||
"0x00e4a10650e5a6D6001C38ff8E64F97016a1645c",
|
||||
|
||||
"0x00a0a24b9f0e5ec7aa4c7389b8302fd0123194de"
|
||||
]
|
||||
},
|
||||
"validateScoreTransition": 1000000,
|
||||
"validateStepTransition": 1500000,
|
||||
"maximumUncleCount": 2
|
||||
"maximumUncleCountTransition": 5067000,
|
||||
"maximumUncleCount": 0
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -38,7 +36,11 @@
|
||||
"forkCanonHash": "0x0a66d93c2f727dca618fabaf70c39b37018c73d78b939d8b11efbbd09034778f",
|
||||
"validateReceiptsTransition" : 1000000,
|
||||
"eip155Transition": 1000000,
|
||||
"validateChainIdTransition": 1000000
|
||||
"validateChainIdTransition": 1000000,
|
||||
"eip140Transition": 5067000,
|
||||
"eip211Transition": 5067000,
|
||||
"eip214Transition": 5067000,
|
||||
"eip658Transition": 5067000
|
||||
},
|
||||
"genesis": {
|
||||
"seal": {
|
||||
@@ -55,13 +57,17 @@
|
||||
"0x0000000000000000000000000000000000000002": { "balance": "1", "builtin": { "name": "sha256", "pricing": { "linear": { "base": 60, "word": 12 } } } },
|
||||
"0x0000000000000000000000000000000000000003": { "balance": "1", "builtin": { "name": "ripemd160", "pricing": { "linear": { "base": 600, "word": 120 } } } },
|
||||
"0x0000000000000000000000000000000000000004": { "balance": "1", "builtin": { "name": "identity", "pricing": { "linear": { "base": 15, "word": 3 } } } },
|
||||
"0x0000000000000000000000000000000000000005": { "builtin": { "name": "modexp", "activate_at": 5067000, "pricing": { "modexp": { "divisor": 20 } } } },
|
||||
"0x0000000000000000000000000000000000000006": { "builtin": { "name": "alt_bn128_add", "activate_at": 5067000, "pricing": { "linear": { "base": 500, "word": 0 } } } },
|
||||
"0x0000000000000000000000000000000000000007": { "builtin": { "name": "alt_bn128_mul", "activate_at": 5067000, "pricing": { "linear": { "base": 40000, "word": 0 } } } },
|
||||
"0x0000000000000000000000000000000000000008": { "builtin": { "name": "alt_bn128_pairing", "activate_at": 5067000, "pricing": { "alt_bn128_pairing": { "base": 100000, "pair": 80000 } } } },
|
||||
"0x00521965e7bd230323c423d96c657db5b79d099f": { "balance": "1606938044258990275541962092341162602522202993782792835301376" }
|
||||
},
|
||||
"nodes": [
|
||||
"enode://0518a3d35d4a7b3e8c433e7ffd2355d84a1304ceb5ef349787b556197f0c87fad09daed760635b97d52179d645d3e6d16a37d2cc0a9945c2ddf585684beb39ac@40.68.248.100:30303",
|
||||
"enode://dcf984764db421fa0cd8dc7fc02ae378545723abb94d179f55325514cc30185eaea3dcefde6e358b7cdbe970c50b7c49e841618713a9a72d6f3f59ad9949ec6b@52.165.239.18:30303",
|
||||
"enode://56abaf065581a5985b8c5f4f88bd202526482761ba10be9bfdcd14846dd01f652ec33fde0f8c0fd1db19b59a4c04465681fcef50e11380ca88d25996191c52de@40.71.221.215:30303",
|
||||
"enode://d07827483dc47b368eaf88454fb04b41b7452cf454e194e2bd4c14f98a3278fed5d819dbecd0d010407fc7688d941ee1e58d4f9c6354d3da3be92f55c17d7ce3@52.166.117.77:30303",
|
||||
"enode://8fa162563a8e5a05eef3e1cd5abc5828c71344f7277bb788a395cce4a0e30baf2b34b92fe0b2dbbba2313ee40236bae2aab3c9811941b9f5a7e8e90aaa27ecba@52.165.239.18:30303",
|
||||
"enode://7e2e7f00784f516939f94e22bdc6cf96153603ca2b5df1c7cc0f90a38e7a2f218ffb1c05b156835e8b49086d11fdd1b3e2965be16baa55204167aa9bf536a4d9@52.243.47.56:30303",
|
||||
"enode://d51b3e98bf35addf2f1d0ea1ffc90483e24d7c60b0fb3be1701e818f3d6778c06e53fdec737a534fe222956296f9d6e909baa025916a94601897e5c7136a7d95@40.71.221.215:30303",
|
||||
"enode://419d42e300e8fd379ff6d045d93d7e66a091441e7b3c9f1d3d10088d8634ad37721e6bf86148f78c3f1b9f1360dc566ca8ee830b2d2079bc9f7171ea6152bb64@52.166.117.77:30303"
|
||||
"enode://0518a3d35d4a7b3e8c433e7ffd2355d84a1304ceb5ef349787b556197f0c87fad09daed760635b97d52179d645d3e6d16a37d2cc0a9945c2ddf585684beb39ac@40.68.248.100:30303"
|
||||
]
|
||||
}
|
||||
|
||||
Submodule ethcore/res/wasm-tests updated: d6185ea16e...d9d6133c1b
@@ -22,7 +22,6 @@ pub type LogBloom = ::log_entry::LogBloom;
|
||||
/// Constant 2048-bit datum for 0. Often used as a default.
|
||||
pub static ZERO_LOGBLOOM: LogBloom = ::bigint::hash::H2048([0x00; 256]);
|
||||
|
||||
#[cfg_attr(feature="dev", allow(enum_variant_names))]
|
||||
/// Semantic boolean for when a seal/signature is included.
|
||||
pub enum Seal {
|
||||
/// The seal/signature is included.
|
||||
|
||||
@@ -301,7 +301,6 @@ pub struct SealedBlock {
|
||||
}
|
||||
|
||||
impl<'x> OpenBlock<'x> {
|
||||
#[cfg_attr(feature="dev", allow(too_many_arguments))]
|
||||
/// Create a new `OpenBlock` ready for transaction pushing.
|
||||
pub fn new(
|
||||
engine: &'x EthEngine,
|
||||
@@ -380,8 +379,13 @@ impl<'x> OpenBlock<'x> {
|
||||
/// NOTE Will check chain constraints and the uncle number but will NOT check
|
||||
/// that the header itself is actually valid.
|
||||
pub fn push_uncle(&mut self, valid_uncle_header: Header) -> Result<(), BlockError> {
|
||||
if self.block.uncles.len() + 1 > self.engine.maximum_uncle_count() {
|
||||
return Err(BlockError::TooManyUncles(OutOfBounds{min: None, max: Some(self.engine.maximum_uncle_count()), found: self.block.uncles.len() + 1}));
|
||||
let max_uncles = self.engine.maximum_uncle_count(self.block.header().number());
|
||||
if self.block.uncles.len() + 1 > max_uncles {
|
||||
return Err(BlockError::TooManyUncles(OutOfBounds{
|
||||
min: None,
|
||||
max: Some(max_uncles),
|
||||
found: self.block.uncles.len() + 1,
|
||||
}));
|
||||
}
|
||||
// TODO: check number
|
||||
// TODO: check not a direct ancestor (use last_hashes for that)
|
||||
@@ -609,7 +613,6 @@ impl IsBlock for SealedBlock {
|
||||
}
|
||||
|
||||
/// Enact the block given by block header, transactions and uncles
|
||||
#[cfg_attr(feature="dev", allow(too_many_arguments))]
|
||||
pub fn enact(
|
||||
header: &Header,
|
||||
transactions: &[SignedTransaction],
|
||||
@@ -683,7 +686,6 @@ fn push_transactions(block: &mut OpenBlock, transactions: &[SignedTransaction])
|
||||
|
||||
// TODO [ToDr] Pass `PreverifiedBlock` by move, this will avoid unecessary allocation
|
||||
/// Enact the block given by `block_bytes` using `engine` on the database `db` with given `parent` block header
|
||||
#[cfg_attr(feature="dev", allow(too_many_arguments))]
|
||||
pub fn enact_verified(
|
||||
block: &PreverifiedBlock,
|
||||
engine: &EthEngine,
|
||||
@@ -726,7 +728,6 @@ mod tests {
|
||||
use transaction::SignedTransaction;
|
||||
|
||||
/// Enact the block given by `block_bytes` using `engine` on the database `db` with given `parent` block header
|
||||
#[cfg_attr(feature="dev", allow(too_many_arguments))]
|
||||
fn enact_bytes(
|
||||
block_bytes: &[u8],
|
||||
engine: &EthEngine,
|
||||
@@ -773,7 +774,6 @@ mod tests {
|
||||
}
|
||||
|
||||
/// Enact the block given by `block_bytes` using `engine` on the database `db` with given `parent` block header. Seal the block aferwards
|
||||
#[cfg_attr(feature="dev", allow(too_many_arguments))]
|
||||
fn enact_and_seal(
|
||||
block_bytes: &[u8],
|
||||
engine: &EthEngine,
|
||||
|
||||
@@ -970,7 +970,6 @@ impl BlockChain {
|
||||
self.cache_man.lock().note_used(CacheId::BlockDetails(block_hash));
|
||||
}
|
||||
|
||||
#[cfg_attr(feature="dev", allow(similar_names))]
|
||||
/// Inserts the block into backing cache database.
|
||||
/// Expects the block to be valid and already verified.
|
||||
/// If the block is already known, does nothing.
|
||||
@@ -1475,7 +1474,6 @@ impl BlockChain {
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
#![cfg_attr(feature="dev", allow(similar_names))]
|
||||
use std::sync::Arc;
|
||||
use rustc_hex::FromHex;
|
||||
use hash::keccak;
|
||||
@@ -1583,7 +1581,6 @@ mod tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg_attr(feature="dev", allow(cyclomatic_complexity))]
|
||||
fn test_find_uncles() {
|
||||
let mut canon_chain = ChainGenerator::default();
|
||||
let mut finalizer = BlockFinalizer::default();
|
||||
@@ -1793,7 +1790,6 @@ mod tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg_attr(feature="dev", allow(cyclomatic_complexity))]
|
||||
fn test_small_fork() {
|
||||
let mut canon_chain = ChainGenerator::default();
|
||||
let mut finalizer = BlockFinalizer::default();
|
||||
|
||||
@@ -1855,7 +1855,7 @@ impl MiningBlockChainClient for Client {
|
||||
let mut open_block = OpenBlock::new(
|
||||
engine,
|
||||
self.factories.clone(),
|
||||
false, // TODO: this will need to be parameterised once we want to do immediate mining insertion.
|
||||
self.tracedb.read().tracing_enabled(),
|
||||
self.state_db.lock().boxed_clone_canon(&h),
|
||||
best_header,
|
||||
self.build_last_hashes(h.clone()),
|
||||
@@ -1870,7 +1870,7 @@ impl MiningBlockChainClient for Client {
|
||||
.find_uncle_headers(&h, engine.maximum_uncle_age())
|
||||
.unwrap_or_else(Vec::new)
|
||||
.into_iter()
|
||||
.take(engine.maximum_uncle_count())
|
||||
.take(engine.maximum_uncle_count(open_block.header().number()))
|
||||
.foreach(|h| {
|
||||
open_block.push_uncle(h).expect("pushing maximum_uncle_count;
|
||||
open_block was just created;
|
||||
@@ -1885,7 +1885,7 @@ impl MiningBlockChainClient for Client {
|
||||
fn reopen_block(&self, block: ClosedBlock) -> OpenBlock {
|
||||
let engine = &*self.engine;
|
||||
let mut block = block.reopen(engine);
|
||||
let max_uncles = engine.maximum_uncle_count();
|
||||
let max_uncles = engine.maximum_uncle_count(block.header().number());
|
||||
if block.uncles().len() < max_uncles {
|
||||
let chain = self.chain.read();
|
||||
let h = chain.best_block_hash();
|
||||
|
||||
@@ -51,8 +51,12 @@ mod finality;
|
||||
|
||||
/// `AuthorityRound` params.
|
||||
pub struct AuthorityRoundParams {
|
||||
/// Time to wait before next block or authority switching.
|
||||
pub step_duration: Duration,
|
||||
/// Time to wait before next block or authority switching,
|
||||
/// in seconds.
|
||||
///
|
||||
/// Deliberately typed as u16 as too high of a value leads
|
||||
/// to slow block issuance.
|
||||
pub step_duration: u16,
|
||||
/// Starting step,
|
||||
pub start_step: Option<u64>,
|
||||
/// Valid validators.
|
||||
@@ -65,20 +69,30 @@ pub struct AuthorityRoundParams {
|
||||
pub immediate_transitions: bool,
|
||||
/// Block reward in base units.
|
||||
pub block_reward: U256,
|
||||
/// Number of accepted uncles transition block.
|
||||
pub maximum_uncle_count_transition: u64,
|
||||
/// Number of accepted uncles.
|
||||
pub maximum_uncle_count: usize,
|
||||
}
|
||||
|
||||
const U16_MAX: usize = ::std::u16::MAX as usize;
|
||||
|
||||
impl From<ethjson::spec::AuthorityRoundParams> for AuthorityRoundParams {
|
||||
fn from(p: ethjson::spec::AuthorityRoundParams) -> Self {
|
||||
let mut step_duration_usize: usize = p.step_duration.into();
|
||||
if step_duration_usize > U16_MAX {
|
||||
step_duration_usize = U16_MAX;
|
||||
warn!(target: "engine", "step_duration is too high ({}), setting it to {}", step_duration_usize, U16_MAX);
|
||||
}
|
||||
AuthorityRoundParams {
|
||||
step_duration: Duration::from_secs(p.step_duration.into()),
|
||||
step_duration: step_duration_usize as u16,
|
||||
validators: new_validator_set(p.validators),
|
||||
start_step: p.start_step.map(Into::into),
|
||||
validate_score_transition: p.validate_score_transition.map_or(0, Into::into),
|
||||
validate_step_transition: p.validate_step_transition.map_or(0, Into::into),
|
||||
immediate_transitions: p.immediate_transitions.unwrap_or(false),
|
||||
block_reward: p.block_reward.map_or_else(Default::default, Into::into),
|
||||
maximum_uncle_count_transition: p.maximum_uncle_count_transition.map_or(0, Into::into),
|
||||
maximum_uncle_count: p.maximum_uncle_count.map_or(0, Into::into),
|
||||
}
|
||||
}
|
||||
@@ -89,26 +103,47 @@ impl From<ethjson::spec::AuthorityRoundParams> for AuthorityRoundParams {
|
||||
struct Step {
|
||||
calibrate: bool, // whether calibration is enabled.
|
||||
inner: AtomicUsize,
|
||||
duration: Duration,
|
||||
duration: u16,
|
||||
}
|
||||
|
||||
impl Step {
|
||||
fn load(&self) -> usize { self.inner.load(AtomicOrdering::SeqCst) }
|
||||
fn duration_remaining(&self) -> Duration {
|
||||
let now = unix_now();
|
||||
let step_end = self.duration * (self.load() as u32 + 1);
|
||||
if step_end > now {
|
||||
step_end - now
|
||||
} else {
|
||||
Duration::from_secs(0)
|
||||
let expected_seconds = (self.load() as u64)
|
||||
.checked_add(1)
|
||||
.and_then(|ctr| ctr.checked_mul(self.duration as u64));
|
||||
match expected_seconds {
|
||||
Some(secs) => {
|
||||
let step_end = Duration::from_secs(secs);
|
||||
if step_end > now {
|
||||
step_end - now
|
||||
} else {
|
||||
Duration::from_secs(0)
|
||||
}
|
||||
},
|
||||
None => {
|
||||
let ctr = self.load();
|
||||
error!(target: "engine", "Step counter is too high: {}, aborting", ctr);
|
||||
panic!("step counter is too high: {}", ctr)
|
||||
},
|
||||
}
|
||||
|
||||
}
|
||||
fn increment(&self) {
|
||||
self.inner.fetch_add(1, AtomicOrdering::SeqCst);
|
||||
use std::usize;
|
||||
// fetch_add won't panic on overflow but will rather wrap
|
||||
// around, leading to zero as the step counter, which might
|
||||
// lead to unexpected situations, so it's better to shut down.
|
||||
if self.inner.fetch_add(1, AtomicOrdering::SeqCst) == usize::MAX {
|
||||
error!(target: "engine", "Step counter is too high: {}, aborting", usize::MAX);
|
||||
panic!("step counter is too high: {}", usize::MAX);
|
||||
}
|
||||
|
||||
}
|
||||
fn calibrate(&self) {
|
||||
if self.calibrate {
|
||||
let new_step = unix_now().as_secs() / self.duration.as_secs();
|
||||
let new_step = unix_now().as_secs() / (self.duration as u64);
|
||||
self.inner.store(new_step as usize, AtomicOrdering::SeqCst);
|
||||
}
|
||||
}
|
||||
@@ -123,6 +158,11 @@ impl Step {
|
||||
}
|
||||
}
|
||||
|
||||
// Chain scoring: total weight is sqrt(U256::max_value())*height - step
|
||||
fn calculate_score(parent_step: U256, current_step: U256) -> U256 {
|
||||
U256::from(U128::max_value()) + parent_step - current_step
|
||||
}
|
||||
|
||||
struct EpochManager {
|
||||
epoch_transition_hash: H256,
|
||||
epoch_transition_number: BlockNumber,
|
||||
@@ -221,6 +261,7 @@ pub struct AuthorityRound {
|
||||
epoch_manager: Mutex<EpochManager>,
|
||||
immediate_transitions: bool,
|
||||
block_reward: U256,
|
||||
maximum_uncle_count_transition: u64,
|
||||
maximum_uncle_count: usize,
|
||||
machine: EthereumMachine,
|
||||
}
|
||||
@@ -350,8 +391,12 @@ impl AsMillis for Duration {
|
||||
impl AuthorityRound {
|
||||
/// Create a new instance of AuthorityRound engine.
|
||||
pub fn new(our_params: AuthorityRoundParams, machine: EthereumMachine) -> Result<Arc<Self>, Error> {
|
||||
if our_params.step_duration == 0 {
|
||||
error!(target: "engine", "Authority Round step duration can't be zero, aborting");
|
||||
panic!("authority_round: step duration can't be zero")
|
||||
}
|
||||
let should_timeout = our_params.start_step.is_none();
|
||||
let initial_step = our_params.start_step.unwrap_or_else(|| (unix_now().as_secs() / our_params.step_duration.as_secs())) as usize;
|
||||
let initial_step = our_params.start_step.unwrap_or_else(|| (unix_now().as_secs() / (our_params.step_duration as u64))) as usize;
|
||||
let engine = Arc::new(
|
||||
AuthorityRound {
|
||||
transition_service: IoService::<()>::start()?,
|
||||
@@ -369,6 +414,7 @@ impl AuthorityRound {
|
||||
epoch_manager: Mutex::new(EpochManager::blank()),
|
||||
immediate_transitions: our_params.immediate_transitions,
|
||||
block_reward: our_params.block_reward,
|
||||
maximum_uncle_count_transition: our_params.maximum_uncle_count_transition,
|
||||
maximum_uncle_count: our_params.maximum_uncle_count,
|
||||
machine: machine,
|
||||
});
|
||||
@@ -441,15 +487,23 @@ impl Engine<EthereumMachine> for AuthorityRound {
|
||||
]
|
||||
}
|
||||
|
||||
fn maximum_uncle_count(&self) -> usize { self.maximum_uncle_count }
|
||||
fn maximum_uncle_count(&self, block: BlockNumber) -> usize {
|
||||
if block >= self.maximum_uncle_count_transition {
|
||||
self.maximum_uncle_count
|
||||
} else {
|
||||
// fallback to default value
|
||||
2
|
||||
}
|
||||
}
|
||||
|
||||
fn populate_from_parent(&self, header: &mut Header, parent: &Header) {
|
||||
// Chain scoring: total weight is sqrt(U256::max_value())*height - step
|
||||
let new_difficulty = U256::from(U128::max_value()) + header_step(parent).expect("Header has been verified; qed").into() - self.step.load().into();
|
||||
header.set_difficulty(new_difficulty);
|
||||
let parent_step = header_step(parent).expect("Header has been verified; qed");
|
||||
let score = calculate_score(parent_step.into(), self.step.load().into());
|
||||
header.set_difficulty(score);
|
||||
}
|
||||
|
||||
fn seals_internally(&self) -> Option<bool> {
|
||||
// TODO: accept a `&Call` here so we can query the validator set.
|
||||
Some(self.signer.read().is_some())
|
||||
}
|
||||
|
||||
@@ -457,14 +511,23 @@ impl Engine<EthereumMachine> for AuthorityRound {
|
||||
///
|
||||
/// This operation is synchronous and may (quite reasonably) not be available, in which case
|
||||
/// `Seal::None` will be returned.
|
||||
fn generate_seal(&self, block: &ExecutedBlock) -> Seal {
|
||||
fn generate_seal(&self, block: &ExecutedBlock, parent: &Header) -> Seal {
|
||||
// first check to avoid generating signature most of the time
|
||||
// (but there's still a race to the `compare_and_swap`)
|
||||
if !self.can_propose.load(AtomicOrdering::SeqCst) { return Seal::None; }
|
||||
|
||||
let header = block.header();
|
||||
let parent_step: U256 = header_step(parent)
|
||||
.expect("Header has been verified; qed").into();
|
||||
|
||||
let step = self.step.load();
|
||||
|
||||
let expected_diff = calculate_score(parent_step, step.into());
|
||||
|
||||
if header.difficulty() != &expected_diff {
|
||||
return Seal::None;
|
||||
}
|
||||
|
||||
// fetch correct validator set for current epoch, taking into account
|
||||
// finality of previous transitions.
|
||||
let active_set;
|
||||
@@ -491,6 +554,13 @@ impl Engine<EthereumMachine> for AuthorityRound {
|
||||
};
|
||||
|
||||
if is_step_proposer(validators, header.parent_hash(), step, header.author()) {
|
||||
// this is guarded against by `can_propose` unless the block was signed
|
||||
// on the same step (implies same key) and on a different node.
|
||||
if parent_step == step.into() {
|
||||
warn!("Attempted to seal block on the same step as parent. Is this authority sealing with more than one node?");
|
||||
return Seal::None;
|
||||
}
|
||||
|
||||
if let Ok(signature) = self.sign(header.bare_hash()) {
|
||||
trace!(target: "engine", "generate_seal: Issuing a block for step {}.", step);
|
||||
|
||||
@@ -505,6 +575,7 @@ impl Engine<EthereumMachine> for AuthorityRound {
|
||||
trace!(target: "engine", "generate_seal: {} not a proposer for step {}.",
|
||||
header.author(), step);
|
||||
}
|
||||
|
||||
Seal::None
|
||||
}
|
||||
|
||||
@@ -546,7 +617,7 @@ impl Engine<EthereumMachine> for AuthorityRound {
|
||||
}
|
||||
|
||||
/// Check the number of seal fields.
|
||||
fn verify_block_basic(&self, header: &Header,) -> Result<(), Error> {
|
||||
fn verify_block_basic(&self, header: &Header) -> Result<(), Error> {
|
||||
if header.number() >= self.validate_score_transition && *header.difficulty() >= U256::from(U128::max_value()) {
|
||||
Err(From::from(BlockError::DifficultyOutOfBounds(
|
||||
OutOfBounds { min: None, max: Some(U256::from(U128::max_value())), found: *header.difficulty() }
|
||||
@@ -857,17 +928,51 @@ mod tests {
|
||||
let b2 = b2.close_and_lock();
|
||||
|
||||
engine.set_signer(tap.clone(), addr1, "1".into());
|
||||
if let Seal::Regular(seal) = engine.generate_seal(b1.block()) {
|
||||
if let Seal::Regular(seal) = engine.generate_seal(b1.block(), &genesis_header) {
|
||||
assert!(b1.clone().try_seal(engine, seal).is_ok());
|
||||
// Second proposal is forbidden.
|
||||
assert!(engine.generate_seal(b1.block()) == Seal::None);
|
||||
assert!(engine.generate_seal(b1.block(), &genesis_header) == Seal::None);
|
||||
}
|
||||
|
||||
engine.set_signer(tap, addr2, "2".into());
|
||||
if let Seal::Regular(seal) = engine.generate_seal(b2.block()) {
|
||||
if let Seal::Regular(seal) = engine.generate_seal(b2.block(), &genesis_header) {
|
||||
assert!(b2.clone().try_seal(engine, seal).is_ok());
|
||||
// Second proposal is forbidden.
|
||||
assert!(engine.generate_seal(b2.block()) == Seal::None);
|
||||
assert!(engine.generate_seal(b2.block(), &genesis_header) == Seal::None);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn checks_difficulty_in_generate_seal() {
|
||||
let tap = Arc::new(AccountProvider::transient_provider());
|
||||
let addr1 = tap.insert_account(keccak("1").into(), "1").unwrap();
|
||||
let addr2 = tap.insert_account(keccak("0").into(), "0").unwrap();
|
||||
|
||||
let spec = Spec::new_test_round();
|
||||
let engine = &*spec.engine;
|
||||
|
||||
let genesis_header = spec.genesis_header();
|
||||
let db1 = spec.ensure_db_good(get_temp_state_db(), &Default::default()).unwrap();
|
||||
let db2 = spec.ensure_db_good(get_temp_state_db(), &Default::default()).unwrap();
|
||||
let last_hashes = Arc::new(vec![genesis_header.hash()]);
|
||||
|
||||
let b1 = OpenBlock::new(engine, Default::default(), false, db1, &genesis_header, last_hashes.clone(), addr1, (3141562.into(), 31415620.into()), vec![], false).unwrap();
|
||||
let b1 = b1.close_and_lock();
|
||||
let b2 = OpenBlock::new(engine, Default::default(), false, db2, &genesis_header, last_hashes, addr2, (3141562.into(), 31415620.into()), vec![], false).unwrap();
|
||||
let b2 = b2.close_and_lock();
|
||||
|
||||
engine.set_signer(tap.clone(), addr1, "1".into());
|
||||
match engine.generate_seal(b1.block(), &genesis_header) {
|
||||
Seal::None | Seal::Proposal(_) => panic!("wrong seal"),
|
||||
Seal::Regular(_) => {
|
||||
engine.step();
|
||||
|
||||
engine.set_signer(tap.clone(), addr2, "0".into());
|
||||
match engine.generate_seal(b2.block(), &genesis_header) {
|
||||
Seal::Regular(_) | Seal::Proposal(_) => panic!("sealed despite wrong difficulty"),
|
||||
Seal::None => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -950,12 +1055,13 @@ mod tests {
|
||||
fn reports_skipped() {
|
||||
let last_benign = Arc::new(AtomicUsize::new(0));
|
||||
let params = AuthorityRoundParams {
|
||||
step_duration: Default::default(),
|
||||
step_duration: 1,
|
||||
start_step: Some(1),
|
||||
validators: Box::new(TestSet::new(Default::default(), last_benign.clone())),
|
||||
validate_score_transition: 0,
|
||||
validate_step_transition: 0,
|
||||
immediate_transitions: true,
|
||||
maximum_uncle_count_transition: 0,
|
||||
maximum_uncle_count: 0,
|
||||
block_reward: Default::default(),
|
||||
};
|
||||
@@ -984,4 +1090,77 @@ mod tests {
|
||||
assert!(aura.verify_block_family(&header, &parent_header).is_ok());
|
||||
assert_eq!(last_benign.load(AtomicOrdering::SeqCst), 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_uncles_transition() {
|
||||
let last_benign = Arc::new(AtomicUsize::new(0));
|
||||
let params = AuthorityRoundParams {
|
||||
step_duration: 1,
|
||||
start_step: Some(1),
|
||||
validators: Box::new(TestSet::new(Default::default(), last_benign.clone())),
|
||||
validate_score_transition: 0,
|
||||
validate_step_transition: 0,
|
||||
immediate_transitions: true,
|
||||
maximum_uncle_count_transition: 1,
|
||||
maximum_uncle_count: 0,
|
||||
block_reward: Default::default(),
|
||||
};
|
||||
|
||||
let aura = {
|
||||
let mut c_params = ::spec::CommonParams::default();
|
||||
c_params.gas_limit_bound_divisor = 5.into();
|
||||
let machine = ::machine::EthereumMachine::regular(c_params, Default::default());
|
||||
AuthorityRound::new(params, machine).unwrap()
|
||||
};
|
||||
|
||||
assert_eq!(aura.maximum_uncle_count(0), 2);
|
||||
assert_eq!(aura.maximum_uncle_count(1), 0);
|
||||
assert_eq!(aura.maximum_uncle_count(100), 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic(expected="counter is too high")]
|
||||
fn test_counter_increment_too_high() {
|
||||
use super::Step;
|
||||
let step = Step {
|
||||
calibrate: false,
|
||||
inner: AtomicUsize::new(::std::usize::MAX),
|
||||
duration: 1,
|
||||
};
|
||||
step.increment();
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic(expected="counter is too high")]
|
||||
fn test_counter_duration_remaining_too_high() {
|
||||
use super::Step;
|
||||
let step = Step {
|
||||
calibrate: false,
|
||||
inner: AtomicUsize::new(::std::usize::MAX),
|
||||
duration: 1,
|
||||
};
|
||||
step.duration_remaining();
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic(expected="authority_round: step duration can't be zero")]
|
||||
fn test_step_duration_zero() {
|
||||
let last_benign = Arc::new(AtomicUsize::new(0));
|
||||
let params = AuthorityRoundParams {
|
||||
step_duration: 0,
|
||||
start_step: Some(1),
|
||||
validators: Box::new(TestSet::new(Default::default(), last_benign.clone())),
|
||||
validate_score_transition: 0,
|
||||
validate_step_transition: 0,
|
||||
immediate_transitions: true,
|
||||
maximum_uncle_count_transition: 0,
|
||||
maximum_uncle_count: 0,
|
||||
block_reward: Default::default(),
|
||||
};
|
||||
|
||||
let mut c_params = ::spec::CommonParams::default();
|
||||
c_params.gas_limit_bound_divisor = 5.into();
|
||||
let machine = ::machine::EthereumMachine::regular(c_params, Default::default());
|
||||
AuthorityRound::new(params, machine).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -107,7 +107,7 @@ impl Engine<EthereumMachine> for BasicAuthority {
|
||||
}
|
||||
|
||||
/// Attempt to seal the block internally.
|
||||
fn generate_seal(&self, block: &ExecutedBlock) -> Seal {
|
||||
fn generate_seal(&self, block: &ExecutedBlock, _parent: &Header) -> Seal {
|
||||
let header = block.header();
|
||||
let author = header.author();
|
||||
if self.validators.contains(header.parent_hash(), author) {
|
||||
@@ -251,7 +251,7 @@ mod tests {
|
||||
let last_hashes = Arc::new(vec![genesis_header.hash()]);
|
||||
let b = OpenBlock::new(engine, Default::default(), false, db, &genesis_header, last_hashes, addr, (3141562.into(), 31415620.into()), vec![], false).unwrap();
|
||||
let b = b.close_and_lock();
|
||||
if let Seal::Regular(seal) = engine.generate_seal(b.block()) {
|
||||
if let Seal::Regular(seal) = engine.generate_seal(b.block(), &genesis_header) {
|
||||
assert!(b.try_seal(engine, seal).is_ok());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,7 +43,7 @@ impl<M: Machine> Engine<M> for InstantSeal<M>
|
||||
|
||||
fn seals_internally(&self) -> Option<bool> { Some(true) }
|
||||
|
||||
fn generate_seal(&self, block: &M::LiveBlock) -> Seal {
|
||||
fn generate_seal(&self, block: &M::LiveBlock, _parent: &M::Header) -> Seal {
|
||||
if block.transactions().is_empty() { Seal::None } else { Seal::Regular(Vec::new()) }
|
||||
}
|
||||
|
||||
@@ -72,7 +72,7 @@ mod tests {
|
||||
let last_hashes = Arc::new(vec![genesis_header.hash()]);
|
||||
let b = OpenBlock::new(engine, Default::default(), false, db, &genesis_header, last_hashes, Address::default(), (3141562.into(), 31415620.into()), vec![], false).unwrap();
|
||||
let b = b.close_and_lock();
|
||||
if let Seal::Regular(seal) = engine.generate_seal(b.block()) {
|
||||
if let Seal::Regular(seal) = engine.generate_seal(b.block(), &genesis_header) {
|
||||
assert!(b.try_seal(engine, seal).is_ok());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -192,7 +192,8 @@ pub trait Engine<M: Machine>: Sync + Send {
|
||||
fn extra_info(&self, _header: &M::Header) -> BTreeMap<String, String> { BTreeMap::new() }
|
||||
|
||||
/// Maximum number of uncles a block is allowed to declare.
|
||||
fn maximum_uncle_count(&self) -> usize { 0 }
|
||||
fn maximum_uncle_count(&self, _block: BlockNumber) -> usize { 0 }
|
||||
|
||||
/// The number of generations back that uncles can be.
|
||||
fn maximum_uncle_age(&self) -> usize { 6 }
|
||||
|
||||
@@ -225,7 +226,7 @@ pub trait Engine<M: Machine>: Sync + Send {
|
||||
///
|
||||
/// It is fine to require access to state or a full client for this function, since
|
||||
/// light clients do not generate seals.
|
||||
fn generate_seal(&self, _block: &M::LiveBlock) -> Seal { Seal::None }
|
||||
fn generate_seal(&self, _block: &M::LiveBlock, _parent: &M::Header) -> Seal { Seal::None }
|
||||
|
||||
/// Verify a locally-generated seal of a header.
|
||||
///
|
||||
@@ -363,7 +364,7 @@ pub trait EthEngine: Engine<::machine::EthereumMachine> {
|
||||
}
|
||||
|
||||
/// The nonce with which accounts begin at given block.
|
||||
fn account_start_nonce(&self, block: u64) -> U256 {
|
||||
fn account_start_nonce(&self, block: BlockNumber) -> U256 {
|
||||
self.machine().account_start_nonce(block)
|
||||
}
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
use bigint::prelude::U256;
|
||||
use engines::Engine;
|
||||
use header::BlockNumber;
|
||||
use parity_machine::{Header, LiveBlock, WithBalances};
|
||||
|
||||
/// Params for a null engine.
|
||||
@@ -95,7 +96,7 @@ impl<M: WithBalances> Engine<M> for NullEngine<M> {
|
||||
self.machine.note_rewards(block, &[(author, result_block_reward)], &uncle_rewards)
|
||||
}
|
||||
|
||||
fn maximum_uncle_count(&self) -> usize { 2 }
|
||||
fn maximum_uncle_count(&self, _block: BlockNumber) -> usize { 2 }
|
||||
|
||||
fn verify_local_seal(&self, _header: &M::Header) -> Result<(), M::Error> {
|
||||
Ok(())
|
||||
|
||||
@@ -450,7 +450,7 @@ impl Engine<EthereumMachine> for Tendermint {
|
||||
|
||||
fn machine(&self) -> &EthereumMachine { &self.machine }
|
||||
|
||||
fn maximum_uncle_count(&self) -> usize { 0 }
|
||||
fn maximum_uncle_count(&self, _block: BlockNumber) -> usize { 0 }
|
||||
|
||||
fn maximum_uncle_age(&self) -> usize { 0 }
|
||||
|
||||
@@ -483,7 +483,7 @@ impl Engine<EthereumMachine> for Tendermint {
|
||||
///
|
||||
/// This operation is synchronous and may (quite reasonably) not be available, in which case
|
||||
/// `Seal::None` will be returned.
|
||||
fn generate_seal(&self, block: &ExecutedBlock) -> Seal {
|
||||
fn generate_seal(&self, block: &ExecutedBlock, _parent: &Header) -> Seal {
|
||||
let header = block.header();
|
||||
let author = header.author();
|
||||
// Only proposer can generate seal if None was generated.
|
||||
@@ -805,7 +805,7 @@ mod tests {
|
||||
let last_hashes = Arc::new(vec![genesis_header.hash()]);
|
||||
let b = OpenBlock::new(spec.engine.as_ref(), Default::default(), false, db.boxed_clone(), &genesis_header, last_hashes, proposer, (3141562.into(), 31415620.into()), vec![], false).unwrap();
|
||||
let b = b.close();
|
||||
if let Seal::Proposal(seal) = spec.engine.generate_seal(b.block()) {
|
||||
if let Seal::Proposal(seal) = spec.engine.generate_seal(b.block(), &genesis_header) {
|
||||
(b, seal)
|
||||
} else {
|
||||
panic!()
|
||||
|
||||
@@ -58,7 +58,7 @@ impl ValidatorContract {
|
||||
let client = self.client.read().clone();
|
||||
Box::new(move |a, d| client.as_ref()
|
||||
.and_then(Weak::upgrade)
|
||||
.ok_or("No client!".into())
|
||||
.ok_or_else(|| "No client!".into())
|
||||
.and_then(|c| {
|
||||
match c.as_full_client() {
|
||||
Some(c) => c.transact_contract(a, d)
|
||||
|
||||
@@ -138,7 +138,7 @@ impl ValidatorSet for Multi {
|
||||
}
|
||||
*self.block_number.write() = Box::new(move |id| client
|
||||
.upgrade()
|
||||
.ok_or("No client!".into())
|
||||
.ok_or_else(|| "No client!".into())
|
||||
.and_then(|c| c.block_number(id).ok_or("Unknown block".into())));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -311,7 +311,7 @@ impl ValidatorSet for ValidatorSafeContract {
|
||||
let client = self.client.read().clone();
|
||||
Box::new(move |addr, data| client.as_ref()
|
||||
.and_then(Weak::upgrade)
|
||||
.ok_or("No client!".into())
|
||||
.ok_or_else(|| "No client!".into())
|
||||
.and_then(|c| {
|
||||
match c.as_full_client() {
|
||||
Some(c) => c.call_contract(id, addr, data),
|
||||
|
||||
@@ -26,7 +26,7 @@ use util::Address;
|
||||
use unexpected::{OutOfBounds, Mismatch};
|
||||
use block::*;
|
||||
use error::{BlockError, Error};
|
||||
use header::Header;
|
||||
use header::{Header, BlockNumber};
|
||||
use engines::{self, Engine};
|
||||
use ethjson;
|
||||
use rlp::{self, UntrustedRlp};
|
||||
@@ -181,7 +181,7 @@ impl Engine<EthereumMachine> for Arc<Ethash> {
|
||||
}
|
||||
}
|
||||
|
||||
fn maximum_uncle_count(&self) -> usize { 2 }
|
||||
fn maximum_uncle_count(&self, _block: BlockNumber) -> usize { 2 }
|
||||
|
||||
fn populate_from_parent(&self, header: &mut Header, parent: &Header) {
|
||||
let difficulty = self.calculate_difficulty(header, parent);
|
||||
@@ -336,7 +336,6 @@ impl Engine<EthereumMachine> for Arc<Ethash> {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(feature="dev", allow(wrong_self_convention))]
|
||||
impl Ethash {
|
||||
fn calculate_difficulty(&self, header: &Header, parent: &Header) -> U256 {
|
||||
const EXP_DIFF_PERIOD: u64 = 100_000;
|
||||
@@ -520,7 +519,7 @@ mod tests {
|
||||
let (eras, reward) = ecip1017_eras_block_reward(eras_rounds, start_reward, block_number);
|
||||
assert_eq!(15, eras);
|
||||
assert_eq!(U256::from_str("271000000000000").unwrap(), reward);
|
||||
|
||||
|
||||
let block_number = 250000000;
|
||||
let (eras, reward) = ecip1017_eras_block_reward(eras_rounds, start_reward, block_number);
|
||||
assert_eq!(49, eras);
|
||||
|
||||
@@ -75,6 +75,11 @@ pub fn new_musicoin<'a, T: Into<SpecParams<'a>>>(params: T) -> Spec {
|
||||
load(params.into(), include_bytes!("../../res/ethereum/musicoin.json"))
|
||||
}
|
||||
|
||||
/// Create a new Ellaism mainnet chain spec.
|
||||
pub fn new_ellaism<'a, T: Into<SpecParams<'a>>>(params: T) -> Spec {
|
||||
load(params.into(), include_bytes!("../../res/ethereum/ellaism.json"))
|
||||
}
|
||||
|
||||
/// Create a new Kovan testnet chain spec.
|
||||
pub fn new_kovan<'a, T: Into<SpecParams<'a>>>(params: T) -> Spec {
|
||||
load(params.into(), include_bytes!("../../res/ethereum/kovan.json"))
|
||||
|
||||
@@ -85,7 +85,6 @@ impl<'a, T: 'a, V: 'a, B: 'a> Externalities<'a, T, V, B>
|
||||
where T: Tracer, V: VMTracer, B: StateBackend
|
||||
{
|
||||
/// Basic `Externalities` constructor.
|
||||
#[cfg_attr(feature="dev", allow(too_many_arguments))]
|
||||
pub fn new(state: &'a mut State<B>,
|
||||
env_info: &'a EnvInfo,
|
||||
machine: &'a Machine,
|
||||
@@ -302,7 +301,6 @@ impl<'a, T: 'a, V: 'a, B: 'a> Ext for Externalities<'a, T, V, B>
|
||||
Ok(self.state.code_size(address)?.unwrap_or(0))
|
||||
}
|
||||
|
||||
#[cfg_attr(feature="dev", allow(match_ref_pats))]
|
||||
fn ret(mut self, gas: &U256, data: &ReturnData, apply_state: bool) -> vm::Result<U256>
|
||||
where Self: Sized {
|
||||
let handle_copy = |to: &mut Option<&mut Bytes>| {
|
||||
|
||||
@@ -16,23 +16,6 @@
|
||||
|
||||
#![warn(missing_docs)]
|
||||
#![cfg_attr(feature="benches", feature(test))]
|
||||
#![cfg_attr(feature="dev", feature(plugin))]
|
||||
#![cfg_attr(feature="dev", plugin(clippy))]
|
||||
|
||||
// Clippy settings
|
||||
// Most of the time much more readable
|
||||
#![cfg_attr(feature="dev", allow(needless_range_loop))]
|
||||
// Shorter than if-else
|
||||
#![cfg_attr(feature="dev", allow(match_bool))]
|
||||
// Keeps consistency (all lines with `.clone()`).
|
||||
#![cfg_attr(feature="dev", allow(clone_on_copy))]
|
||||
// Complains on Box<E> when implementing From<Box<E>>
|
||||
#![cfg_attr(feature="dev", allow(boxed_local))]
|
||||
// Complains about nested modules with same name as parent
|
||||
#![cfg_attr(feature="dev", allow(module_inception))]
|
||||
// TODO [todr] a lot of warnings to be fixed
|
||||
#![cfg_attr(feature="dev", allow(assign_op_pattern))]
|
||||
|
||||
|
||||
//! Ethcore library
|
||||
//!
|
||||
|
||||
@@ -366,7 +366,6 @@ impl Miner {
|
||||
)
|
||||
}
|
||||
|
||||
#[cfg_attr(feature="dev", allow(match_same_arms))]
|
||||
/// Prepares new block for sealing including top transactions from queue.
|
||||
fn prepare_block(&self, chain: &MiningBlockChainClient) -> (ClosedBlock, Option<H256>) {
|
||||
let _timer = PerfTimer::new("prepare_block");
|
||||
@@ -534,7 +533,13 @@ impl Miner {
|
||||
fn seal_and_import_block_internally(&self, chain: &MiningBlockChainClient, block: ClosedBlock) -> bool {
|
||||
if !block.transactions().is_empty() || self.forced_sealing() || Instant::now() > *self.next_mandatory_reseal.read() {
|
||||
trace!(target: "miner", "seal_block_internally: attempting internal seal.");
|
||||
match self.engine.generate_seal(block.block()) {
|
||||
|
||||
let parent_header = match chain.block_header(BlockId::Hash(*block.header().parent_hash())) {
|
||||
Some(hdr) => hdr.decode(),
|
||||
None => return false,
|
||||
};
|
||||
|
||||
match self.engine.generate_seal(block.block(), &parent_header) {
|
||||
// Save proposal for later seal submission and broadcast it.
|
||||
Seal::Proposal(seal) => {
|
||||
trace!(target: "miner", "Received a Proposal seal.");
|
||||
@@ -702,8 +707,6 @@ impl Miner {
|
||||
/// Are we allowed to do a non-mandatory reseal?
|
||||
fn tx_reseal_allowed(&self) -> bool { Instant::now() > *self.next_allowed_reseal.lock() }
|
||||
|
||||
#[cfg_attr(feature="dev", allow(wrong_self_convention))]
|
||||
#[cfg_attr(feature="dev", allow(redundant_closure))]
|
||||
fn from_pending_block<H, F, G>(&self, latest_block_number: BlockNumber, from_chain: F, map_block: G) -> H
|
||||
where F: Fn() -> H, G: FnOnce(&ClosedBlock) -> H {
|
||||
let sealing_work = self.sealing_work.lock();
|
||||
@@ -863,7 +866,6 @@ impl MinerService for Miner {
|
||||
results
|
||||
}
|
||||
|
||||
#[cfg_attr(feature="dev", allow(collapsible_if))]
|
||||
fn import_own_transaction(
|
||||
&self,
|
||||
chain: &MiningBlockChainClient,
|
||||
|
||||
@@ -15,8 +15,6 @@
|
||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#![warn(missing_docs)]
|
||||
#![cfg_attr(all(nightly, feature="dev"), feature(plugin))]
|
||||
#![cfg_attr(all(nightly, feature="dev"), plugin(clippy))]
|
||||
|
||||
//! Miner module
|
||||
//! Keeps track of transactions and mined block.
|
||||
|
||||
@@ -136,7 +136,6 @@ impl PartialOrd for TransactionOrigin {
|
||||
}
|
||||
|
||||
impl Ord for TransactionOrigin {
|
||||
#[cfg_attr(feature="dev", allow(match_same_arms))]
|
||||
fn cmp(&self, other: &TransactionOrigin) -> Ordering {
|
||||
if *other == *self {
|
||||
return Ordering::Equal;
|
||||
@@ -516,7 +515,6 @@ pub struct AccountDetails {
|
||||
const GAS_PRICE_BUMP_SHIFT: usize = 3; // 2 = 25%, 3 = 12.5%, 4 = 6.25%
|
||||
|
||||
/// Describes the strategy used to prioritize transactions in the queue.
|
||||
#[cfg_attr(feature="dev", allow(enum_variant_names))]
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||
pub enum PrioritizationStrategy {
|
||||
/// Use only gas price. Disregards the actual computation cost of the transaction.
|
||||
|
||||
@@ -186,7 +186,6 @@ impl IoHandler<ClientIoMessage> for ClientIoHandler {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(feature="dev", allow(single_match))]
|
||||
fn message(&self, _io: &IoContext<ClientIoMessage>, net_message: &ClientIoMessage) {
|
||||
use std::thread;
|
||||
|
||||
|
||||
@@ -57,7 +57,6 @@ impl StateProducer {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(feature="dev", allow(let_and_return))]
|
||||
/// Tick the state producer. This alters the state, writing new data into
|
||||
/// the database.
|
||||
pub fn tick<R: Rng>(&mut self, rng: &mut R, db: &mut HashDB) {
|
||||
|
||||
@@ -35,6 +35,15 @@ use std::cell::{RefCell, Cell};
|
||||
|
||||
const STORAGE_CACHE_ITEMS: usize = 8192;
|
||||
|
||||
/// Boolean type for clean/dirty status.
|
||||
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
|
||||
pub enum Filth {
|
||||
/// Data has not been changed.
|
||||
Clean,
|
||||
/// Data has been changed.
|
||||
Dirty,
|
||||
}
|
||||
|
||||
/// Single account in the system.
|
||||
/// Keeps track of changes to the code and storage.
|
||||
/// The changes are applied in `commit_storage` and `commit_code`
|
||||
|
||||
@@ -604,7 +604,6 @@ impl<B: Backend> State<B> {
|
||||
}
|
||||
|
||||
/// Add `incr` to the balance of account `a`.
|
||||
#[cfg_attr(feature="dev", allow(single_match))]
|
||||
pub fn add_balance(&mut self, a: &Address, incr: &U256, cleanup_mode: CleanupMode) -> trie::Result<()> {
|
||||
trace!(target: "state", "add_balance({}, {}): {}", a, incr, self.balance(a)?);
|
||||
let is_value_transfer = !incr.is_zero();
|
||||
@@ -744,8 +743,6 @@ impl<B: Backend> State<B> {
|
||||
}
|
||||
|
||||
/// Commits our cached account changes into the trie.
|
||||
#[cfg_attr(feature="dev", allow(match_ref_pats))]
|
||||
#[cfg_attr(feature="dev", allow(needless_borrow))]
|
||||
pub fn commit(&mut self) -> Result<(), Error> {
|
||||
// first, commit the sub trees.
|
||||
let mut accounts = self.cache.borrow_mut();
|
||||
|
||||
@@ -58,7 +58,6 @@ impl Substate {
|
||||
}
|
||||
|
||||
/// Get the cleanup mode object from this.
|
||||
#[cfg_attr(feature="dev", allow(wrong_self_convention))]
|
||||
pub fn to_cleanup_mode(&mut self, schedule: &Schedule) -> CleanupMode {
|
||||
match (schedule.kill_dust != CleanDustMode::Off, schedule.no_empty, schedule.kill_empty) {
|
||||
(false, false, _) => CleanupMode::ForceCreate,
|
||||
|
||||
@@ -427,7 +427,6 @@ impl state::Backend for StateDB {
|
||||
cache.accounts.get_mut(addr).map(|a| a.as_ref().map(|a| a.clone_basic()))
|
||||
}
|
||||
|
||||
#[cfg_attr(feature="dev", allow(map_clone))]
|
||||
fn get_cached_code(&self, hash: &H256) -> Option<Arc<Vec<u8>>> {
|
||||
let mut cache = self.code_cache.lock();
|
||||
|
||||
|
||||
@@ -34,7 +34,6 @@ use cache_manager::CacheManager;
|
||||
const TRACE_DB_VER: &'static [u8] = b"1.0";
|
||||
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
#[cfg_attr(feature="dev", allow(enum_variant_names))]
|
||||
enum TraceDBIndex {
|
||||
/// Block traces index.
|
||||
BlockTraces = 0,
|
||||
|
||||
@@ -164,7 +164,6 @@ struct QueueSignal {
|
||||
}
|
||||
|
||||
impl QueueSignal {
|
||||
#[cfg_attr(feature="dev", allow(bool_comparison))]
|
||||
fn set_sync(&self) {
|
||||
// Do not signal when we are about to close
|
||||
if self.deleting.load(AtomicOrdering::Relaxed) {
|
||||
@@ -179,7 +178,6 @@ impl QueueSignal {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(feature="dev", allow(bool_comparison))]
|
||||
fn set_async(&self) {
|
||||
// Do not signal when we are about to close
|
||||
if self.deleting.load(AtomicOrdering::Relaxed) {
|
||||
|
||||
@@ -137,9 +137,14 @@ pub fn verify_block_family(header: &Header, parent: &Header, engine: &EthEngine,
|
||||
|
||||
fn verify_uncles(header: &Header, bytes: &[u8], bc: &BlockProvider, engine: &EthEngine) -> Result<(), Error> {
|
||||
let num_uncles = UntrustedRlp::new(bytes).at(2)?.item_count()?;
|
||||
let max_uncles = engine.maximum_uncle_count(header.number());
|
||||
if num_uncles != 0 {
|
||||
if num_uncles > engine.maximum_uncle_count() {
|
||||
return Err(From::from(BlockError::TooManyUncles(OutOfBounds { min: None, max: Some(engine.maximum_uncle_count()), found: num_uncles })));
|
||||
if num_uncles > max_uncles {
|
||||
return Err(From::from(BlockError::TooManyUncles(OutOfBounds {
|
||||
min: None,
|
||||
max: Some(max_uncles),
|
||||
found: num_uncles,
|
||||
})));
|
||||
}
|
||||
|
||||
let mut excluded = HashSet::new();
|
||||
@@ -268,7 +273,7 @@ pub fn verify_header_params(header: &Header, engine: &EthEngine, is_full: bool)
|
||||
}
|
||||
|
||||
if is_full {
|
||||
let max_time = get_time().sec as u64 + 30;
|
||||
let max_time = get_time().sec as u64 + 15;
|
||||
if header.timestamp() > max_time {
|
||||
return Err(From::from(BlockError::InvalidTimestamp(OutOfBounds { max: Some(max_time), min: None, found: header.timestamp() })))
|
||||
}
|
||||
@@ -493,7 +498,6 @@ mod tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg_attr(feature="dev", allow(similar_names))]
|
||||
fn test_verify_block() {
|
||||
use rlp::RlpStream;
|
||||
|
||||
@@ -641,9 +645,15 @@ mod tests {
|
||||
check_fail_timestamp(basic_test(&create_test_block_with_data(&header, &good_transactions, &good_uncles), engine));
|
||||
|
||||
header = good.clone();
|
||||
header.set_timestamp(get_time().sec as u64 + 40);
|
||||
header.set_timestamp(get_time().sec as u64 + 20);
|
||||
check_fail_timestamp(basic_test(&create_test_block_with_data(&header, &good_transactions, &good_uncles), engine));
|
||||
|
||||
header = good.clone();
|
||||
header.set_timestamp(get_time().sec as u64 + 10);
|
||||
header.set_uncles_hash(good_uncles_hash.clone());
|
||||
header.set_transactions_root(good_transactions_root.clone());
|
||||
check_ok(basic_test(&create_test_block_with_data(&header, &good_transactions, &good_uncles), engine));
|
||||
|
||||
header = good.clone();
|
||||
header.set_number(9);
|
||||
check_fail(family_test(&create_test_block_with_data(&header, &good_transactions, &good_uncles), engine, &bc),
|
||||
@@ -653,7 +663,7 @@ mod tests {
|
||||
let mut bad_uncles = good_uncles.clone();
|
||||
bad_uncles.push(good_uncle1.clone());
|
||||
check_fail(family_test(&create_test_block_with_data(&header, &good_transactions, &bad_uncles), engine, &bc),
|
||||
TooManyUncles(OutOfBounds { max: Some(engine.maximum_uncle_count()), min: None, found: bad_uncles.len() }));
|
||||
TooManyUncles(OutOfBounds { max: Some(engine.maximum_uncle_count(header.number())), min: None, found: bad_uncles.len() }));
|
||||
|
||||
header = good.clone();
|
||||
bad_uncles = vec![ good_uncle1.clone(), good_uncle1.clone() ];
|
||||
|
||||
@@ -96,7 +96,6 @@ pub trait Ext {
|
||||
/// Returns Err, if we run out of gas.
|
||||
/// Otherwise returns call_result which contains gas left
|
||||
/// and true if subcall was successfull.
|
||||
#[cfg_attr(feature="dev", allow(too_many_arguments))]
|
||||
fn call(&mut self,
|
||||
gas: &U256,
|
||||
sender_address: &Address,
|
||||
|
||||
@@ -69,17 +69,17 @@ pub const SIGNATURES: &'static [UserFunctionDescriptor] = &[
|
||||
),
|
||||
Static(
|
||||
"_ccall",
|
||||
&[I32; 6],
|
||||
&[I64, I32, I32, I32, I32, I32, I32],
|
||||
Some(I32),
|
||||
),
|
||||
Static(
|
||||
"_dcall",
|
||||
&[I32; 5],
|
||||
&[I64, I32, I32, I32, I32, I32],
|
||||
Some(I32),
|
||||
),
|
||||
Static(
|
||||
"_scall",
|
||||
&[I32; 5],
|
||||
&[I64, I32, I32, I32, I32, I32],
|
||||
Some(I32),
|
||||
),
|
||||
Static(
|
||||
|
||||
@@ -111,6 +111,7 @@ impl vm::Vm for WasmInterpreter {
|
||||
address: params.address,
|
||||
sender: params.sender,
|
||||
origin: params.origin,
|
||||
code_address: params.code_address,
|
||||
value: params.value.value(),
|
||||
},
|
||||
&self.program,
|
||||
|
||||
@@ -104,6 +104,7 @@ pub struct RuntimeContext {
|
||||
pub address: Address,
|
||||
pub sender: Address,
|
||||
pub origin: Address,
|
||||
pub code_address: Address,
|
||||
pub value: U256,
|
||||
}
|
||||
|
||||
@@ -305,6 +306,7 @@ impl<'a, 'b> Runtime<'a, 'b> {
|
||||
//
|
||||
// method signature:
|
||||
// fn (
|
||||
// gas: i64,
|
||||
// address: *const u8,
|
||||
// val_ptr: *const u8,
|
||||
// input_ptr: *const u8,
|
||||
@@ -323,6 +325,7 @@ impl<'a, 'b> Runtime<'a, 'b> {
|
||||
//
|
||||
// signature (same as static call):
|
||||
// fn (
|
||||
// gas: i64,
|
||||
// address: *const u8,
|
||||
// input_ptr: *const u8,
|
||||
// input_len: u32,
|
||||
@@ -330,7 +333,7 @@ impl<'a, 'b> Runtime<'a, 'b> {
|
||||
// result_len: u32,
|
||||
// ) -> i32
|
||||
|
||||
self.do_call(false, CallType::CallCode, context)
|
||||
self.do_call(false, CallType::DelegateCall, context)
|
||||
}
|
||||
|
||||
fn do_call(
|
||||
@@ -363,6 +366,9 @@ impl<'a, 'b> Runtime<'a, 'b> {
|
||||
let address = self.pop_address(&mut context)?;
|
||||
trace!(target: "wasm", " address: {:?}", address);
|
||||
|
||||
let gas = context.value_stack.pop_as::<i64>()? as u64;
|
||||
trace!(target: "wasm", " gas: {:?}", gas);
|
||||
|
||||
if let Some(ref val) = val {
|
||||
let address_balance = self.ext.balance(&self.context.address)
|
||||
.map_err(|_| UserTrap::BalanceQueryError)?;
|
||||
@@ -377,16 +383,16 @@ impl<'a, 'b> Runtime<'a, 'b> {
|
||||
|
||||
let mut result = Vec::with_capacity(result_alloc_len as usize);
|
||||
result.resize(result_alloc_len as usize, 0);
|
||||
let gas = self.gas_left()
|
||||
.map_err(|_| UserTrap::InvalidGasState)?
|
||||
.into();
|
||||
|
||||
// todo: optimize to use memory views once it's in
|
||||
let payload = self.memory.get(input_ptr, input_len as usize)?;
|
||||
|
||||
self.charge(|_| gas.into())?;
|
||||
|
||||
let call_result = self.ext.call(
|
||||
&gas,
|
||||
&self.context.sender,
|
||||
&self.context.address,
|
||||
&gas.into(),
|
||||
match call_type { CallType::DelegateCall => &self.context.sender, _ => &self.context.address },
|
||||
match call_type { CallType::Call | CallType::StaticCall => &address, _ => &self.context.address },
|
||||
val,
|
||||
&payload,
|
||||
&address,
|
||||
@@ -396,12 +402,16 @@ impl<'a, 'b> Runtime<'a, 'b> {
|
||||
|
||||
match call_result {
|
||||
vm::MessageCallResult::Success(gas_left, _) => {
|
||||
self.gas_counter = self.gas_limit - gas_left.low_u64();
|
||||
// cannot overflow, before making call gas_counter was incremented with gas, and gas_left < gas
|
||||
self.gas_counter = self.gas_counter - gas_left.low_u64();
|
||||
|
||||
self.memory.set(result_ptr, &result)?;
|
||||
Ok(Some(0i32.into()))
|
||||
},
|
||||
vm::MessageCallResult::Reverted(gas_left, _) => {
|
||||
self.gas_counter = self.gas_limit - gas_left.low_u64();
|
||||
// cannot overflow, before making call gas_counter was incremented with gas, and gas_left < gas
|
||||
self.gas_counter = self.gas_counter - gas_left.low_u64();
|
||||
|
||||
self.memory.set(result_ptr, &result)?;
|
||||
Ok(Some((-1i32).into()))
|
||||
},
|
||||
@@ -416,6 +426,7 @@ impl<'a, 'b> Runtime<'a, 'b> {
|
||||
{
|
||||
// signature (same as code call):
|
||||
// fn (
|
||||
// gas: i64,
|
||||
// address: *const u8,
|
||||
// input_ptr: *const u8,
|
||||
// input_len: u32,
|
||||
|
||||
@@ -60,7 +60,7 @@ fn empty() {
|
||||
test_finalize(interpreter.exec(params, &mut ext)).unwrap()
|
||||
};
|
||||
|
||||
assert_eq!(gas_left, U256::from(99_982));
|
||||
assert_eq!(gas_left, U256::from(96_678));
|
||||
}
|
||||
|
||||
// This test checks if the contract deserializes payload header properly.
|
||||
@@ -112,7 +112,7 @@ fn logger() {
|
||||
U256::from(1_000_000_000),
|
||||
"Logger sets 0x04 key to the trasferred value"
|
||||
);
|
||||
assert_eq!(gas_left, U256::from(19_147));
|
||||
assert_eq!(gas_left, U256::from(15_860));
|
||||
}
|
||||
|
||||
// This test checks if the contract can allocate memory and pass pointer to the result stream properly.
|
||||
@@ -147,7 +147,7 @@ fn identity() {
|
||||
sender,
|
||||
"Idenity test contract does not return the sender passed"
|
||||
);
|
||||
assert_eq!(gas_left, U256::from(99_844));
|
||||
assert_eq!(gas_left, U256::from(96_540));
|
||||
}
|
||||
|
||||
// Dispersion test sends byte array and expect the contract to 'disperse' the original elements with
|
||||
@@ -180,7 +180,7 @@ fn dispersion() {
|
||||
result,
|
||||
vec![0u8, 0, 125, 11, 197, 7, 255, 8, 19, 0]
|
||||
);
|
||||
assert_eq!(gas_left, U256::from(96_393));
|
||||
assert_eq!(gas_left, U256::from(96_116));
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -208,7 +208,7 @@ fn suicide_not() {
|
||||
result,
|
||||
vec![0u8]
|
||||
);
|
||||
assert_eq!(gas_left, U256::from(96_725));
|
||||
assert_eq!(gas_left, U256::from(96_461));
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -240,7 +240,7 @@ fn suicide() {
|
||||
};
|
||||
|
||||
assert!(ext.suicides.contains(&refund));
|
||||
assert_eq!(gas_left, U256::from(96_687));
|
||||
assert_eq!(gas_left, U256::from(96_429));
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -270,7 +270,7 @@ fn create() {
|
||||
assert!(ext.calls.contains(
|
||||
&FakeCall {
|
||||
call_type: FakeCallType::Create,
|
||||
gas: U256::from(65_899),
|
||||
gas: U256::from(62_545),
|
||||
sender_address: None,
|
||||
receive_address: None,
|
||||
value: Some(1_000_000_000.into()),
|
||||
@@ -278,9 +278,52 @@ fn create() {
|
||||
code_address: None,
|
||||
}
|
||||
));
|
||||
assert_eq!(gas_left, U256::from(65_892));
|
||||
assert_eq!(gas_left, U256::from(62_538));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn call_msg() {
|
||||
::ethcore_logger::init_log();
|
||||
|
||||
let sender: Address = "01030507090b0d0f11131517191b1d1f21232527".parse().unwrap();
|
||||
let receiver: Address = "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6".parse().unwrap();
|
||||
let contract_address: Address = "0d461d4174b4ae35775c4a342f1e5e1e4e6c4db5".parse().unwrap();
|
||||
|
||||
let mut params = ActionParams::default();
|
||||
params.sender = sender.clone();
|
||||
params.address = receiver.clone();
|
||||
params.code_address = contract_address.clone();
|
||||
params.gas = U256::from(100_000);
|
||||
params.code = Some(Arc::new(load_sample!("call.wasm")));
|
||||
params.data = Some(Vec::new());
|
||||
|
||||
let mut ext = FakeExt::new();
|
||||
ext.balances.insert(receiver.clone(), U256::from(10000000000u64));
|
||||
|
||||
let gas_left = {
|
||||
let mut interpreter = wasm_interpreter();
|
||||
let result = interpreter.exec(params, &mut ext).expect("Interpreter to execute without any errors");
|
||||
match result {
|
||||
GasLeft::Known(gas_left) => gas_left,
|
||||
GasLeft::NeedsReturn { .. } => { panic!("Call test should not return payload"); },
|
||||
}
|
||||
};
|
||||
|
||||
trace!(target: "wasm", "fake_calls: {:?}", &ext.calls);
|
||||
assert!(ext.calls.contains(
|
||||
&FakeCall {
|
||||
call_type: FakeCallType::Call,
|
||||
gas: U256::from(33_000),
|
||||
sender_address: Some(receiver),
|
||||
receive_address: Some(Address::from([99, 88, 77, 66, 55, 44, 33, 22, 11, 0, 11, 22, 33, 44, 55, 66, 77, 88, 99, 0])),
|
||||
value: Some(1000000000.into()),
|
||||
data: vec![129u8, 123, 113, 107, 101, 97],
|
||||
code_address: Some(Address::from([99, 88, 77, 66, 55, 44, 33, 22, 11, 0, 11, 22, 33, 44, 55, 66, 77, 88, 99, 0])),
|
||||
}
|
||||
));
|
||||
|
||||
assert_eq!(gas_left, U256::from(95_699));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn call_code() {
|
||||
@@ -312,7 +355,7 @@ fn call_code() {
|
||||
assert!(ext.calls.contains(
|
||||
&FakeCall {
|
||||
call_type: FakeCallType::Call,
|
||||
gas: U256::from(98_713),
|
||||
gas: U256::from(20_000),
|
||||
sender_address: Some(sender),
|
||||
receive_address: Some(receiver),
|
||||
value: None,
|
||||
@@ -324,7 +367,7 @@ fn call_code() {
|
||||
// siphash result
|
||||
let res = LittleEndian::read_u32(&result[..]);
|
||||
assert_eq!(res, 4198595614);
|
||||
assert_eq!(gas_left, U256::from(93_855));
|
||||
assert_eq!(gas_left, U256::from(90_550));
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -333,6 +376,7 @@ fn call_static() {
|
||||
|
||||
let sender: Address = "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6".parse().unwrap();
|
||||
let receiver: Address = "01030507090b0d0f11131517191b1d1f21232527".parse().unwrap();
|
||||
let contract_address: Address = "0d461d4174b4ae35775c4a342f1e5e1e4e6c4db5".parse().unwrap();
|
||||
|
||||
let mut params = ActionParams::default();
|
||||
params.sender = sender.clone();
|
||||
@@ -341,6 +385,7 @@ fn call_static() {
|
||||
params.code = Some(Arc::new(load_sample!("call_static.wasm")));
|
||||
params.data = Some(Vec::new());
|
||||
params.value = ActionValue::transfer(1_000_000_000);
|
||||
params.code_address = contract_address.clone();
|
||||
|
||||
let mut ext = FakeExt::new();
|
||||
|
||||
@@ -357,9 +402,9 @@ fn call_static() {
|
||||
assert!(ext.calls.contains(
|
||||
&FakeCall {
|
||||
call_type: FakeCallType::Call,
|
||||
gas: U256::from(98_713),
|
||||
sender_address: Some(sender),
|
||||
receive_address: Some(receiver),
|
||||
gas: U256::from(20_000),
|
||||
sender_address: Some(receiver),
|
||||
receive_address: Some("13077bfb00000000000000000000000000000000".parse().unwrap()),
|
||||
value: None,
|
||||
data: vec![1u8, 2, 3, 5, 7, 11],
|
||||
code_address: Some("13077bfb00000000000000000000000000000000".parse().unwrap()),
|
||||
@@ -370,7 +415,7 @@ fn call_static() {
|
||||
let res = LittleEndian::read_u32(&result[..]);
|
||||
assert_eq!(res, 317632590);
|
||||
|
||||
assert_eq!(gas_left, U256::from(93_855));
|
||||
assert_eq!(gas_left, U256::from(90_550));
|
||||
}
|
||||
|
||||
// Realloc test
|
||||
@@ -393,7 +438,7 @@ fn realloc() {
|
||||
}
|
||||
};
|
||||
assert_eq!(result, vec![0u8; 2]);
|
||||
assert_eq!(gas_left, U256::from(96_723));
|
||||
assert_eq!(gas_left, U256::from(96_445));
|
||||
}
|
||||
|
||||
// Tests that contract's ability to read from a storage
|
||||
@@ -419,7 +464,7 @@ fn storage_read() {
|
||||
};
|
||||
|
||||
assert_eq!(Address::from(&result[12..32]), address);
|
||||
assert_eq!(gas_left, U256::from(99_767));
|
||||
assert_eq!(gas_left, U256::from(96_463));
|
||||
}
|
||||
|
||||
// Tests keccak calculation
|
||||
@@ -445,7 +490,7 @@ fn keccak() {
|
||||
};
|
||||
|
||||
assert_eq!(H256::from_slice(&result), H256::from("68371d7e884c168ae2022c82bd837d51837718a7f7dfb7aa3f753074a35e1d87"));
|
||||
assert_eq!(gas_left, U256::from(81_446));
|
||||
assert_eq!(gas_left, U256::from(81_067));
|
||||
}
|
||||
|
||||
// memcpy test.
|
||||
@@ -477,7 +522,7 @@ fn memcpy() {
|
||||
};
|
||||
|
||||
assert_eq!(result, test_payload);
|
||||
assert_eq!(gas_left, U256::from(72_216));
|
||||
assert_eq!(gas_left, U256::from(71_940));
|
||||
}
|
||||
|
||||
// memmove test.
|
||||
@@ -509,7 +554,7 @@ fn memmove() {
|
||||
};
|
||||
|
||||
assert_eq!(result, test_payload);
|
||||
assert_eq!(gas_left, U256::from(72_216));
|
||||
assert_eq!(gas_left, U256::from(71_940));
|
||||
}
|
||||
|
||||
// memset test
|
||||
@@ -534,7 +579,7 @@ fn memset() {
|
||||
};
|
||||
|
||||
assert_eq!(result, vec![228u8; 8192]);
|
||||
assert_eq!(gas_left, U256::from(72_196));
|
||||
assert_eq!(gas_left, U256::from(71_921));
|
||||
}
|
||||
|
||||
macro_rules! reqrep_test {
|
||||
@@ -591,7 +636,7 @@ fn math_add() {
|
||||
U256::from_dec_str("1888888888888888888888888888887").unwrap(),
|
||||
(&result[..]).into()
|
||||
);
|
||||
assert_eq!(gas_left, U256::from(95_524));
|
||||
assert_eq!(gas_left, U256::from(95_384));
|
||||
}
|
||||
|
||||
// multiplication
|
||||
@@ -613,7 +658,7 @@ fn math_mul() {
|
||||
U256::from_dec_str("888888888888888888888888888887111111111111111111111111111112").unwrap(),
|
||||
(&result[..]).into()
|
||||
);
|
||||
assert_eq!(gas_left, U256::from(94_674));
|
||||
assert_eq!(gas_left, U256::from(94_374));
|
||||
}
|
||||
|
||||
// subtraction
|
||||
@@ -635,7 +680,7 @@ fn math_sub() {
|
||||
U256::from_dec_str("111111111111111111111111111111").unwrap(),
|
||||
(&result[..]).into()
|
||||
);
|
||||
assert_eq!(gas_left, U256::from(95_516));
|
||||
assert_eq!(gas_left, U256::from(95_372));
|
||||
}
|
||||
|
||||
// subtraction with overflow
|
||||
@@ -677,7 +722,7 @@ fn math_div() {
|
||||
U256::from_dec_str("1125000").unwrap(),
|
||||
(&result[..]).into()
|
||||
);
|
||||
assert_eq!(gas_left, U256::from(88_514));
|
||||
assert_eq!(gas_left, U256::from(88_356));
|
||||
}
|
||||
|
||||
// This test checks the ability of wasm contract to invoke
|
||||
@@ -765,7 +810,7 @@ fn externs() {
|
||||
"Gas limit requested and returned does not match"
|
||||
);
|
||||
|
||||
assert_eq!(gas_left, U256::from(94_858));
|
||||
assert_eq!(gas_left, U256::from(95_321));
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -791,7 +836,7 @@ fn embedded_keccak() {
|
||||
};
|
||||
|
||||
assert_eq!(H256::from_slice(&result), H256::from("68371d7e884c168ae2022c82bd837d51837718a7f7dfb7aa3f753074a35e1d87"));
|
||||
assert_eq!(gas_left, U256::from(81_446));
|
||||
assert_eq!(gas_left, U256::from(81_067));
|
||||
}
|
||||
|
||||
/// This test checks the correctness of log extern
|
||||
@@ -826,5 +871,5 @@ fn events() {
|
||||
assert_eq!(&log_entry.data, b"gnihtemos");
|
||||
|
||||
assert_eq!(&result, b"gnihtemos");
|
||||
assert_eq!(gas_left, U256::from(79_637));
|
||||
assert_eq!(gas_left, U256::from(79_206));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user