forked from informalsystems/tendermint-rs
-
Notifications
You must be signed in to change notification settings - Fork 0
/
light_client.rs
121 lines (101 loc) · 3.32 KB
/
light_client.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
use std::{collections::HashMap, time::Duration};
use tendermint_light_client::{
components::{
io::{AtHeight, Io},
scheduler,
},
errors::Error,
light_client::LightClient,
state::State,
store::{memory::MemoryStore, LightStore},
tests::*,
verifier::{
operations::ProdHasher,
options::Options,
types::{LightBlock, Status},
ProdVerifier,
},
};
use tendermint_testgen::{light_block::default_peer_id, Tester};
// Link to JSON test files repo:
// https://github.com/informalsystems/conformance-tests
const TEST_FILES_PATH: &str = "./tests/support/";
struct BisectionTestResult {
untrusted_light_block: LightBlock,
new_states: Result<Vec<LightBlock>, Error>,
}
fn run_test(tc: LightClientTest<LightBlock>) -> BisectionTestResult {
let primary = default_peer_id();
let untrusted_height = tc.height_to_verify;
let trust_threshold = tc.trust_options.trust_level;
let trusting_period = tc.trust_options.period;
let now = tc.now;
// In Go, default is 10 sec.
// Once we switch to the proposer based timestamps, it will probably be a consensus parameter
let clock_drift = Duration::from_secs(10);
let clock = MockClock { now };
let options = Options {
trust_threshold,
trusting_period: trusting_period.into(),
clock_drift,
};
let provider = tc.primary;
let io = MockIo::new(provider.lite_blocks);
let trusted_height = tc.trust_options.height;
let trusted_state = io
.fetch_light_block(AtHeight::At(trusted_height))
.expect("could not 'request' light block");
let mut light_store = MemoryStore::new();
light_store.insert(trusted_state, Status::Trusted);
let mut state = State {
light_store: Box::new(light_store),
verification_trace: HashMap::new(),
};
let verifier = ProdVerifier::default();
let hasher = ProdHasher::default();
let mut light_client = LightClient::new(
primary,
options,
clock,
scheduler::basic_bisecting_schedule,
verifier,
hasher,
io.clone(),
);
let result = verify_bisection(untrusted_height, &mut light_client, &mut state);
let untrusted_light_block = io
.fetch_light_block(AtHeight::At(untrusted_height))
.expect("header at untrusted height not found");
BisectionTestResult {
untrusted_light_block,
new_states: result,
}
}
fn forward_test(tc: LightClientTest<LightBlock>) {
let expect_error = match &tc.expected_output {
Some(eo) => eo.eq("error"),
None => false,
};
let test_result = run_test(tc);
let expected_state = test_result.untrusted_light_block;
match test_result.new_states {
Ok(new_states) => {
assert_eq!(new_states[0].height(), expected_state.height());
assert_eq!(new_states[0], expected_state);
assert!(!expect_error);
},
Err(e) => {
if !expect_error {
dbg!(e);
}
assert!(expect_error);
},
}
}
#[test]
fn run_tests() {
let mut tester = Tester::new("light client verification", TEST_FILES_PATH);
tester.add_test("forward verification with bisection", forward_test);
tester.run_foreach_in_dir("bisection/single_peer");
tester.finalize();
}