Skip to content

Commit

Permalink
Implement include_events in get_transactions/get_account_transactions
Browse files Browse the repository at this point in the history
Closes: diem#2874
Approved by: phoenix-antigravity
  • Loading branch information
thefallentree authored and DavidLDill committed Mar 13, 2020
1 parent 1709a6e commit c046e2c
Show file tree
Hide file tree
Showing 4 changed files with 193 additions and 65 deletions.
58 changes: 48 additions & 10 deletions json-rpc/src/methods.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,10 +103,30 @@ async fn get_transactions(

let mut result = vec![];

let all_events = if include_events {
txs.events
.ok_or_else(|| format_err!("Storage layer didn't return events when requested!"))?
} else {
vec![]
};

for (v, tx) in txs.transactions.into_iter().enumerate() {
let events = if include_events {
all_events
.get(v)
.ok_or_else(|| format_err!("Missing events for version: {}", v))?
.iter()
.cloned()
.map(|x| (start_version + v as u64, x).into())
.collect()
} else {
vec![]
};

result.push(TransactionView {
version: start_version + v as u64,
transaction: tx.into(),
events,
});
}
Ok(result)
Expand All @@ -123,18 +143,36 @@ async fn get_account_transaction(

let account = AccountAddress::try_from(p_account)?;

Ok(service
let version = service.db.get_latest_version()?;

let tx = service
.db
.get_txn_by_account(
account,
sequence,
service.db.get_latest_version()?,
include_events,
)?
.map(|tx| TransactionView {
version: tx.version,
.get_txn_by_account(account, sequence, version, include_events)?;

if let Some(tx) = tx {
if include_events {
ensure!(
tx.events.is_some(),
"Storage layer didn't return events when requested!"
);
}
let tx_version = tx.version;

let events = tx
.events
.unwrap_or_default()
.into_iter()
.map(|x| ((tx_version, x).into()))
.collect();

Ok(Some(TransactionView {
version: tx_version,
transaction: tx.transaction.into(),
events,
}))
} else {
Ok(None)
}
}

/// Returns events by given access path
Expand All @@ -148,7 +186,7 @@ async fn get_events(service: JsonRpcService, params: Vec<Value>) -> Result<Vec<E

let mut events = vec![];
for (version, event) in events_with_proof {
events.push(EventView::try_from((version, event))?);
events.push((version, event).into());
}
Ok(events)
}
Expand Down
41 changes: 34 additions & 7 deletions json-rpc/src/tests/mock_db.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,22 +54,34 @@ impl LibraDBTrait for MockLibraDB {
address: AccountAddress,
seq_num: u64,
_ledger_version: u64,
_fetch_events: bool,
fetch_events: bool,
) -> Result<Option<TransactionWithProof>, Error> {
Ok(self
.all_txns
.iter()
.find(|x| {
.enumerate()
.find(|(_, x)| {
if let Ok(t) = x.as_signed_user_txn() {
t.sender() == address && t.sequence_number() == seq_num
} else {
false
}
})
.map(|x| TransactionWithProof {
version: 0,
.map(|(v, x)| TransactionWithProof {
version: v as u64,
transaction: x.clone(),
events: None,
events: if fetch_events {
Some(
self.events
.iter()
.filter(|(ev, _)| *ev == v as u64)
.map(|(_, e)| e)
.cloned()
.collect(),
)
} else {
None
},
proof: TransactionProof::new(
TransactionAccumulatorProof::new(vec![]),
TransactionInfo::new(
Expand All @@ -92,7 +104,7 @@ impl LibraDBTrait for MockLibraDB {
start_version: u64,
limit: u64,
_ledger_version: u64,
_fetch_events: bool,
fetch_events: bool,
) -> Result<TransactionListWithProof, Error> {
let transactions: Vec<Transaction> = self
.all_txns
Expand All @@ -104,7 +116,22 @@ impl LibraDBTrait for MockLibraDB {
let first_transaction_version = transactions.first().map(|_| start_version);
Ok(TransactionListWithProof {
transactions,
events: None,
events: if fetch_events {
Some(
(start_version..start_version + limit)
.map(|version| {
self.events
.iter()
.filter(|(v, _)| *v == version)
.map(|(_, e)| e)
.cloned()
.collect()
})
.collect(),
)
} else {
None
},
first_transaction_version,
proof: TransactionListProof::new_empty(),
})
Expand Down
110 changes: 82 additions & 28 deletions json-rpc/src/tests/unit_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,11 @@ use crate::{
client::{JsonRpcAsyncClient, JsonRpcBatch, JsonRpcResponse},
runtime::bootstrap,
tests::mock_db::MockLibraDB,
views::{BlockMetadata, EventView, StateProofView, TransactionDataView, TransactionView},
views::{
BlockMetadata, BytesView, EventView, StateProofView, TransactionDataView, TransactionView,
},
};
use anyhow::format_err;
use futures::{channel::mpsc::channel, StreamExt};
use hex;
use libra_config::utils;
Expand Down Expand Up @@ -323,7 +326,7 @@ fn test_get_transactions_impl(blocks: Vec<(Vec<TransactionToCommit>, LedgerInfoW
let page = 800usize;

for base_version in (0..version).map(u64::from).take(page).collect::<Vec<_>>() {
let request = serde_json::json!({"jsonrpc": "2.0", "method": "get_transactions", "params": [base_version, page as u64, false], "id": 1});
let request = serde_json::json!({"jsonrpc": "2.0", "method": "get_transactions", "params": [base_version, page as u64, true], "id": 1});
let resp = client.post(&url).json(&request).send().unwrap();
assert_eq!(resp.status(), 200);
let data = fetch_result(resp.json().unwrap());
Expand All @@ -341,29 +344,50 @@ fn test_get_transactions_impl(blocks: Vec<(Vec<TransactionToCommit>, LedgerInfoW
Some(version)
);
let tx = &mock_db.all_txns[version as usize];
let view = response.as_object().unwrap().get("transaction").unwrap();

let view: TransactionView =
serde_json::from_value(response.clone()).expect("Invalid result");

// Check we returned correct events
let expected_events = mock_db
.events
.iter()
.filter(|(v, _)| *v == view.version)
.map(|(_, e)| e)
.collect::<Vec<_>>();

assert_eq!(expected_events.len(), view.events.len());

for (i, event_view) in view.events.iter().enumerate() {
let expected_event =
expected_events.get(i).expect("Expected event didn't find");
assert_eq!(event_view.sequence_number, expected_event.sequence_number());
assert_eq!(event_view.transaction_version, version);
assert_eq!(
event_view.key.0,
BytesView::from(expected_event.key().as_bytes()).0
);
// TODO: check event_data
}

match tx {
Transaction::BlockMetadata(t) => {
assert_eq!(
"blockmetadata",
view.get("type").unwrap().as_str().unwrap()
);
assert_eq!(
t.clone().into_inner().unwrap().1,
view.get("timestamp_usecs").unwrap().as_u64().unwrap()
);
}
Transaction::WriteSet(_) => {
assert_eq!("writeset", view.get("type").unwrap().as_str().unwrap());
}
Transaction::UserTransaction(t) => {
assert_eq!("user", view.get("type").unwrap().as_str().unwrap());
assert_eq!(
t.sender().to_string(),
view.get("sender").unwrap().as_str().unwrap()
);
// TODO: verify every field
}
Transaction::BlockMetadata(t) => match view.transaction {
TransactionDataView::BlockMetadata { timestamp_usecs } => {
assert_eq!(t.clone().into_inner().unwrap().1, timestamp_usecs);
}
_ => panic!("Returned value doesn't match!"),
},
Transaction::WriteSet(_) => match view.transaction {
TransactionDataView::WriteSet { .. } => {}
_ => panic!("Returned value doesn't match!"),
},
Transaction::UserTransaction(t) => match view.transaction {
TransactionDataView::UserTransaction { sender, .. } => {
assert_eq!(t.sender().to_string(), sender);
// TODO: verify every field
}
_ => panic!("Returned value doesn't match!"),
},
}
}
}
Expand Down Expand Up @@ -412,14 +436,38 @@ fn test_get_account_transaction_impl(
let ar = AccountResource::try_from(blob).unwrap();
for seq in 1..ar.sequence_number() {
let p_addr = String::from(acc);
let request = serde_json::json!({"jsonrpc": "2.0", "method": "get_account_transaction", "params": [p_addr, seq, false], "id": 1});
let request = serde_json::json!({"jsonrpc": "2.0", "method": "get_account_transaction", "params": [p_addr, seq, true], "id": 1});
let resp = client.post(&url).json(&request).send().unwrap();
assert_eq!(resp.status(), 200);

let data: Option<TransactionView> = fetch_data(resp);
let view = data.unwrap().transaction;
let tx_view = data.expect("Transaction didn't exists!");

// Check we returned correct events
let expected_events = mock_db
.events
.iter()
.filter(|(ev, _)| *ev == tx_view.version)
.map(|(_, e)| e)
.collect::<Vec<_>>();

assert_eq!(tx_view.events.len(), expected_events.len());

for (i, event_view) in tx_view.events.iter().enumerate() {
let expected_event = expected_events.get(i).expect("Expected event didn't find");
assert_eq!(event_view.sequence_number, expected_event.sequence_number());
assert_eq!(event_view.transaction_version, tx_view.version);
assert_eq!(
event_view.key.0,
BytesView::from(expected_event.key().as_bytes()).0
);
// TODO: check event_data
}

let tx_data_view = tx_view.transaction;

// Always user transaction
match view {
match tx_data_view {
TransactionDataView::UserTransaction {
sender,
sequence_number,
Expand All @@ -443,7 +491,13 @@ where
}

fn fetch_result(data: JsonMap) -> Value {
let result: Value = serde_json::from_value(data.get("result").unwrap().clone()).unwrap();
let result: Value = serde_json::from_value(
data.get("result")
.ok_or_else(|| format_err!("Unexpected response: {:?}", data))
.unwrap()
.clone(),
)
.unwrap();
assert_eq!(
data.get("jsonrpc").unwrap(),
&serde_json::Value::String("2.0".to_string())
Expand Down
Loading

0 comments on commit c046e2c

Please sign in to comment.