[stable] Backports (#8557)
* Update wasmi and pwasm-utils (#8493) * Update wasmi to 0.2 New wasmi supports 32bit platforms and no longer requires a special feature to build for such platforms. * Update pwasm-utils to 0.1.5 * Fetching logs by hash in blockchain database (#8463) * Fetch logs by hash in blockchain database * Fix tests * Add unit test for branch block logs fetching * Add docs that blocks must already be sorted * Handle branch block cases properly * typo: empty -> is_empty * Remove return_empty_if_none by using a closure * Use BTreeSet to avoid sorting again * Move is_canon to BlockChain * typo: pass value by reference * Use loop and wrap inside blocks to simplify the code Borrowed from https://github.com/paritytech/parity/pull/8463#discussion_r183453326 * typo: missed a comment * Pass on storage keys tracing to handle the case when it is not modified (#8491) * Pass on storage keys even if it is not modified * typo: account and storage query `to_pod_diff` builds both `touched_addresses` merge and storage keys merge. * Fix tests * Use state query directly because of suicided accounts * Fix a RefCell borrow issue * Add tests for unmodified storage trace * Address grumbles * typo: remove unwanted empty line * ensure_cached compiles with the original signature * Enable WebAssembly and Byzantium for Ellaism (#8520) * Enable WebAssembly and Byzantium for Ellaism * Fix indentation * Remove empty lines * Fix compilation.
This commit is contained in:
parent
d9f6aba308
commit
b9ceda38a6
19
Cargo.lock
generated
19
Cargo.lock
generated
@ -1677,6 +1677,11 @@ dependencies = [
|
|||||||
"tiny-keccak 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"tiny-keccak 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "nan-preserving-float"
|
||||||
|
version = "0.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "net2"
|
name = "net2"
|
||||||
version = "0.2.31"
|
version = "0.2.31"
|
||||||
@ -2485,7 +2490,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pwasm-utils"
|
name = "pwasm-utils"
|
||||||
version = "0.1.3"
|
version = "0.1.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
@ -3433,18 +3438,19 @@ dependencies = [
|
|||||||
"libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
|
"libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
"log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"parity-wasm 0.27.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
"parity-wasm 0.27.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"pwasm-utils 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"pwasm-utils 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"vm 0.1.0",
|
"vm 0.1.0",
|
||||||
"wasmi 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"wasmi 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasmi"
|
name = "wasmi"
|
||||||
version = "0.1.3"
|
version = "0.2.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"memory_units 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"memory_units 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"nan-preserving-float 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"parity-wasm 0.27.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
"parity-wasm 0.27.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -3673,6 +3679,7 @@ dependencies = [
|
|||||||
"checksum msdos_time 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "65ba9d75bcea84e07812618fedf284a64776c2f2ea0cad6bca7f69739695a958"
|
"checksum msdos_time 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "65ba9d75bcea84e07812618fedf284a64776c2f2ea0cad6bca7f69739695a958"
|
||||||
"checksum multibase 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b9c35dac080fd6e16a99924c8dfdef0af89d797dd851adab25feaffacf7850d6"
|
"checksum multibase 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b9c35dac080fd6e16a99924c8dfdef0af89d797dd851adab25feaffacf7850d6"
|
||||||
"checksum multihash 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7d49add5f49eb08bfc4d01ff286b84a48f53d45314f165c2d6efe477222d24f3"
|
"checksum multihash 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7d49add5f49eb08bfc4d01ff286b84a48f53d45314f165c2d6efe477222d24f3"
|
||||||
|
"checksum nan-preserving-float 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "34d4f00fcc2f4c9efa8cc971db0da9e28290e28e97af47585e48691ef10ff31f"
|
||||||
"checksum net2 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)" = "3a80f842784ef6c9a958b68b7516bc7e35883c614004dd94959a4dca1b716c09"
|
"checksum net2 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)" = "3a80f842784ef6c9a958b68b7516bc7e35883c614004dd94959a4dca1b716c09"
|
||||||
"checksum nodrop 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "9a2228dca57108069a5262f2ed8bd2e82496d2e074a06d1ccc7ce1687b6ae0a2"
|
"checksum nodrop 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "9a2228dca57108069a5262f2ed8bd2e82496d2e074a06d1ccc7ce1687b6ae0a2"
|
||||||
"checksum ntp 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "143149743832c6543b60a8ef2a26cd9122dfecec2b767158e852a7beecf6d7a0"
|
"checksum ntp 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "143149743832c6543b60a8ef2a26cd9122dfecec2b767158e852a7beecf6d7a0"
|
||||||
@ -3713,7 +3720,7 @@ dependencies = [
|
|||||||
"checksum primal-sieve 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "c0911abe7b63ddec27527ba7579c3017f645eb992be6ddbfad605e34aca01876"
|
"checksum primal-sieve 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "c0911abe7b63ddec27527ba7579c3017f645eb992be6ddbfad605e34aca01876"
|
||||||
"checksum protobuf 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "568a15e4d572d9a5e63ae3a55f84328c984842887db179b40b4cc6a608bac6a4"
|
"checksum protobuf 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "568a15e4d572d9a5e63ae3a55f84328c984842887db179b40b4cc6a608bac6a4"
|
||||||
"checksum pulldown-cmark 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8361e81576d2e02643b04950e487ec172b687180da65c731c03cf336784e6c07"
|
"checksum pulldown-cmark 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8361e81576d2e02643b04950e487ec172b687180da65c731c03cf336784e6c07"
|
||||||
"checksum pwasm-utils 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "54d440c3b56eee028aa5d4f18cbed8c6e0c9ae23563b93f344beb7e73854ea02"
|
"checksum pwasm-utils 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d51e9954a77aab7b4b606dc315a49cbed187924f163b6750cdf6d5677dbf0839"
|
||||||
"checksum quasi 0.32.0 (registry+https://github.com/rust-lang/crates.io-index)" = "18c45c4854d6d1cf5d531db97c75880feb91c958b0720f4ec1057135fec358b3"
|
"checksum quasi 0.32.0 (registry+https://github.com/rust-lang/crates.io-index)" = "18c45c4854d6d1cf5d531db97c75880feb91c958b0720f4ec1057135fec358b3"
|
||||||
"checksum quasi_codegen 0.32.0 (registry+https://github.com/rust-lang/crates.io-index)" = "51b9e25fa23c044c1803f43ca59c98dac608976dd04ce799411edd58ece776d4"
|
"checksum quasi_codegen 0.32.0 (registry+https://github.com/rust-lang/crates.io-index)" = "51b9e25fa23c044c1803f43ca59c98dac608976dd04ce799411edd58ece776d4"
|
||||||
"checksum quasi_macros 0.32.0 (registry+https://github.com/rust-lang/crates.io-index)" = "29cec87bc2816766d7e4168302d505dd06b0a825aed41b00633d296e922e02dd"
|
"checksum quasi_macros 0.32.0 (registry+https://github.com/rust-lang/crates.io-index)" = "29cec87bc2816766d7e4168302d505dd06b0a825aed41b00633d296e922e02dd"
|
||||||
@ -3814,7 +3821,7 @@ dependencies = [
|
|||||||
"checksum vergen 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c3365f36c57e5df714a34be40902b27a992eeddb9996eca52d0584611cf885d"
|
"checksum vergen 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c3365f36c57e5df714a34be40902b27a992eeddb9996eca52d0584611cf885d"
|
||||||
"checksum version_check 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6b772017e347561807c1aa192438c5fd74242a670a6cffacc40f2defd1dc069d"
|
"checksum version_check 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6b772017e347561807c1aa192438c5fd74242a670a6cffacc40f2defd1dc069d"
|
||||||
"checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
|
"checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
|
||||||
"checksum wasmi 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d19da510b59247935ad5f598357b3cc739912666d75d3d28318026478d95bbdb"
|
"checksum wasmi 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "46df76793c28cd8f590d5667f540a81c1c245440a17b03560e381226e27cf348"
|
||||||
"checksum webpki 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9e1622384bcb5458c6a3e3fa572f53ea8fef1cc85e535a2983dea87e9154fac2"
|
"checksum webpki 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9e1622384bcb5458c6a3e3fa572f53ea8fef1cc85e535a2983dea87e9154fac2"
|
||||||
"checksum webpki-roots 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "155d4060e5befdf3a6076bd28c22513473d9900b763c9e4521acc6f78a75415c"
|
"checksum webpki-roots 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "155d4060e5befdf3a6076bd28c22513473d9900b763c9e4521acc6f78a75415c"
|
||||||
"checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a"
|
"checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a"
|
||||||
|
@ -13,9 +13,9 @@
|
|||||||
"eip150Transition": "0x0",
|
"eip150Transition": "0x0",
|
||||||
"eip160Transition": "0x0",
|
"eip160Transition": "0x0",
|
||||||
"ecip1017EraRounds": 10000000,
|
"ecip1017EraRounds": 10000000,
|
||||||
|
|
||||||
"eip161abcTransition": "0x7fffffffffffffff",
|
"eip161abcTransition": "0x7fffffffffffffff",
|
||||||
"eip161dTransition": "0x7fffffffffffffff"
|
"eip161dTransition": "0x7fffffffffffffff",
|
||||||
|
"eip100bTransition": 2000000
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -29,7 +29,12 @@
|
|||||||
"chainID": "0x40",
|
"chainID": "0x40",
|
||||||
"eip155Transition": "0x0",
|
"eip155Transition": "0x0",
|
||||||
"eip98Transition": "0x7fffffffffffff",
|
"eip98Transition": "0x7fffffffffffff",
|
||||||
"eip86Transition": "0x7fffffffffffff"
|
"eip86Transition": "0x7fffffffffffff",
|
||||||
|
"wasmActivationTransition": 2000000,
|
||||||
|
"eip140Transition": 2000000,
|
||||||
|
"eip211Transition": 2000000,
|
||||||
|
"eip214Transition": 2000000,
|
||||||
|
"eip658Transition": 2000000
|
||||||
},
|
},
|
||||||
"genesis": {
|
"genesis": {
|
||||||
"seal": {
|
"seal": {
|
||||||
@ -67,6 +72,10 @@
|
|||||||
"0000000000000000000000000000000000000001": { "builtin": { "name": "ecrecover", "pricing": { "linear": { "base": 3000, "word": 0 } } } },
|
"0000000000000000000000000000000000000001": { "builtin": { "name": "ecrecover", "pricing": { "linear": { "base": 3000, "word": 0 } } } },
|
||||||
"0000000000000000000000000000000000000002": { "builtin": { "name": "sha256", "pricing": { "linear": { "base": 60, "word": 12 } } } },
|
"0000000000000000000000000000000000000002": { "builtin": { "name": "sha256", "pricing": { "linear": { "base": 60, "word": 12 } } } },
|
||||||
"0000000000000000000000000000000000000003": { "builtin": { "name": "ripemd160", "pricing": { "linear": { "base": 600, "word": 120 } } } },
|
"0000000000000000000000000000000000000003": { "builtin": { "name": "ripemd160", "pricing": { "linear": { "base": 600, "word": 120 } } } },
|
||||||
"0000000000000000000000000000000000000004": { "builtin": { "name": "identity", "pricing": { "linear": { "base": 15, "word": 3 } } } }
|
"0000000000000000000000000000000000000004": { "builtin": { "name": "identity", "pricing": { "linear": { "base": 15, "word": 3 } } } },
|
||||||
|
"0000000000000000000000000000000000000005": { "builtin": { "name": "modexp", "activate_at": 2000000, "pricing": { "modexp": { "divisor": 20 } } } },
|
||||||
|
"0000000000000000000000000000000000000006": { "builtin": { "name": "alt_bn128_add", "activate_at": 2000000, "pricing": { "linear": { "base": 500, "word": 0 } } } },
|
||||||
|
"0000000000000000000000000000000000000007": { "builtin": { "name": "alt_bn128_mul", "activate_at": 2000000, "pricing": { "linear": { "base": 40000, "word": 0 } } } },
|
||||||
|
"0000000000000000000000000000000000000008": { "builtin": { "name": "alt_bn128_pairing", "activate_at": 2000000, "pricing": { "alt_bn128_pairing": { "base": 100000, "pair": 80000 } } } }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -57,6 +57,12 @@ pub trait BlockProvider {
|
|||||||
/// (though not necessarily a part of the canon chain).
|
/// (though not necessarily a part of the canon chain).
|
||||||
fn is_known(&self, hash: &H256) -> bool;
|
fn is_known(&self, hash: &H256) -> bool;
|
||||||
|
|
||||||
|
/// Returns true if the given block is known and in the canon chain.
|
||||||
|
fn is_canon(&self, hash: &H256) -> bool {
|
||||||
|
let is_canon = || Some(hash == &self.block_hash(self.block_number(hash)?)?);
|
||||||
|
is_canon().unwrap_or(false)
|
||||||
|
}
|
||||||
|
|
||||||
/// Get the first block of the best part of the chain.
|
/// Get the first block of the best part of the chain.
|
||||||
/// Return `None` if there is no gap and the first block is the genesis.
|
/// Return `None` if there is no gap and the first block is the genesis.
|
||||||
/// Any queries of blocks which precede this one are not guaranteed to
|
/// Any queries of blocks which precede this one are not guaranteed to
|
||||||
@ -153,7 +159,7 @@ pub trait BlockProvider {
|
|||||||
fn blocks_with_bloom(&self, bloom: &Bloom, from_block: BlockNumber, to_block: BlockNumber) -> Vec<BlockNumber>;
|
fn blocks_with_bloom(&self, bloom: &Bloom, from_block: BlockNumber, to_block: BlockNumber) -> Vec<BlockNumber>;
|
||||||
|
|
||||||
/// Returns logs matching given filter.
|
/// Returns logs matching given filter.
|
||||||
fn logs<F>(&self, blocks: Vec<BlockNumber>, matches: F, limit: Option<usize>) -> Vec<LocalizedLogEntry>
|
fn logs<F>(&self, blocks: Vec<H256>, matches: F, limit: Option<usize>) -> Vec<LocalizedLogEntry>
|
||||||
where F: Fn(&LogEntry) -> bool + Send + Sync, Self: Sized;
|
where F: Fn(&LogEntry) -> bool + Send + Sync, Self: Sized;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -360,16 +366,18 @@ impl BlockProvider for BlockChain {
|
|||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn logs<F>(&self, mut blocks: Vec<BlockNumber>, matches: F, limit: Option<usize>) -> Vec<LocalizedLogEntry>
|
/// Returns logs matching given filter. The order of logs returned will be the same as the order of the blocks
|
||||||
|
/// provided. And it's the callers responsibility to sort blocks provided in advance.
|
||||||
|
fn logs<F>(&self, mut blocks: Vec<H256>, matches: F, limit: Option<usize>) -> Vec<LocalizedLogEntry>
|
||||||
where F: Fn(&LogEntry) -> bool + Send + Sync, Self: Sized {
|
where F: Fn(&LogEntry) -> bool + Send + Sync, Self: Sized {
|
||||||
// sort in reverse order
|
// sort in reverse order
|
||||||
blocks.sort_by(|a, b| b.cmp(a));
|
blocks.reverse();
|
||||||
|
|
||||||
let mut logs = blocks
|
let mut logs = blocks
|
||||||
.chunks(128)
|
.chunks(128)
|
||||||
.flat_map(move |blocks_chunk| {
|
.flat_map(move |blocks_chunk| {
|
||||||
blocks_chunk.into_par_iter()
|
blocks_chunk.into_par_iter()
|
||||||
.filter_map(|number| self.block_hash(*number).map(|hash| (*number, hash)))
|
.filter_map(|hash| self.block_number(&hash).map(|r| (r, hash)))
|
||||||
.filter_map(|(number, hash)| self.block_receipts(&hash).map(|r| (number, hash, r.receipts)))
|
.filter_map(|(number, hash)| self.block_receipts(&hash).map(|r| (number, hash, r.receipts)))
|
||||||
.filter_map(|(number, hash, receipts)| self.block_body(&hash).map(|ref b| (number, hash, receipts, b.transaction_hashes())))
|
.filter_map(|(number, hash, receipts)| self.block_body(&hash).map(|ref b| (number, hash, receipts, b.transaction_hashes())))
|
||||||
.flat_map(|(number, hash, mut receipts, mut hashes)| {
|
.flat_map(|(number, hash, mut receipts, mut hashes)| {
|
||||||
@ -396,7 +404,7 @@ impl BlockProvider for BlockChain {
|
|||||||
.enumerate()
|
.enumerate()
|
||||||
.map(move |(i, log)| LocalizedLogEntry {
|
.map(move |(i, log)| LocalizedLogEntry {
|
||||||
entry: log,
|
entry: log,
|
||||||
block_hash: hash,
|
block_hash: *hash,
|
||||||
block_number: number,
|
block_number: number,
|
||||||
transaction_hash: tx_hash,
|
transaction_hash: tx_hash,
|
||||||
// iterating in reverse order
|
// iterating in reverse order
|
||||||
@ -1957,17 +1965,33 @@ mod tests {
|
|||||||
value: 103.into(),
|
value: 103.into(),
|
||||||
data: "601080600c6000396000f3006000355415600957005b60203560003555".from_hex().unwrap(),
|
data: "601080600c6000396000f3006000355415600957005b60203560003555".from_hex().unwrap(),
|
||||||
}.sign(&secret(), None);
|
}.sign(&secret(), None);
|
||||||
|
let t4 = Transaction {
|
||||||
|
nonce: 0.into(),
|
||||||
|
gas_price: 0.into(),
|
||||||
|
gas: 100_000.into(),
|
||||||
|
action: Action::Create,
|
||||||
|
value: 104.into(),
|
||||||
|
data: "601080600c6000396000f3006000355415600957005b60203560003555".from_hex().unwrap(),
|
||||||
|
}.sign(&secret(), None);
|
||||||
let tx_hash1 = t1.hash();
|
let tx_hash1 = t1.hash();
|
||||||
let tx_hash2 = t2.hash();
|
let tx_hash2 = t2.hash();
|
||||||
let tx_hash3 = t3.hash();
|
let tx_hash3 = t3.hash();
|
||||||
|
let tx_hash4 = t4.hash();
|
||||||
|
|
||||||
let genesis = BlockBuilder::genesis();
|
let genesis = BlockBuilder::genesis();
|
||||||
let b1 = genesis.add_block_with_transactions(vec![t1, t2]);
|
let b1 = genesis.add_block_with_transactions(vec![t1, t2]);
|
||||||
let b2 = b1.add_block_with_transactions(iter::once(t3));
|
let b2 = b1.add_block_with_transactions(iter::once(t3));
|
||||||
|
let b3 = genesis.add_block_with(|| BlockOptions {
|
||||||
|
transactions: vec![t4.clone()],
|
||||||
|
difficulty: U256::from(9),
|
||||||
|
..Default::default()
|
||||||
|
}); // Branch block
|
||||||
let b1_hash = b1.last().hash();
|
let b1_hash = b1.last().hash();
|
||||||
let b1_number = b1.last().number();
|
let b1_number = b1.last().number();
|
||||||
let b2_hash = b2.last().hash();
|
let b2_hash = b2.last().hash();
|
||||||
let b2_number = b2.last().number();
|
let b2_number = b2.last().number();
|
||||||
|
let b3_hash = b3.last().hash();
|
||||||
|
let b3_number = b3.last().number();
|
||||||
|
|
||||||
let db = new_db();
|
let db = new_db();
|
||||||
let bc = new_chain(&genesis.last().encoded(), db.clone());
|
let bc = new_chain(&genesis.last().encoded(), db.clone());
|
||||||
@ -1998,10 +2022,21 @@ mod tests {
|
|||||||
],
|
],
|
||||||
}
|
}
|
||||||
]);
|
]);
|
||||||
|
insert_block(&db, &bc, &b3.last().encoded(), vec![
|
||||||
|
Receipt {
|
||||||
|
outcome: TransactionOutcome::StateRoot(H256::default()),
|
||||||
|
gas_used: 10_000.into(),
|
||||||
|
log_bloom: Default::default(),
|
||||||
|
logs: vec![
|
||||||
|
LogEntry { address: Default::default(), topics: vec![], data: vec![5], },
|
||||||
|
],
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
|
||||||
// when
|
// when
|
||||||
let logs1 = bc.logs(vec![1, 2], |_| true, None);
|
let logs1 = bc.logs(vec![b1_hash, b2_hash], |_| true, None);
|
||||||
let logs2 = bc.logs(vec![1, 2], |_| true, Some(1));
|
let logs2 = bc.logs(vec![b1_hash, b2_hash], |_| true, Some(1));
|
||||||
|
let logs3 = bc.logs(vec![b3_hash], |_| true, None);
|
||||||
|
|
||||||
// then
|
// then
|
||||||
assert_eq!(logs1, vec![
|
assert_eq!(logs1, vec![
|
||||||
@ -2053,6 +2088,17 @@ mod tests {
|
|||||||
log_index: 0,
|
log_index: 0,
|
||||||
}
|
}
|
||||||
]);
|
]);
|
||||||
|
assert_eq!(logs3, vec![
|
||||||
|
LocalizedLogEntry {
|
||||||
|
entry: LogEntry { address: Default::default(), topics: vec![], data: vec![5] },
|
||||||
|
block_hash: b3_hash,
|
||||||
|
block_number: b3_number,
|
||||||
|
transaction_hash: tx_hash4,
|
||||||
|
transaction_index: 0,
|
||||||
|
transaction_log_index: 0,
|
||||||
|
log_index: 0,
|
||||||
|
}
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
||||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
use std::collections::{HashSet, HashMap, BTreeMap, VecDeque};
|
use std::collections::{HashSet, HashMap, BTreeMap, BTreeSet, VecDeque};
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
use std::sync::{Arc, Weak};
|
use std::sync::{Arc, Weak};
|
||||||
use std::sync::atomic::{AtomicUsize, AtomicBool, Ordering as AtomicOrdering};
|
use std::sync::atomic::{AtomicUsize, AtomicBool, Ordering as AtomicOrdering};
|
||||||
@ -1666,23 +1666,83 @@ impl BlockChainClient for Client {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn logs(&self, filter: Filter) -> Vec<LocalizedLogEntry> {
|
fn logs(&self, filter: Filter) -> Vec<LocalizedLogEntry> {
|
||||||
let (from, to) = match (self.block_number_ref(&filter.from_block), self.block_number_ref(&filter.to_block)) {
|
// Wrap the logic inside a closure so that we can take advantage of question mark syntax.
|
||||||
(Some(from), Some(to)) => (from, to),
|
let fetch_logs = || {
|
||||||
_ => return Vec::new(),
|
let chain = self.chain.read();
|
||||||
|
|
||||||
|
// First, check whether `filter.from_block` and `filter.to_block` is on the canon chain. If so, we can use the
|
||||||
|
// optimized version.
|
||||||
|
let is_canon = |id| {
|
||||||
|
match id {
|
||||||
|
&BlockId::Pending => true,
|
||||||
|
// If it is referred by number, then it is always on the canon chain.
|
||||||
|
&BlockId::Earliest | &BlockId::Latest | &BlockId::Number(_) => true,
|
||||||
|
// If it is referred by hash, we see whether a hash -> number -> hash conversion gives us the same
|
||||||
|
// result.
|
||||||
|
&BlockId::Hash(ref hash) => chain.is_canon(hash),
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let chain = self.chain.read();
|
let blocks = if is_canon(&filter.from_block) && is_canon(&filter.to_block) {
|
||||||
let blocks = filter.bloom_possibilities().iter()
|
// If we are on the canon chain, use bloom filter to fetch required hashes.
|
||||||
.map(move |bloom| {
|
let from = self.block_number_ref(&filter.from_block)?;
|
||||||
|
let to = self.block_number_ref(&filter.to_block)?;
|
||||||
|
|
||||||
|
filter.bloom_possibilities().iter()
|
||||||
|
.map(|bloom| {
|
||||||
chain.blocks_with_bloom(bloom, from, to)
|
chain.blocks_with_bloom(bloom, from, to)
|
||||||
})
|
})
|
||||||
.flat_map(|m| m)
|
.flat_map(|m| m)
|
||||||
// remove duplicate elements
|
// remove duplicate elements
|
||||||
.collect::<HashSet<u64>>()
|
.collect::<BTreeSet<u64>>()
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.collect::<Vec<u64>>();
|
.filter_map(|n| chain.block_hash(n))
|
||||||
|
.collect::<Vec<H256>>()
|
||||||
|
|
||||||
self.chain.read().logs(blocks, |entry| filter.matches(entry), filter.limit)
|
} else {
|
||||||
|
// Otherwise, we use a slower version that finds a link between from_block and to_block.
|
||||||
|
let from_hash = Self::block_hash(&chain, &*self.miner, filter.from_block)?;
|
||||||
|
let from_number = chain.block_number(&from_hash)?;
|
||||||
|
let to_hash = Self::block_hash(&chain, &*self.miner, filter.from_block)?;
|
||||||
|
|
||||||
|
let blooms = filter.bloom_possibilities();
|
||||||
|
let bloom_match = |header: &encoded::Header| {
|
||||||
|
blooms.iter().any(|bloom| header.log_bloom().contains_bloom(bloom))
|
||||||
|
};
|
||||||
|
|
||||||
|
let (blocks, last_hash) = {
|
||||||
|
let mut blocks = Vec::new();
|
||||||
|
let mut current_hash = to_hash;
|
||||||
|
|
||||||
|
loop {
|
||||||
|
let header = chain.block_header_data(¤t_hash)?;
|
||||||
|
if bloom_match(&header) {
|
||||||
|
blocks.push(current_hash);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stop if `from` block is reached.
|
||||||
|
if header.number() <= from_number {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
current_hash = header.parent_hash();
|
||||||
|
}
|
||||||
|
|
||||||
|
blocks.reverse();
|
||||||
|
(blocks, current_hash)
|
||||||
|
};
|
||||||
|
|
||||||
|
// Check if we've actually reached the expected `from` block.
|
||||||
|
if last_hash != from_hash || blocks.is_empty() {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
blocks
|
||||||
|
};
|
||||||
|
|
||||||
|
Some(self.chain.read().logs(blocks, |entry| filter.matches(entry), filter.limit))
|
||||||
|
};
|
||||||
|
|
||||||
|
fetch_logs().unwrap_or_default()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn filter_traces(&self, filter: TraceFilter) -> Option<Vec<LocalizedTrace>> {
|
fn filter_traces(&self, filter: TraceFilter) -> Option<Vec<LocalizedTrace>> {
|
||||||
|
@ -21,7 +21,7 @@
|
|||||||
|
|
||||||
use std::cell::{RefCell, RefMut};
|
use std::cell::{RefCell, RefMut};
|
||||||
use std::collections::hash_map::Entry;
|
use std::collections::hash_map::Entry;
|
||||||
use std::collections::{HashMap, BTreeMap, HashSet};
|
use std::collections::{HashMap, BTreeMap, BTreeSet, HashSet};
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use hash::{KECCAK_NULL_RLP, KECCAK_EMPTY};
|
use hash::{KECCAK_NULL_RLP, KECCAK_EMPTY};
|
||||||
@ -833,40 +833,65 @@ impl<B: Backend> State<B> {
|
|||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return a list of all touched addresses in cache.
|
/// Populate a PodAccount map from this state, with another state as the account and storage query.
|
||||||
fn touched_addresses(&self) -> Vec<Address> {
|
pub fn to_pod_diff<X: Backend>(&mut self, query: &State<X>) -> trie::Result<PodState> {
|
||||||
assert!(self.checkpoints.borrow().is_empty());
|
assert!(self.checkpoints.borrow().is_empty());
|
||||||
self.cache.borrow().iter().map(|(add, _)| *add).collect()
|
|
||||||
|
// Merge PodAccount::to_pod for cache of self and `query`.
|
||||||
|
let all_addresses = self.cache.borrow().keys().cloned()
|
||||||
|
.chain(query.cache.borrow().keys().cloned())
|
||||||
|
.collect::<BTreeSet<_>>();
|
||||||
|
|
||||||
|
Ok(PodState::from(all_addresses.into_iter().fold(Ok(BTreeMap::new()), |m: trie::Result<_>, address| {
|
||||||
|
let mut m = m?;
|
||||||
|
|
||||||
|
let account = self.ensure_cached(&address, RequireCache::Code, true, |acc| {
|
||||||
|
acc.map(|acc| {
|
||||||
|
// Merge all modified storage keys.
|
||||||
|
let all_keys = {
|
||||||
|
let self_keys = acc.storage_changes().keys().cloned()
|
||||||
|
.collect::<BTreeSet<_>>();
|
||||||
|
|
||||||
|
if let Some(ref query_storage) = query.cache.borrow().get(&address)
|
||||||
|
.and_then(|opt| {
|
||||||
|
Some(opt.account.as_ref()?.storage_changes().keys().cloned()
|
||||||
|
.collect::<BTreeSet<_>>())
|
||||||
|
})
|
||||||
|
{
|
||||||
|
self_keys.union(&query_storage).cloned().collect::<Vec<_>>()
|
||||||
|
} else {
|
||||||
|
self_keys.into_iter().collect::<Vec<_>>()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Storage must be fetched after ensure_cached to avoid borrow problem.
|
||||||
|
(*acc.balance(), *acc.nonce(), all_keys, acc.code().map(|x| x.to_vec()))
|
||||||
|
})
|
||||||
|
})?;
|
||||||
|
|
||||||
|
if let Some((balance, nonce, storage_keys, code)) = account {
|
||||||
|
let storage = storage_keys.into_iter().fold(Ok(BTreeMap::new()), |s: trie::Result<_>, key| {
|
||||||
|
let mut s = s?;
|
||||||
|
|
||||||
|
s.insert(key, self.storage_at(&address, &key)?);
|
||||||
|
Ok(s)
|
||||||
|
})?;
|
||||||
|
|
||||||
|
m.insert(address, PodAccount {
|
||||||
|
balance, nonce, storage, code
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn query_pod(&mut self, query: &PodState, touched_addresses: &[Address]) -> trie::Result<()> {
|
Ok(m)
|
||||||
let pod = query.get();
|
})?))
|
||||||
|
|
||||||
for address in touched_addresses {
|
|
||||||
if !self.ensure_cached(address, RequireCache::Code, true, |a| a.is_some())? {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(pod_account) = pod.get(address) {
|
|
||||||
// needs to be split into two parts for the refcell code here
|
|
||||||
// to work.
|
|
||||||
for key in pod_account.storage.keys() {
|
|
||||||
self.storage_at(address, key)?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a `StateDiff` describing the difference from `orig` to `self`.
|
/// Returns a `StateDiff` describing the difference from `orig` to `self`.
|
||||||
/// Consumes self.
|
/// Consumes self.
|
||||||
pub fn diff_from<X: Backend>(&self, orig: State<X>) -> trie::Result<StateDiff> {
|
pub fn diff_from<X: Backend>(&self, mut orig: State<X>) -> trie::Result<StateDiff> {
|
||||||
let addresses_post = self.touched_addresses();
|
|
||||||
let pod_state_post = self.to_pod();
|
let pod_state_post = self.to_pod();
|
||||||
let mut state_pre = orig;
|
let pod_state_pre = orig.to_pod_diff(self)?;
|
||||||
state_pre.query_pod(&pod_state_post, &addresses_post)?;
|
Ok(pod_state::diff_pod(&pod_state_pre, &pod_state_post))
|
||||||
Ok(pod_state::diff_pod(&state_pre.to_pod(), &pod_state_post))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// load required account data from the databases.
|
// load required account data from the databases.
|
||||||
@ -2209,9 +2234,6 @@ mod tests {
|
|||||||
let original = state.clone();
|
let original = state.clone();
|
||||||
state.kill_account(&a);
|
state.kill_account(&a);
|
||||||
|
|
||||||
assert_eq!(original.touched_addresses(), vec![]);
|
|
||||||
assert_eq!(state.touched_addresses(), vec![a]);
|
|
||||||
|
|
||||||
let diff = state.diff_from(original).unwrap();
|
let diff = state.diff_from(original).unwrap();
|
||||||
let diff_map = diff.get();
|
let diff_map = diff.get();
|
||||||
assert_eq!(diff_map.len(), 1);
|
assert_eq!(diff_map.len(), 1);
|
||||||
@ -2224,4 +2246,42 @@ mod tests {
|
|||||||
storage: Default::default()
|
storage: Default::default()
|
||||||
}), None).as_ref());
|
}), None).as_ref());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn should_trace_diff_unmodified_storage() {
|
||||||
|
use pod_account;
|
||||||
|
|
||||||
|
let a = 10.into();
|
||||||
|
let db = get_temp_state_db();
|
||||||
|
|
||||||
|
let (root, db) = {
|
||||||
|
let mut state = State::new(db, U256::from(0), Default::default());
|
||||||
|
state.set_storage(&a, H256::from(&U256::from(1u64)), H256::from(&U256::from(20u64))).unwrap();
|
||||||
|
state.commit().unwrap();
|
||||||
|
state.drop()
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut state = State::from_existing(db, root, U256::from(0u8), Default::default()).unwrap();
|
||||||
|
let original = state.clone();
|
||||||
|
state.set_storage(&a, H256::from(&U256::from(1u64)), H256::from(&U256::from(100u64))).unwrap();
|
||||||
|
|
||||||
|
let diff = state.diff_from(original).unwrap();
|
||||||
|
let diff_map = diff.get();
|
||||||
|
assert_eq!(diff_map.len(), 1);
|
||||||
|
assert!(diff_map.get(&a).is_some());
|
||||||
|
assert_eq!(diff_map.get(&a),
|
||||||
|
pod_account::diff_pod(Some(&PodAccount {
|
||||||
|
balance: U256::zero(),
|
||||||
|
nonce: U256::zero(),
|
||||||
|
code: Some(Default::default()),
|
||||||
|
storage: vec![(H256::from(&U256::from(1u64)), H256::from(&U256::from(20u64)))]
|
||||||
|
.into_iter().collect(),
|
||||||
|
}), Some(&PodAccount {
|
||||||
|
balance: U256::zero(),
|
||||||
|
nonce: U256::zero(),
|
||||||
|
code: Some(Default::default()),
|
||||||
|
storage: vec![(H256::from(&U256::from(1u64)), H256::from(&U256::from(100u64)))]
|
||||||
|
.into_iter().collect(),
|
||||||
|
})).as_ref());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -458,7 +458,7 @@ mod tests {
|
|||||||
unimplemented!()
|
unimplemented!()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn logs<F>(&self, _blocks: Vec<BlockNumber>, _matches: F, _limit: Option<usize>) -> Vec<LocalizedLogEntry>
|
fn logs<F>(&self, _blocks: Vec<H256>, _matches: F, _limit: Option<usize>) -> Vec<LocalizedLogEntry>
|
||||||
where F: Fn(&LogEntry) -> bool, Self: Sized {
|
where F: Fn(&LogEntry) -> bool, Self: Sized {
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
}
|
}
|
||||||
|
@ -11,5 +11,5 @@ parity-wasm = "0.27"
|
|||||||
libc = "0.2"
|
libc = "0.2"
|
||||||
pwasm-utils = "0.1"
|
pwasm-utils = "0.1"
|
||||||
vm = { path = "../vm" }
|
vm = { path = "../vm" }
|
||||||
wasmi = { version = "0.1.3", features = ["opt-in-32bit"] }
|
|
||||||
ethcore-logger = { path = "../../logger" }
|
ethcore-logger = { path = "../../logger" }
|
||||||
|
wasmi = { version = "0.2" }
|
||||||
|
Loading…
Reference in New Issue
Block a user