-
Notifications
You must be signed in to change notification settings - Fork 1.4k
/
rpc_server.rs
129 lines (104 loc) Β· 2.98 KB
/
rpc_server.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
122
123
124
125
126
127
128
129
use {
super::*,
bitcoin::{hash_types::BlockHash, Txid},
jsonrpc_core::{IoHandler, Result},
jsonrpc_derive::rpc,
jsonrpc_http_server::{CloseHandle, ServerBuilder},
};
#[rpc]
pub trait RpcApi {
#[rpc(name = "getblockhash")]
fn getblockhash(&self, height: usize) -> Result<BlockHash>;
#[rpc(name = "getblock")]
fn getblock(&self, blockhash: BlockHash, verbosity: u64) -> Result<String>;
#[rpc(name = "getrawtransaction")]
fn getrawtransaction(
&self,
txid: Txid,
verbose: bool,
block_hash: Option<BlockHash>,
) -> Result<Transaction>;
}
pub struct RpcServer {
blocks: Arc<Mutex<Vec<Block>>>,
calls: Arc<Mutex<Vec<String>>>,
}
impl RpcServer {
pub(crate) fn spawn(
blocks: Vec<Block>,
) -> (
Arc<Mutex<Vec<Block>>>,
CloseHandle,
Arc<Mutex<Vec<String>>>,
u16,
) {
let calls = Arc::new(Mutex::new(Vec::new()));
let blocks = Arc::new(Mutex::new(blocks));
let server = Self {
blocks: blocks.clone(),
calls: calls.clone(),
};
let mut io = IoHandler::default();
io.extend_with(server.to_delegate());
let server = ServerBuilder::new(io)
.threads(1)
.start_http(&"127.0.0.1:0".parse().unwrap())
.unwrap();
let close_handle = server.close_handle();
let port = server.address().port();
thread::spawn(|| server.wait());
(blocks, close_handle, calls, port)
}
fn call(&self, method: &str) {
self.calls.lock().unwrap().push(method.into());
}
}
impl RpcApi for RpcServer {
fn getblockhash(&self, height: usize) -> Result<BlockHash> {
self.call("getblockhash");
match self.blocks.lock().unwrap().get(height) {
Some(block) => Ok(block.block_hash()),
None => Err(jsonrpc_core::Error::new(
jsonrpc_core::types::error::ErrorCode::ServerError(-8),
)),
}
}
fn getblock(&self, blockhash: BlockHash, verbosity: u64) -> Result<String> {
self.call("getblock");
assert_eq!(verbosity, 0, "Verbosity level {verbosity} is unsupported");
for block in self.blocks.lock().unwrap().iter() {
if block.block_hash() == blockhash {
let mut encoded = Vec::new();
block.consensus_encode(&mut encoded).unwrap();
return Ok(hex::encode(encoded));
}
}
Err(jsonrpc_core::Error::new(
jsonrpc_core::types::error::ErrorCode::ServerError(-8),
))
}
fn getrawtransaction(
&self,
txid: Txid,
verbose: bool,
block_hash: Option<BlockHash>,
) -> Result<Transaction> {
self.call("getrawtransaction");
assert_eq!(verbose, false, "Verbose flag {verbose} is unsupported");
assert_eq!(
block_hash, None,
"Passing in a block hash {:?} is unsupported",
block_hash
);
for block in self.blocks.lock().unwrap().iter() {
for transaction in &block.txdata {
if transaction.txid() == txid {
return Ok(transaction.clone());
}
}
}
Err(jsonrpc_core::Error::new(
jsonrpc_core::types::error::ErrorCode::ServerError(-8),
))
}
}