Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
Open sidebar
Chiguireitor
addrindexrs
Commits
95da35ac
Unverified
Commit
95da35ac
authored
Apr 30, 2018
by
Roman Zeyde
Browse files
Move query-related code into a separate module
parent
68feda0b
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
122 additions
and
112 deletions
+122
-112
src/bin/index_server.rs
src/bin/index_server.rs
+2
-2
src/index.rs
src/index.rs
+18
-107
src/lib.rs
src/lib.rs
+1
-0
src/query.rs
src/query.rs
+98
-0
src/rpc.rs
src/rpc.rs
+3
-3
No files found.
src/bin/index_server.rs
View file @
95da35ac
...
...
@@ -6,7 +6,7 @@ extern crate indexrs;
use
argparse
::{
ArgumentParser
,
StoreFalse
};
use
std
::
fs
::
OpenOptions
;
use
indexrs
::{
daemon
,
index
,
rpc
,
store
,
waiter
};
use
indexrs
::{
daemon
,
index
,
query
,
rpc
,
store
,
waiter
};
fn
setup_logging
()
{
use
simplelog
::
*
;
...
...
@@ -51,7 +51,7 @@ fn run_server(config: Config) {
}
let
store
=
store
::
Store
::
open
(
DB_PATH
,
store
::
StoreOptions
{
auto_compact
:
true
});
let
query
=
index
::
Query
::
new
(
&
store
,
&
daemon
);
let
query
=
query
::
Query
::
new
(
&
store
,
&
daemon
);
crossbeam
::
scope
(|
scope
|
{
scope
.spawn
(||
rpc
::
serve
(
"localhost:50001"
,
&
query
));
...
...
src/index.rs
View file @
95da35ac
use
bincode
;
use
bitcoin
::
blockdata
::
block
::{
Block
,
BlockHeader
};
use
bitcoin
::
blockdata
::
transaction
::{
Transaction
,
TxIn
,
TxOut
};
use
bitcoin
::
blockdata
::
transaction
::{
TxIn
,
TxOut
};
use
bitcoin
::
network
::
serialize
::
BitcoinHash
;
use
bitcoin
::
network
::
serialize
::{
deserialize
,
serialize
};
use
bitcoin
::
util
::
hash
::
Sha256dHash
;
use
crypto
::
digest
::
Digest
;
use
crypto
::
sha2
::
Sha256
;
use
itertools
::
enumerate
;
use
pbr
;
use
std
::
io
::{
stderr
,
Stderr
};
use
std
::
time
::{
Duration
,
Instant
};
...
...
@@ -17,12 +16,12 @@ use store::{Row, Store};
use
types
::{
Bytes
,
HeaderMap
};
const
HASH_LEN
:
usize
=
32
;
const
HASH_PREFIX_LEN
:
usize
=
8
;
pub
const
HASH_PREFIX_LEN
:
usize
=
8
;
type
FullHash
=
[
u8
;
HASH_LEN
];
type
HashPrefix
=
[
u8
;
HASH_PREFIX_LEN
];
pub
type
HashPrefix
=
[
u8
;
HASH_PREFIX_LEN
];
fn
hash_prefix
(
hash
:
&
[
u8
])
->
HashPrefix
{
pub
fn
hash_prefix
(
hash
:
&
[
u8
])
->
HashPrefix
{
array_ref!
[
hash
,
0
,
HASH_PREFIX_LEN
]
.clone
()
}
...
...
@@ -31,43 +30,43 @@ fn full_hash(hash: &[u8]) -> FullHash {
}
#[derive(Serialize,
Deserialize)]
struct
TxInKey
{
code
:
u8
,
prev_hash_prefix
:
HashPrefix
,
prev_index
:
u16
,
pub
struct
TxInKey
{
pub
code
:
u8
,
pub
prev_hash_prefix
:
HashPrefix
,
pub
prev_index
:
u16
,
}
#[derive(Serialize,
Deserialize)]
struct
TxInRow
{
pub
struct
TxInRow
{
key
:
TxInKey
,
txid_prefix
:
HashPrefix
,
pub
txid_prefix
:
HashPrefix
,
}
#[derive(Serialize,
Deserialize)]
struct
TxOutKey
{
pub
struct
TxOutKey
{
code
:
u8
,
script_hash_prefix
:
HashPrefix
,
}
#[derive(Serialize,
Deserialize)]
struct
TxOutRow
{
pub
struct
TxOutRow
{
key
:
TxOutKey
,
txid_prefix
:
HashPrefix
,
pub
txid_prefix
:
HashPrefix
,
}
#[derive(Serialize,
Deserialize)]
struct
TxKey
{
pub
struct
TxKey
{
code
:
u8
,
txid
:
FullHash
,
pub
txid
:
FullHash
,
}
#[derive(Serialize,
Deserialize)]
struct
BlockKey
{
pub
struct
BlockKey
{
code
:
u8
,
hash
:
FullHash
,
}
fn
digest
(
data
:
&
[
u8
])
->
FullHash
{
pub
fn
compute_script_hash
(
data
:
&
[
u8
])
->
FullHash
{
let
mut
hash
=
FullHash
::
default
();
let
mut
sha2
=
Sha256
::
new
();
sha2
.input
(
data
);
...
...
@@ -94,7 +93,7 @@ fn txout_row(output: &TxOut, txid: &Sha256dHash) -> Row {
key
:
bincode
::
serialize
(
&
TxOutRow
{
key
:
TxOutKey
{
code
:
b
'O'
,
script_hash_prefix
:
hash_prefix
(
&
digest
(
&
output
.script_pubkey
[
..
])),
script_hash_prefix
:
hash_prefix
(
&
compute_script_hash
(
&
output
.script_pubkey
[
..
])),
},
txid_prefix
:
hash_prefix
(
&
txid
[
..
]),
})
.unwrap
(),
...
...
@@ -315,91 +314,3 @@ impl Index {
self
.headers
=
Some
(
current_headers
)
}
}
pub
struct
Query
<
'a
>
{
store
:
&
'a
Store
,
daemon
:
&
'a
Daemon
,
}
impl
<
'a
>
Query
<
'a
>
{
pub
fn
new
(
store
:
&
'a
Store
,
daemon
:
&
'a
Daemon
)
->
Query
<
'a
>
{
Query
{
store
,
daemon
}
}
fn
load_txns
(
&
self
,
prefixes
:
Vec
<
HashPrefix
>
)
->
Vec
<
Transaction
>
{
let
mut
txns
=
Vec
::
new
();
for
txid_prefix
in
prefixes
{
for
row
in
self
.store
.scan
(
&
[
b
"T"
,
&
txid_prefix
[
..
]]
.concat
())
{
let
key
:
TxKey
=
bincode
::
deserialize
(
&
row
.key
)
.unwrap
();
let
txid
:
Sha256dHash
=
deserialize
(
&
key
.txid
)
.unwrap
();
let
txn_bytes
=
self
.daemon
.get
(
&
format!
(
"tx/{}.bin"
,
txid
.be_hex_string
()));
let
txn
:
Transaction
=
deserialize
(
&
txn_bytes
)
.unwrap
();
txns
.push
(
txn
)
}
}
txns
}
fn
find_spending_txn
(
&
self
,
txid
:
&
Sha256dHash
,
output_index
:
u32
)
->
Option
<
Transaction
>
{
let
spend_key
=
bincode
::
serialize
(
&
TxInKey
{
code
:
b
'I'
,
prev_hash_prefix
:
hash_prefix
(
&
txid
[
..
]),
prev_index
:
output_index
as
u16
,
})
.unwrap
();
let
mut
spending
:
Vec
<
Transaction
>
=
self
.load_txns
(
self
.store
.scan
(
&
spend_key
)
.iter
()
.map
(|
row
|
{
bincode
::
deserialize
::
<
TxInRow
>
(
&
row
.key
)
.unwrap
()
.txid_prefix
})
.collect
(),
);
spending
.retain
(|
item
|
{
item
.input
.iter
()
.any
(|
input
|
input
.prev_hash
==
*
txid
&&
input
.prev_index
==
output_index
)
});
assert
!
(
spending
.len
()
<=
1
);
if
spending
.len
()
==
1
{
Some
(
spending
.remove
(
0
))
}
else
{
None
}
}
pub
fn
balance
(
&
self
,
script_hash
:
&
[
u8
])
->
f64
{
let
mut
funding
:
Vec
<
Transaction
>
=
self
.load_txns
(
self
.store
.scan
(
&
[
b
"O"
,
&
script_hash
[
..
HASH_PREFIX_LEN
]]
.concat
())
.iter
()
.map
(|
row
|
{
bincode
::
deserialize
::
<
TxOutRow
>
(
&
row
.key
)
.unwrap
()
.txid_prefix
})
.collect
(),
);
funding
.retain
(|
item
|
{
item
.output
.iter
()
.any
(|
output
|
digest
(
&
output
.script_pubkey
[
..
])
==
script_hash
)
});
let
mut
balance
=
0u64
;
let
mut
spending
=
Vec
::
<
Transaction
>
::
new
();
for
txn
in
&
funding
{
let
txid
=
txn
.txid
();
for
(
index
,
output
)
in
enumerate
(
&
txn
.output
)
{
if
let
Some
(
spent
)
=
self
.find_spending_txn
(
&
txid
,
index
as
u32
)
{
spending
.push
(
spent
);
// TODO: may contain duplicate TXNs
}
else
{
balance
+=
output
.value
;
}
}
}
balance
as
f64
/
100_000_000f64
}
}
src/lib.rs
View file @
95da35ac
...
...
@@ -24,6 +24,7 @@ extern crate serde_json;
pub
mod
daemon
;
pub
mod
index
;
pub
mod
query
;
pub
mod
rpc
;
pub
mod
store
;
pub
mod
waiter
;
...
...
src/query.rs
0 → 100644
View file @
95da35ac
use
bincode
;
use
bitcoin
::
blockdata
::
transaction
::
Transaction
;
use
bitcoin
::
network
::
serialize
::
deserialize
;
use
bitcoin
::
util
::
hash
::
Sha256dHash
;
use
itertools
::
enumerate
;
use
daemon
::
Daemon
;
use
index
::{
compute_script_hash
,
hash_prefix
,
HashPrefix
,
TxInKey
,
TxInRow
,
TxKey
,
TxOutRow
,
HASH_PREFIX_LEN
};
use
store
::
Store
;
pub
struct
Query
<
'a
>
{
store
:
&
'a
Store
,
daemon
:
&
'a
Daemon
,
}
impl
<
'a
>
Query
<
'a
>
{
pub
fn
new
(
store
:
&
'a
Store
,
daemon
:
&
'a
Daemon
)
->
Query
<
'a
>
{
Query
{
store
,
daemon
}
}
fn
load_txns
(
&
self
,
prefixes
:
Vec
<
HashPrefix
>
)
->
Vec
<
Transaction
>
{
let
mut
txns
=
Vec
::
new
();
for
txid_prefix
in
prefixes
{
for
row
in
self
.store
.scan
(
&
[
b
"T"
,
&
txid_prefix
[
..
]]
.concat
())
{
let
key
:
TxKey
=
bincode
::
deserialize
(
&
row
.key
)
.unwrap
();
let
txid
:
Sha256dHash
=
deserialize
(
&
key
.txid
)
.unwrap
();
let
txn_bytes
=
self
.daemon
.get
(
&
format!
(
"tx/{}.bin"
,
txid
.be_hex_string
()));
let
txn
:
Transaction
=
deserialize
(
&
txn_bytes
)
.unwrap
();
txns
.push
(
txn
)
}
}
txns
}
fn
find_spending_txn
(
&
self
,
txid
:
&
Sha256dHash
,
output_index
:
u32
)
->
Option
<
Transaction
>
{
let
spend_key
=
bincode
::
serialize
(
&
TxInKey
{
code
:
b
'I'
,
prev_hash_prefix
:
hash_prefix
(
&
txid
[
..
]),
prev_index
:
output_index
as
u16
,
})
.unwrap
();
let
mut
spending
:
Vec
<
Transaction
>
=
self
.load_txns
(
self
.store
.scan
(
&
spend_key
)
.iter
()
.map
(|
row
|
{
bincode
::
deserialize
::
<
TxInRow
>
(
&
row
.key
)
.unwrap
()
.txid_prefix
})
.collect
(),
);
spending
.retain
(|
item
|
{
item
.input
.iter
()
.any
(|
input
|
input
.prev_hash
==
*
txid
&&
input
.prev_index
==
output_index
)
});
assert
!
(
spending
.len
()
<=
1
);
if
spending
.len
()
==
1
{
Some
(
spending
.remove
(
0
))
}
else
{
None
}
}
pub
fn
balance
(
&
self
,
script_hash
:
&
[
u8
])
->
f64
{
let
mut
funding
:
Vec
<
Transaction
>
=
self
.load_txns
(
self
.store
.scan
(
&
[
b
"O"
,
&
script_hash
[
..
HASH_PREFIX_LEN
]]
.concat
())
.iter
()
.map
(|
row
|
{
bincode
::
deserialize
::
<
TxOutRow
>
(
&
row
.key
)
.unwrap
()
.txid_prefix
})
.collect
(),
);
funding
.retain
(|
item
|
{
item
.output
.iter
()
.any
(|
output
|
compute_script_hash
(
&
output
.script_pubkey
[
..
])
==
script_hash
)
});
let
mut
balance
=
0u64
;
let
mut
spending
=
Vec
::
<
Transaction
>
::
new
();
for
txn
in
&
funding
{
let
txid
=
txn
.txid
();
for
(
index
,
output
)
in
enumerate
(
&
txn
.output
)
{
if
let
Some
(
spent
)
=
self
.find_spending_txn
(
&
txid
,
index
as
u32
)
{
spending
.push
(
spent
);
// TODO: may contain duplicate TXNs
}
else
{
balance
+=
output
.value
;
}
}
}
balance
as
f64
/
100_000_000f64
}
}
src/rpc.rs
View file @
95da35ac
...
...
@@ -3,12 +3,12 @@ use serde_json::{from_str, Number, Value};
use
std
::
io
::{
BufRead
,
BufReader
,
Write
};
use
std
::
net
::{
SocketAddr
,
TcpListener
,
TcpStream
};
use
index
;
use
query
::
Query
;
error_chain!
{}
struct
Handler
<
'a
>
{
query
:
&
'a
index
::
Query
<
'a
>
,
query
:
&
'a
Query
<
'a
>
,
}
impl
<
'a
>
Handler
<
'a
>
{
...
...
@@ -129,7 +129,7 @@ impl<'a> Handler<'a> {
}
}
pub
fn
serve
(
addr
:
&
str
,
query
:
&
index
::
Query
)
{
pub
fn
serve
(
addr
:
&
str
,
query
:
&
Query
)
{
let
listener
=
TcpListener
::
bind
(
addr
)
.unwrap
();
info!
(
"RPC server running on {}"
,
addr
);
loop
{
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment