enforce validity of on_demand requests
This commit is contained in:
parent
9524ebbff1
commit
b37124991c
@ -43,8 +43,6 @@ pub enum Error {
|
|||||||
Canceled,
|
Canceled,
|
||||||
/// No suitable peers available to serve the request.
|
/// No suitable peers available to serve the request.
|
||||||
NoPeersAvailable,
|
NoPeersAvailable,
|
||||||
/// Invalid request.
|
|
||||||
InvalidRequest,
|
|
||||||
/// Request timed out.
|
/// Request timed out.
|
||||||
TimedOut,
|
TimedOut,
|
||||||
}
|
}
|
||||||
@ -95,6 +93,7 @@ enum Pending {
|
|||||||
pub struct OnDemand {
|
pub struct OnDemand {
|
||||||
peers: RwLock<HashMap<PeerId, Peer>>,
|
peers: RwLock<HashMap<PeerId, Peer>>,
|
||||||
pending_requests: RwLock<HashMap<ReqId, Pending>>,
|
pending_requests: RwLock<HashMap<ReqId, Pending>>,
|
||||||
|
orphaned_requests: RwLock<Vec<Pending>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for OnDemand {
|
impl Default for OnDemand {
|
||||||
@ -102,6 +101,7 @@ impl Default for OnDemand {
|
|||||||
OnDemand {
|
OnDemand {
|
||||||
peers: RwLock::new(HashMap::new()),
|
peers: RwLock::new(HashMap::new()),
|
||||||
pending_requests: RwLock::new(HashMap::new()),
|
pending_requests: RwLock::new(HashMap::new()),
|
||||||
|
orphaned_requests: RwLock::new(Vec::new()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -117,20 +117,13 @@ impl OnDemand {
|
|||||||
|
|
||||||
// dispatch the request, completing the request if no peers available.
|
// dispatch the request, completing the request if no peers available.
|
||||||
fn dispatch_header_by_number(&self, ctx: &BasicContext, req: request::HeaderByNumber, sender: Sender<(encoded::Header, U256)>) {
|
fn dispatch_header_by_number(&self, ctx: &BasicContext, req: request::HeaderByNumber, sender: Sender<(encoded::Header, U256)>) {
|
||||||
let num = req.num;
|
let num = req.num();
|
||||||
let cht_num = match ::cht::block_to_cht_number(req.num) {
|
let cht_num = req.cht_num();
|
||||||
Some(cht_num) => cht_num,
|
|
||||||
None => {
|
|
||||||
warn!(target: "on_demand", "Attempted to dispatch invalid header proof: req.num == 0");
|
|
||||||
sender.complete(Err(Error::InvalidRequest));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let les_req = LesRequest::HeaderProofs(les_request::HeaderProofs {
|
let les_req = LesRequest::HeaderProofs(les_request::HeaderProofs {
|
||||||
requests: vec![les_request::HeaderProof {
|
requests: vec![les_request::HeaderProof {
|
||||||
cht_number: cht_num,
|
cht_number: cht_num,
|
||||||
block_number: req.num,
|
block_number: num,
|
||||||
from_level: 0,
|
from_level: 0,
|
||||||
}],
|
}],
|
||||||
});
|
});
|
||||||
|
@ -59,12 +59,33 @@ impl From<Box<TrieError>> for Error {
|
|||||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
pub struct HeaderByNumber {
|
pub struct HeaderByNumber {
|
||||||
/// The header's number.
|
/// The header's number.
|
||||||
pub num: u64,
|
num: u64,
|
||||||
|
/// The cht number for the given block number.
|
||||||
|
cht_num: u64,
|
||||||
/// The root of the CHT containing this header.
|
/// The root of the CHT containing this header.
|
||||||
pub cht_root: H256,
|
cht_root: H256,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl HeaderByNumber {
|
impl HeaderByNumber {
|
||||||
|
/// Construct a new header-by-number request. Fails if the given number is 0.
|
||||||
|
/// Provide the expected CHT root to compare against.
|
||||||
|
pub fn new(num: u64, cht_root: H256) -> Option<Self> {
|
||||||
|
::cht::block_to_cht_number(num).map(|cht_num| HeaderByNumber {
|
||||||
|
num: num,
|
||||||
|
cht_num: cht_num,
|
||||||
|
cht_root: cht_root,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Access the requested block number.
|
||||||
|
pub fn num(&self) -> u64 { self.num }
|
||||||
|
|
||||||
|
/// Access the CHT number.
|
||||||
|
pub fn cht_num(&self) -> u64 { self.cht_num }
|
||||||
|
|
||||||
|
/// Access the expected CHT root.
|
||||||
|
pub fn cht_root(&self) -> H256 { self.cht_root }
|
||||||
|
|
||||||
/// Check a response with a header and cht proof.
|
/// Check a response with a header and cht proof.
|
||||||
pub fn check_response(&self, header: &[u8], proof: &[Bytes]) -> Result<(encoded::Header, U256), Error> {
|
pub fn check_response(&self, header: &[u8], proof: &[Bytes]) -> Result<(encoded::Header, U256), Error> {
|
||||||
let (expected_hash, td) = match ::cht::check_proof(proof, self.num, self.cht_root) {
|
let (expected_hash, td) = match ::cht::check_proof(proof, self.num, self.cht_root) {
|
||||||
@ -222,6 +243,11 @@ mod tests {
|
|||||||
use ethcore::encoded;
|
use ethcore::encoded;
|
||||||
use ethcore::receipt::Receipt;
|
use ethcore::receipt::Receipt;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn no_invalid_header_by_number() {
|
||||||
|
assert!(HeaderByNumber::new(0, Default::default()).is_none())
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn check_header_by_number() {
|
fn check_header_by_number() {
|
||||||
use ::cht;
|
use ::cht;
|
||||||
@ -244,10 +270,7 @@ mod tests {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let proof = cht.prove(10_000, 0).unwrap().unwrap();
|
let proof = cht.prove(10_000, 0).unwrap().unwrap();
|
||||||
let req = HeaderByNumber {
|
let req = HeaderByNumber::new(10_000, cht.root()).unwrap();
|
||||||
num: 10_000,
|
|
||||||
cht_root: cht.root(),
|
|
||||||
};
|
|
||||||
|
|
||||||
let raw_header = test_client.block_header(::ethcore::ids::BlockId::Number(10_000)).unwrap();
|
let raw_header = test_client.block_header(::ethcore::ids::BlockId::Number(10_000)).unwrap();
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user