This repository has been archived by the owner on Nov 6, 2020. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 1.7k
RPC: parity_getBlockReceipts #9527
Merged
Merged
Changes from all commits
Commits
Show all changes
11 commits
Select commit
Hold shift + click to select a range
f8742e4
Block receipts RPC.
tomusdrw 4311b4e
Merge branch 'master' into td-blockreceipts
tomusdrw 799d56c
Use lazy evaluation of block receipts (ecrecover).
tomusdrw 1dd3b94
Optimize transaction_receipt to prevent performance regression.
tomusdrw a066b53
Merge branch 'master' into td-blockreceipts
tomusdrw 7619f30
Merge branch 'master' into td-blockreceipts
tomusdrw fd3e7be
Fix RPC grumbles.
tomusdrw f287e58
Add block & transaction receipt tests.
tomusdrw 8bb8e78
Fix conversion to block id.
tomusdrw 87de315
Merge branch 'master' into td-blockreceipts
tomusdrw 14c50f6
Merge branch 'master' into td-blockreceipts
debris File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1783,26 +1783,49 @@ impl BlockChainClient for Client { | |
} | ||
|
||
fn transaction_receipt(&self, id: TransactionId) -> Option<LocalizedReceipt> { | ||
// NOTE Don't use block_receipts here for performance reasons | ||
let address = self.transaction_address(id)?; | ||
let hash = address.block_hash; | ||
let chain = self.chain.read(); | ||
self.transaction_address(id) | ||
.and_then(|address| chain.block_number(&address.block_hash).and_then(|block_number| { | ||
let transaction = chain.block_body(&address.block_hash) | ||
.and_then(|body| body.view().localized_transaction_at(&address.block_hash, block_number, address.index)); | ||
|
||
let previous_receipts = (0..address.index + 1) | ||
.map(|index| { | ||
let mut address = address.clone(); | ||
address.index = index; | ||
chain.transaction_receipt(&address) | ||
}) | ||
.collect(); | ||
match (transaction, previous_receipts) { | ||
(Some(transaction), Some(previous_receipts)) => { | ||
Some(transaction_receipt(self.engine().machine(), transaction, previous_receipts)) | ||
}, | ||
_ => None, | ||
} | ||
})) | ||
let number = chain.block_number(&hash)?; | ||
let body = chain.block_body(&hash)?; | ||
let mut receipts = chain.block_receipts(&hash)?.receipts; | ||
receipts.truncate(address.index + 1); | ||
|
||
let transaction = body.view().localized_transaction_at(&hash, number, address.index)?; | ||
let receipt = receipts.pop()?; | ||
let gas_used = receipts.last().map_or_else(|| 0.into(), |r| r.gas_used); | ||
let no_of_logs = receipts.into_iter().map(|receipt| receipt.logs.len()).sum::<usize>(); | ||
|
||
let receipt = transaction_receipt(self.engine().machine(), transaction, receipt, gas_used, no_of_logs); | ||
Some(receipt) | ||
} | ||
|
||
fn block_receipts(&self, id: BlockId) -> Option<Vec<LocalizedReceipt>> { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This method could probably use a test. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Added for both |
||
let hash = self.block_hash(id)?; | ||
|
||
let chain = self.chain.read(); | ||
let receipts = chain.block_receipts(&hash)?; | ||
let number = chain.block_number(&hash)?; | ||
let body = chain.block_body(&hash)?; | ||
let engine = self.engine.clone(); | ||
|
||
let mut gas_used = 0.into(); | ||
let mut no_of_logs = 0; | ||
|
||
Some(body | ||
.view() | ||
.localized_transactions(&hash, number) | ||
.into_iter() | ||
.zip(receipts.receipts) | ||
.map(move |(transaction, receipt)| { | ||
let result = transaction_receipt(engine.machine(), transaction, receipt, gas_used, no_of_logs); | ||
gas_used = result.cumulative_gas_used; | ||
no_of_logs += result.logs.len(); | ||
result | ||
}) | ||
.collect() | ||
) | ||
} | ||
|
||
fn tree_route(&self, from: &H256, to: &H256) -> Option<TreeRoute> { | ||
|
@@ -1821,7 +1844,7 @@ impl BlockChainClient for Client { | |
self.state_db.read().journal_db().state(hash) | ||
} | ||
|
||
fn block_receipts(&self, hash: &H256) -> Option<Bytes> { | ||
fn encoded_block_receipts(&self, hash: &H256) -> Option<Bytes> { | ||
self.chain.read().block_receipts(hash).map(|receipts| ::rlp::encode(&receipts).into_vec()) | ||
} | ||
|
||
|
@@ -2376,16 +2399,14 @@ impl Drop for Client { | |
|
||
/// Returns `LocalizedReceipt` given `LocalizedTransaction` | ||
/// and a vector of receipts from given block up to transaction index. | ||
fn transaction_receipt(machine: &::machine::EthereumMachine, mut tx: LocalizedTransaction, mut receipts: Vec<Receipt>) -> LocalizedReceipt { | ||
assert_eq!(receipts.len(), tx.transaction_index + 1, "All previous receipts are provided."); | ||
|
||
fn transaction_receipt( | ||
machine: &::machine::EthereumMachine, | ||
mut tx: LocalizedTransaction, | ||
receipt: Receipt, | ||
prior_gas_used: U256, | ||
prior_no_of_logs: usize, | ||
) -> LocalizedReceipt { | ||
let sender = tx.sender(); | ||
let receipt = receipts.pop().expect("Current receipt is provided; qed"); | ||
let prior_gas_used = match tx.transaction_index { | ||
0 => 0.into(), | ||
i => receipts.get(i - 1).expect("All previous receipts are provided; qed").gas_used, | ||
}; | ||
let no_of_logs = receipts.into_iter().map(|receipt| receipt.logs.len()).sum::<usize>(); | ||
let transaction_hash = tx.hash(); | ||
let block_hash = tx.block_hash; | ||
let block_number = tx.block_number; | ||
|
@@ -2414,7 +2435,7 @@ fn transaction_receipt(machine: &::machine::EthereumMachine, mut tx: LocalizedTr | |
transaction_hash: transaction_hash, | ||
transaction_index: transaction_index, | ||
transaction_log_index: i, | ||
log_index: no_of_logs + i, | ||
log_index: prior_no_of_logs + i, | ||
}).collect(), | ||
log_bloom: receipt.log_bloom, | ||
outcome: receipt.outcome, | ||
|
@@ -2462,6 +2483,33 @@ mod tests { | |
assert!(client.tree_route(&genesis, &new_hash).is_none()); | ||
} | ||
|
||
#[test] | ||
fn should_return_block_receipts() { | ||
use client::{BlockChainClient, BlockId, TransactionId}; | ||
use test_helpers::{generate_dummy_client_with_data}; | ||
|
||
let client = generate_dummy_client_with_data(2, 2, &[1.into(), 1.into()]); | ||
let receipts = client.block_receipts(BlockId::Latest).unwrap(); | ||
|
||
assert_eq!(receipts.len(), 2); | ||
assert_eq!(receipts[0].transaction_index, 0); | ||
assert_eq!(receipts[0].block_number, 2); | ||
assert_eq!(receipts[0].cumulative_gas_used, 53_000.into()); | ||
assert_eq!(receipts[0].gas_used, 53_000.into()); | ||
|
||
assert_eq!(receipts[1].transaction_index, 1); | ||
assert_eq!(receipts[1].block_number, 2); | ||
assert_eq!(receipts[1].cumulative_gas_used, 106_000.into()); | ||
assert_eq!(receipts[1].gas_used, 53_000.into()); | ||
|
||
|
||
let receipt = client.transaction_receipt(TransactionId::Hash(receipts[0].transaction_hash)); | ||
assert_eq!(receipt, Some(receipts[0].clone())); | ||
|
||
let receipt = client.transaction_receipt(TransactionId::Hash(receipts[1].transaction_hash)); | ||
assert_eq!(receipt, Some(receipts[1].clone())); | ||
} | ||
|
||
#[test] | ||
fn should_return_correct_log_index() { | ||
use hash::keccak; | ||
|
@@ -2505,20 +2553,15 @@ mod tests { | |
topics: vec![], | ||
data: vec![], | ||
}]; | ||
let receipts = vec![Receipt { | ||
outcome: TransactionOutcome::StateRoot(state_root), | ||
gas_used: 5.into(), | ||
log_bloom: Default::default(), | ||
logs: vec![logs[0].clone()], | ||
}, Receipt { | ||
let receipt = Receipt { | ||
outcome: TransactionOutcome::StateRoot(state_root), | ||
gas_used: gas_used, | ||
log_bloom: Default::default(), | ||
logs: logs.clone(), | ||
}]; | ||
}; | ||
|
||
// when | ||
let receipt = transaction_receipt(&machine, transaction, receipts); | ||
let receipt = transaction_receipt(&machine, transaction, receipt, 5.into(), 1); | ||
|
||
// then | ||
assert_eq!(receipt, LocalizedReceipt { | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't understand these 3 lines. why do we pop a receipt and then take a
gas_used
from the one before it?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So to actually generate a
LocalizedReceipt
we need 3 things:So the logic is as follows:
index
(inclusive)receipts.pop()
; point 1.)current.gas_used - previous.gas_used
to figure out whatcurrent
gas usage of transaction was)