mirror of
https://github.com/romanz/electrs.git
synced 2025-02-24 15:02:21 +01:00
Merge branch 'fix-hashtypes'
This commit is contained in:
commit
2133120234
12 changed files with 164 additions and 220 deletions
116
Cargo.lock
generated
116
Cargo.lock
generated
|
@ -83,7 +83,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "bech32"
|
||||
version = "0.7.1"
|
||||
version = "0.7.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
|
@ -119,23 +119,21 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "bitcoin"
|
||||
version = "0.21.0"
|
||||
version = "0.23.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"bech32 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"bitcoin_hashes 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"bech32 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"bitcoin_hashes 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"secp256k1 0.15.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"secp256k1 0.17.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bitcoin_hashes"
|
||||
version = "0.7.1"
|
||||
version = "0.7.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
|
@ -337,8 +335,8 @@ version = "0.8.3"
|
|||
dependencies = [
|
||||
"base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"bincode 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"bitcoin 0.21.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"bitcoin_hashes 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"bitcoin 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"bitcoin_hashes 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"configure_me 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"configure_me_codegen 0.3.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"crossbeam-channel 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -717,33 +715,6 @@ dependencies = [
|
|||
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand"
|
||||
version = "0.6.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand_jitter 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand_pcg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_chacha"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_core"
|
||||
version = "0.3.1"
|
||||
|
@ -757,32 +728,6 @@ name = "rand_core"
|
|||
version = "0.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "rand_hc"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_isaac"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_jitter"
|
||||
version = "0.1.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_os"
|
||||
version = "0.1.3"
|
||||
|
@ -796,23 +741,6 @@ dependencies = [
|
|||
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_pcg"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_xorshift"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rayon"
|
||||
version = "1.2.0"
|
||||
|
@ -946,11 +874,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
|
||||
[[package]]
|
||||
name = "secp256k1"
|
||||
version = "0.15.5"
|
||||
version = "0.17.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"secp256k1-sys 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "secp256k1-sys"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"cc 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1273,11 +1209,11 @@ dependencies = [
|
|||
"checksum backtrace 0.3.40 (registry+https://github.com/rust-lang/crates.io-index)" = "924c76597f0d9ca25d762c25a4d369d51267536465dc5064bdf0eb073ed477ea"
|
||||
"checksum backtrace-sys 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)" = "5d6575f128516de27e3ce99689419835fce9643a9b215a14d2b5b685be018491"
|
||||
"checksum base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0b25d992356d2eb0ed82172f5248873db5560c4721f564b13cb5193bda5e668e"
|
||||
"checksum bech32 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9e0089c35ab7c6f2bc55ab23f769913f0ac65b1023e7e74638a1f43128dd5df2"
|
||||
"checksum bech32 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "cdcf67bb7ba7797a081cd19009948ab533af7c355d5caf1d08c777582d351e9c"
|
||||
"checksum bincode 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b8ab639324e3ee8774d296864fbc0dbbb256cf1a41c490b94cba90c082915f92"
|
||||
"checksum bindgen 0.47.3 (registry+https://github.com/rust-lang/crates.io-index)" = "df683a55b54b41d5ea8ebfaebb5aa7e6b84e3f3006a78f010dadc9ca88469260"
|
||||
"checksum bitcoin 0.21.0 (registry+https://github.com/rust-lang/crates.io-index)" = "dc34f963060a2091b4e285d8082e1946be35caf467e73b3155262c8357fb4595"
|
||||
"checksum bitcoin_hashes 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "db6b697833d852acea530c9e815e6adc724267856b6506bc500362a068a39c7b"
|
||||
"checksum bitcoin 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6a32c9d2fa897cfbb0db45d71e3d2838666194abc4828c0f994e4b5c3bf85ba4"
|
||||
"checksum bitcoin_hashes 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)" = "b375d62f341cef9cd9e77793ec8f1db3fc9ce2e4d57e982c8fe697a2c16af3b6"
|
||||
"checksum bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
|
||||
"checksum blake2b_simd 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)" = "5850aeee1552f495dd0250014cf64b82b7c8879a89d83b33bbdace2cc4f63182"
|
||||
"checksum byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a7c3dd8985a7111efc5c80b44e23ecdd8c007de8ade3b96595387e812b957cf5"
|
||||
|
@ -1347,16 +1283,9 @@ dependencies = [
|
|||
"checksum quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "053a8c8bcc71fcce321828dc897a98ab9760bef03a4fc36693c231e5b3216cfe"
|
||||
"checksum rand 0.3.23 (registry+https://github.com/rust-lang/crates.io-index)" = "64ac302d8f83c0c1974bf758f6b041c6c8ada916fbb44a609158ca8b064cc76c"
|
||||
"checksum rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "552840b97013b1a26992c11eac34bdd778e464601a4c2054b5f0bff7c6761293"
|
||||
"checksum rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca"
|
||||
"checksum rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef"
|
||||
"checksum rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b"
|
||||
"checksum rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc"
|
||||
"checksum rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4"
|
||||
"checksum rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08"
|
||||
"checksum rand_jitter 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "1166d5c91dc97b88d1decc3285bb0a99ed84b05cfd0bc2341bdf2d43fc41e39b"
|
||||
"checksum rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7b75f676a1e053fc562eafbb47838d67c84801e38fc1ba459e8f180deabd5071"
|
||||
"checksum rand_pcg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "abf9b09b01790cfe0364f52bf32995ea3c39f4d2dd011eac241d2914146d0b44"
|
||||
"checksum rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c"
|
||||
"checksum rayon 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "83a27732a533a1be0a0035a111fe76db89ad312f6f0347004c220c57f209a123"
|
||||
"checksum rayon-core 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "98dcf634205083b17d0861252431eb2acbfb698ab7478a2d20de07954f47ec7b"
|
||||
"checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2"
|
||||
|
@ -1374,7 +1303,8 @@ dependencies = [
|
|||
"checksum ryu 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bfa8506c1de11c9c4e4c38863ccbe02a305c8188e85a05a784c9e11e1c3910c8"
|
||||
"checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27"
|
||||
"checksum scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b42e15e59b18a828bbf5c58ea01debb36b9b096346de35d941dcb89009f24a0d"
|
||||
"checksum secp256k1 0.15.5 (registry+https://github.com/rust-lang/crates.io-index)" = "4d311229f403d64002e9eed9964dfa5a0a0c1ac443344f7546bf48e916c6053a"
|
||||
"checksum secp256k1 0.17.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2932dc07acd2066ff2e3921a4419606b220ba6cd03a9935123856cc534877056"
|
||||
"checksum secp256k1-sys 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7ab2c26f0d3552a0f12e639ae8a64afc2e3db9c52fe32f5fc6c289d38519f220"
|
||||
"checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403"
|
||||
"checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
|
||||
"checksum serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)" = "9796c9b7ba2ffe7a9ce53c2287dfc48080f4b2b362fcc245a259b3a7201119dd"
|
||||
|
|
|
@ -24,8 +24,8 @@ latest_rust = [] # use latest Rust features (otherwise, support Rust 1.34)
|
|||
[dependencies]
|
||||
base64 = "0.10"
|
||||
bincode = "1.0"
|
||||
bitcoin = { version = "0.21", features = ["use-serde"] }
|
||||
bitcoin_hashes = "0.7.1"
|
||||
bitcoin = { version = "0.23", features = ["use-serde"] }
|
||||
bitcoin_hashes = "0.7.6"
|
||||
configure_me = "0.3.3"
|
||||
crossbeam-channel = "0.3"
|
||||
dirs = "1.0"
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use bitcoin_hashes::sha256d::Hash as Sha256dHash;
|
||||
use bitcoin::hash_types::BlockHash;
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
use crate::{config::Config, daemon, errors::*, index, signal::Waiter, store};
|
||||
|
@ -8,7 +8,7 @@ pub struct App {
|
|||
index: index::Index,
|
||||
daemon: daemon::Daemon,
|
||||
banner: String,
|
||||
tip: Mutex<Sha256dHash>,
|
||||
tip: Mutex<BlockHash>,
|
||||
}
|
||||
|
||||
impl App {
|
||||
|
@ -23,7 +23,7 @@ impl App {
|
|||
index,
|
||||
daemon: daemon.reconnect()?,
|
||||
banner: config.server_banner.clone(),
|
||||
tip: Mutex::new(Sha256dHash::default()),
|
||||
tip: Mutex::new(BlockHash::default()),
|
||||
}))
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
use bitcoin::hash_types::BlockHash;
|
||||
use bitcoin::blockdata::block::Block;
|
||||
use bitcoin::consensus::encode::{deserialize, Decodable};
|
||||
use bitcoin::util::hash::BitcoinHash;
|
||||
use bitcoin_hashes::sha256d::Hash as Sha256dHash;
|
||||
use libc;
|
||||
use std::collections::HashSet;
|
||||
use std::fs;
|
||||
|
@ -20,11 +19,12 @@ use crate::metrics::{CounterVec, Histogram, HistogramOpts, HistogramVec, MetricO
|
|||
use crate::signal::Waiter;
|
||||
use crate::store::{DBStore, Row, WriteStore};
|
||||
use crate::util::{spawn_thread, HeaderList, SyncChannel};
|
||||
use bitcoin::BitcoinHash;
|
||||
|
||||
struct Parser {
|
||||
magic: u32,
|
||||
current_headers: HeaderList,
|
||||
indexed_blockhashes: Mutex<HashSet<Sha256dHash>>,
|
||||
indexed_blockhashes: Mutex<HashSet<BlockHash>>,
|
||||
// metrics
|
||||
duration: HistogramVec,
|
||||
block_count: CounterVec,
|
||||
|
@ -35,7 +35,7 @@ impl Parser {
|
|||
fn new(
|
||||
daemon: &Daemon,
|
||||
metrics: &Metrics,
|
||||
indexed_blockhashes: HashSet<Sha256dHash>,
|
||||
indexed_blockhashes: HashSet<BlockHash>,
|
||||
) -> Result<Arc<Parser>> {
|
||||
Ok(Arc::new(Parser {
|
||||
magic: daemon.magic(),
|
||||
|
|
29
src/cache.rs
29
src/cache.rs
|
@ -1,9 +1,9 @@
|
|||
use crate::errors::*;
|
||||
use crate::metrics::{CounterVec, MetricOpts, Metrics};
|
||||
|
||||
use bitcoin::hash_types::{BlockHash, Txid};
|
||||
use bitcoin::blockdata::transaction::Transaction;
|
||||
use bitcoin::consensus::encode::deserialize;
|
||||
use bitcoin_hashes::sha256d::Hash as Sha256dHash;
|
||||
use lru::LruCache;
|
||||
use prometheus::IntGauge;
|
||||
use std::hash::Hash;
|
||||
|
@ -62,7 +62,7 @@ impl<K: Hash + Eq, V> SizedLruCache<K, V> {
|
|||
}
|
||||
|
||||
pub struct BlockTxIDsCache {
|
||||
map: Mutex<SizedLruCache<Sha256dHash /* blockhash */, Vec<Sha256dHash /* txid */>>>,
|
||||
map: Mutex<SizedLruCache<BlockHash, Vec<Txid>>>,
|
||||
}
|
||||
|
||||
impl BlockTxIDsCache {
|
||||
|
@ -85,11 +85,11 @@ impl BlockTxIDsCache {
|
|||
|
||||
pub fn get_or_else<F>(
|
||||
&self,
|
||||
blockhash: &Sha256dHash,
|
||||
blockhash: &BlockHash,
|
||||
load_txids_func: F,
|
||||
) -> Result<Vec<Sha256dHash>>
|
||||
) -> Result<Vec<Txid>>
|
||||
where
|
||||
F: FnOnce() -> Result<Vec<Sha256dHash>>,
|
||||
F: FnOnce() -> Result<Vec<Txid>>,
|
||||
{
|
||||
if let Some(txids) = self.map.lock().unwrap().get(blockhash) {
|
||||
return Ok(txids.clone());
|
||||
|
@ -107,7 +107,7 @@ impl BlockTxIDsCache {
|
|||
|
||||
pub struct TransactionCache {
|
||||
// Store serialized transaction (should use less RAM).
|
||||
map: Mutex<SizedLruCache<Sha256dHash, Vec<u8>>>,
|
||||
map: Mutex<SizedLruCache<Txid, Vec<u8>>>,
|
||||
}
|
||||
|
||||
impl TransactionCache {
|
||||
|
@ -128,7 +128,7 @@ impl TransactionCache {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn get_or_else<F>(&self, txid: &Sha256dHash, load_txn_func: F) -> Result<Transaction>
|
||||
pub fn get_or_else<F>(&self, txid: &Txid, load_txn_func: F) -> Result<Transaction>
|
||||
where
|
||||
F: FnOnce() -> Result<Vec<u8>>,
|
||||
{
|
||||
|
@ -201,17 +201,17 @@ mod tests {
|
|||
assert_eq!(usage.get(), 100);
|
||||
}
|
||||
|
||||
fn gen_hash(seed: u8) -> Sha256dHash {
|
||||
fn gen_hash<T: Hash>(seed: u8) -> T {
|
||||
let bytes: Vec<u8> = (seed..seed + 32).collect();
|
||||
Sha256dHash::hash(&bytes[..])
|
||||
<T as Hash>::hash(&bytes[..])
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_blocktxids_cache_hit_and_miss() {
|
||||
let block1 = gen_hash(1);
|
||||
let block2 = gen_hash(2);
|
||||
let block3 = gen_hash(3);
|
||||
let txids = vec![gen_hash(4), gen_hash(5)];
|
||||
let block1: BlockHash = gen_hash(1);
|
||||
let block2: BlockHash = gen_hash(2);
|
||||
let block3: BlockHash = gen_hash(3);
|
||||
let txids: Vec<Txid> = vec![gen_hash(4), gen_hash(5)];
|
||||
|
||||
let misses: Mutex<usize> = Mutex::new(0);
|
||||
let miss_func = || {
|
||||
|
@ -249,7 +249,6 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn test_txn_cache() {
|
||||
use bitcoin::util::hash::BitcoinHash;
|
||||
use hex;
|
||||
|
||||
let dummy_metrics = Metrics::new("127.0.0.1:60000".parse().unwrap());
|
||||
|
@ -257,7 +256,7 @@ mod tests {
|
|||
let tx_bytes = hex::decode("0100000001a15d57094aa7a21a28cb20b59aab8fc7d1149a3bdbcddba9c622e4f5f6a99ece010000006c493046022100f93bb0e7d8db7bd46e40132d1f8242026e045f03a0efe71bbb8e3f475e970d790221009337cd7f1f929f00cc6ff01f03729b069a7c21b59b1736ddfee5db5946c5da8c0121033b9b137ee87d5a812d6f506efdd37f0affa7ffc310711c06c7f3e097c9447c52ffffffff0100e1f505000000001976a9140389035a9225b3839e2bbf32d826a1e222031fd888ac00000000").unwrap();
|
||||
|
||||
let tx: Transaction = deserialize(&tx_bytes).unwrap();
|
||||
let txid = tx.bitcoin_hash();
|
||||
let txid = tx.txid();
|
||||
|
||||
let mut misses = 0;
|
||||
assert_eq!(
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
use base64;
|
||||
use bitcoin_hashes::Hash;
|
||||
use bitcoin::hash_types::{BlockHash, Txid};
|
||||
use bitcoin::blockdata::block::{Block, BlockHeader};
|
||||
use bitcoin::blockdata::transaction::Transaction;
|
||||
use bitcoin::consensus::encode::{deserialize, serialize};
|
||||
use bitcoin::network::constants::Network;
|
||||
use bitcoin::util::hash::BitcoinHash;
|
||||
use bitcoin_hashes::hex::{FromHex, ToHex};
|
||||
use bitcoin_hashes::sha256d::Hash as Sha256dHash;
|
||||
use glob;
|
||||
use hex;
|
||||
use serde_json::{from_str, from_value, Map, Value};
|
||||
|
@ -22,9 +22,10 @@ use crate::errors::*;
|
|||
use crate::metrics::{HistogramOpts, HistogramVec, Metrics};
|
||||
use crate::signal::Waiter;
|
||||
use crate::util::HeaderList;
|
||||
use bitcoin::BitcoinHash;
|
||||
|
||||
fn parse_hash(value: &Value) -> Result<Sha256dHash> {
|
||||
Ok(Sha256dHash::from_hex(
|
||||
fn parse_hash<T: Hash>(value: &Value) -> Result<T> {
|
||||
Ok(T::from_hex(
|
||||
value
|
||||
.as_str()
|
||||
.chain_err(|| format!("non-string value: {}", value))?,
|
||||
|
@ -460,11 +461,11 @@ impl Daemon {
|
|||
Ok(self.getnetworkinfo()?.relayfee)
|
||||
}
|
||||
|
||||
pub fn getbestblockhash(&self) -> Result<Sha256dHash> {
|
||||
pub fn getbestblockhash(&self) -> Result<BlockHash> {
|
||||
parse_hash(&self.request("getbestblockhash", json!([]))?).chain_err(|| "invalid blockhash")
|
||||
}
|
||||
|
||||
pub fn getblockheader(&self, blockhash: &Sha256dHash) -> Result<BlockHeader> {
|
||||
pub fn getblockheader(&self, blockhash: &BlockHash) -> Result<BlockHeader> {
|
||||
header_from_value(self.request(
|
||||
"getblockheader",
|
||||
json!([blockhash.to_hex(), /*verbose=*/ false]),
|
||||
|
@ -485,7 +486,7 @@ impl Daemon {
|
|||
Ok(result)
|
||||
}
|
||||
|
||||
pub fn getblock(&self, blockhash: &Sha256dHash) -> Result<Block> {
|
||||
pub fn getblock(&self, blockhash: &BlockHash) -> Result<Block> {
|
||||
let block = block_from_value(
|
||||
self.request("getblock", json!([blockhash.to_hex(), /*verbose=*/ false]))?,
|
||||
)?;
|
||||
|
@ -493,7 +494,7 @@ impl Daemon {
|
|||
Ok(block)
|
||||
}
|
||||
|
||||
fn load_blocktxids(&self, blockhash: &Sha256dHash) -> Result<Vec<Sha256dHash>> {
|
||||
fn load_blocktxids(&self, blockhash: &BlockHash) -> Result<Vec<Txid>> {
|
||||
self.request("getblock", json!([blockhash.to_hex(), /*verbose=*/ 1]))?
|
||||
.get("tx")
|
||||
.chain_err(|| "block missing txids")?
|
||||
|
@ -501,15 +502,15 @@ impl Daemon {
|
|||
.chain_err(|| "invalid block txids")?
|
||||
.iter()
|
||||
.map(parse_hash)
|
||||
.collect::<Result<Vec<Sha256dHash>>>()
|
||||
.collect::<Result<Vec<Txid>>>()
|
||||
}
|
||||
|
||||
pub fn getblocktxids(&self, blockhash: &Sha256dHash) -> Result<Vec<Sha256dHash>> {
|
||||
pub fn getblocktxids(&self, blockhash: &BlockHash) -> Result<Vec<Txid>> {
|
||||
self.blocktxids_cache
|
||||
.get_or_else(&blockhash, || self.load_blocktxids(blockhash))
|
||||
}
|
||||
|
||||
pub fn getblocks(&self, blockhashes: &[Sha256dHash]) -> Result<Vec<Block>> {
|
||||
pub fn getblocks(&self, blockhashes: &[BlockHash]) -> Result<Vec<Block>> {
|
||||
let params_list: Vec<Value> = blockhashes
|
||||
.iter()
|
||||
.map(|hash| json!([hash.to_hex(), /*verbose=*/ false]))
|
||||
|
@ -524,8 +525,8 @@ impl Daemon {
|
|||
|
||||
pub fn gettransaction(
|
||||
&self,
|
||||
txhash: &Sha256dHash,
|
||||
blockhash: Option<Sha256dHash>,
|
||||
txhash: &Txid,
|
||||
blockhash: Option<BlockHash>,
|
||||
) -> Result<Transaction> {
|
||||
let mut args = json!([txhash.to_hex(), /*verbose=*/ false]);
|
||||
if let Some(blockhash) = blockhash {
|
||||
|
@ -536,8 +537,8 @@ impl Daemon {
|
|||
|
||||
pub fn gettransaction_raw(
|
||||
&self,
|
||||
txhash: &Sha256dHash,
|
||||
blockhash: Option<Sha256dHash>,
|
||||
txhash: &Txid,
|
||||
blockhash: Option<BlockHash>,
|
||||
verbose: bool,
|
||||
) -> Result<Value> {
|
||||
let mut args = json!([txhash.to_hex(), verbose]);
|
||||
|
@ -547,7 +548,7 @@ impl Daemon {
|
|||
Ok(self.request("getrawtransaction", args)?)
|
||||
}
|
||||
|
||||
pub fn gettransactions(&self, txhashes: &[&Sha256dHash]) -> Result<Vec<Transaction>> {
|
||||
pub fn gettransactions(&self, txhashes: &[&Txid]) -> Result<Vec<Transaction>> {
|
||||
let params_list: Vec<Value> = txhashes
|
||||
.iter()
|
||||
.map(|txhash| json!([txhash.to_hex(), /*verbose=*/ false]))
|
||||
|
@ -562,7 +563,7 @@ impl Daemon {
|
|||
Ok(txs)
|
||||
}
|
||||
|
||||
pub fn getmempooltxids(&self) -> Result<HashSet<Sha256dHash>> {
|
||||
pub fn getmempooltxids(&self) -> Result<HashSet<Txid>> {
|
||||
let txids: Value = self.request("getrawmempool", json!([/*verbose=*/ false]))?;
|
||||
let mut result = HashSet::new();
|
||||
for value in txids.as_array().chain_err(|| "non-array result")? {
|
||||
|
@ -571,7 +572,7 @@ impl Daemon {
|
|||
Ok(result)
|
||||
}
|
||||
|
||||
pub fn getmempoolentry(&self, txid: &Sha256dHash) -> Result<MempoolEntry> {
|
||||
pub fn getmempoolentry(&self, txid: &Txid) -> Result<MempoolEntry> {
|
||||
let entry = self.request("getmempoolentry", json!([txid.to_hex()]))?;
|
||||
let fee = (entry
|
||||
.get("fee")
|
||||
|
@ -588,16 +589,16 @@ impl Daemon {
|
|||
Ok(MempoolEntry::new(fee, vsize))
|
||||
}
|
||||
|
||||
pub fn broadcast(&self, tx: &Transaction) -> Result<Sha256dHash> {
|
||||
pub fn broadcast(&self, tx: &Transaction) -> Result<Txid> {
|
||||
let tx = hex::encode(serialize(tx));
|
||||
let txid = self.request("sendrawtransaction", json!([tx]))?;
|
||||
Ok(
|
||||
Sha256dHash::from_hex(txid.as_str().chain_err(|| "non-string txid")?)
|
||||
Txid::from_hex(txid.as_str().chain_err(|| "non-string txid")?)
|
||||
.chain_err(|| "failed to parse txid")?,
|
||||
)
|
||||
}
|
||||
|
||||
fn get_all_headers(&self, tip: &Sha256dHash) -> Result<Vec<BlockHeader>> {
|
||||
fn get_all_headers(&self, tip: &BlockHash) -> Result<Vec<BlockHeader>> {
|
||||
let info: Value = self.request("getblockheader", json!([tip.to_hex()]))?;
|
||||
let tip_height = info
|
||||
.get("height")
|
||||
|
@ -607,7 +608,7 @@ impl Daemon {
|
|||
let all_heights: Vec<usize> = (0..=tip_height).collect();
|
||||
let chunk_size = 100_000;
|
||||
let mut result = vec![];
|
||||
let null_hash = Sha256dHash::default();
|
||||
let null_hash = BlockHash::default();
|
||||
for heights in all_heights.chunks(chunk_size) {
|
||||
trace!("downloading {} block headers", heights.len());
|
||||
let mut headers = self.getblockheaders(&heights)?;
|
||||
|
@ -628,7 +629,7 @@ impl Daemon {
|
|||
pub fn get_new_headers(
|
||||
&self,
|
||||
indexed_headers: &HeaderList,
|
||||
bestblockhash: &Sha256dHash,
|
||||
bestblockhash: &BlockHash,
|
||||
) -> Result<Vec<BlockHeader>> {
|
||||
// Iterate back over headers until known blockash is found:
|
||||
if indexed_headers.is_empty() {
|
||||
|
@ -640,7 +641,7 @@ impl Daemon {
|
|||
bestblockhash,
|
||||
);
|
||||
let mut new_headers = vec![];
|
||||
let null_hash = Sha256dHash::default();
|
||||
let null_hash = BlockHash::default();
|
||||
let mut blockhash = *bestblockhash;
|
||||
while blockhash != null_hash {
|
||||
if indexed_headers.header_by_blockhash(&blockhash).is_some() {
|
||||
|
|
36
src/index.rs
36
src/index.rs
|
@ -1,9 +1,8 @@
|
|||
use bincode;
|
||||
use bitcoin::hash_types::{BlockHash, Txid};
|
||||
use bitcoin::blockdata::block::{Block, BlockHeader};
|
||||
use bitcoin::blockdata::transaction::{Transaction, TxIn, TxOut};
|
||||
use bitcoin::consensus::encode::{deserialize, serialize};
|
||||
use bitcoin::util::hash::BitcoinHash;
|
||||
use bitcoin_hashes::sha256d::Hash as Sha256dHash;
|
||||
use crypto::digest::Digest;
|
||||
use crypto::sha2::Sha256;
|
||||
use std::collections::{HashMap, HashSet};
|
||||
|
@ -21,6 +20,7 @@ use crate::util::{
|
|||
full_hash, hash_prefix, spawn_thread, Bytes, FullHash, HashPrefix, HeaderEntry, HeaderList,
|
||||
HeaderMap, SyncChannel, HASH_PREFIX_LEN,
|
||||
};
|
||||
use bitcoin::BitcoinHash;
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct TxInKey {
|
||||
|
@ -36,7 +36,7 @@ pub struct TxInRow {
|
|||
}
|
||||
|
||||
impl TxInRow {
|
||||
pub fn new(txid: &Sha256dHash, input: &TxIn) -> TxInRow {
|
||||
pub fn new(txid: &Txid, input: &TxIn) -> TxInRow {
|
||||
TxInRow {
|
||||
key: TxInKey {
|
||||
code: b'I',
|
||||
|
@ -47,7 +47,7 @@ impl TxInRow {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn filter(txid: &Sha256dHash, output_index: usize) -> Bytes {
|
||||
pub fn filter(txid: &Txid, output_index: usize) -> Bytes {
|
||||
bincode::serialize(&TxInKey {
|
||||
code: b'I',
|
||||
prev_hash_prefix: hash_prefix(&txid[..]),
|
||||
|
@ -81,7 +81,7 @@ pub struct TxOutRow {
|
|||
}
|
||||
|
||||
impl TxOutRow {
|
||||
pub fn new(txid: &Sha256dHash, output: &TxOut) -> TxOutRow {
|
||||
pub fn new(txid: &Txid, output: &TxOut) -> TxOutRow {
|
||||
TxOutRow {
|
||||
key: TxOutKey {
|
||||
code: b'O',
|
||||
|
@ -123,7 +123,7 @@ pub struct TxRow {
|
|||
}
|
||||
|
||||
impl TxRow {
|
||||
pub fn new(txid: &Sha256dHash, height: u32) -> TxRow {
|
||||
pub fn new(txid: &Txid, height: u32) -> TxRow {
|
||||
TxRow {
|
||||
key: TxKey {
|
||||
code: b'T',
|
||||
|
@ -137,7 +137,7 @@ impl TxRow {
|
|||
[b"T", &txid_prefix[..]].concat()
|
||||
}
|
||||
|
||||
pub fn filter_full(txid: &Sha256dHash) -> Bytes {
|
||||
pub fn filter_full(txid: &Txid) -> Bytes {
|
||||
[b"T", &txid[..]].concat()
|
||||
}
|
||||
|
||||
|
@ -174,8 +174,8 @@ pub fn index_transaction<'a>(
|
|||
txn: &'a Transaction,
|
||||
height: usize,
|
||||
) -> impl 'a + Iterator<Item = Row> {
|
||||
let null_hash = Sha256dHash::default();
|
||||
let txid: Sha256dHash = txn.txid();
|
||||
let null_hash = Txid::default();
|
||||
let txid = txn.txid();
|
||||
|
||||
let inputs = txn.input.iter().filter_map(move |input| {
|
||||
if input.previous_output.txid == null_hash {
|
||||
|
@ -213,7 +213,7 @@ pub fn index_block<'a>(block: &'a Block, height: usize) -> impl 'a + Iterator<It
|
|||
.chain(std::iter::once(row))
|
||||
}
|
||||
|
||||
pub fn last_indexed_block(blockhash: &Sha256dHash) -> Row {
|
||||
pub fn last_indexed_block(blockhash: &BlockHash) -> Row {
|
||||
// Store last indexed block (i.e. all previous blocks were indexed)
|
||||
Row {
|
||||
key: b"L".to_vec(),
|
||||
|
@ -221,7 +221,7 @@ pub fn last_indexed_block(blockhash: &Sha256dHash) -> Row {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn read_indexed_blockhashes(store: &dyn ReadStore) -> HashSet<Sha256dHash> {
|
||||
pub fn read_indexed_blockhashes(store: &dyn ReadStore) -> HashSet<BlockHash> {
|
||||
let mut result = HashSet::new();
|
||||
for row in store.scan(b"B") {
|
||||
let key: BlockKey = bincode::deserialize(&row.key).unwrap();
|
||||
|
@ -231,10 +231,10 @@ pub fn read_indexed_blockhashes(store: &dyn ReadStore) -> HashSet<Sha256dHash> {
|
|||
}
|
||||
|
||||
fn read_indexed_headers(store: &dyn ReadStore) -> HeaderList {
|
||||
let latest_blockhash: Sha256dHash = match store.get(b"L") {
|
||||
let latest_blockhash: BlockHash = match store.get(b"L") {
|
||||
// latest blockheader persisted in the DB.
|
||||
Some(row) => deserialize(&row).unwrap(),
|
||||
None => Sha256dHash::default(),
|
||||
None => BlockHash::default(),
|
||||
};
|
||||
trace!("latest indexed blockhash: {}", latest_blockhash);
|
||||
let mut map = HeaderMap::new();
|
||||
|
@ -244,7 +244,7 @@ fn read_indexed_headers(store: &dyn ReadStore) -> HeaderList {
|
|||
map.insert(deserialize(&key.hash).unwrap(), header);
|
||||
}
|
||||
let mut headers = vec![];
|
||||
let null_hash = Sha256dHash::default();
|
||||
let null_hash = BlockHash::default();
|
||||
let mut blockhash = latest_blockhash;
|
||||
while blockhash != null_hash {
|
||||
let header = map
|
||||
|
@ -264,7 +264,7 @@ fn read_indexed_headers(store: &dyn ReadStore) -> HeaderList {
|
|||
assert_eq!(
|
||||
headers
|
||||
.last()
|
||||
.map(BitcoinHash::bitcoin_hash)
|
||||
.map(BlockHeader::bitcoin_hash)
|
||||
.unwrap_or(null_hash),
|
||||
latest_blockhash
|
||||
);
|
||||
|
@ -370,7 +370,7 @@ impl Index {
|
|||
.cloned()
|
||||
}
|
||||
|
||||
pub fn update(&self, store: &impl WriteStore, waiter: &Waiter) -> Result<Sha256dHash> {
|
||||
pub fn update(&self, store: &impl WriteStore, waiter: &Waiter) -> Result<BlockHash> {
|
||||
let daemon = self.daemon.reconnect()?;
|
||||
let tip = daemon.getbestblockhash()?;
|
||||
let new_headers: Vec<HeaderEntry> = {
|
||||
|
@ -380,13 +380,13 @@ impl Index {
|
|||
if let Some(latest_header) = new_headers.last() {
|
||||
info!("{:?} ({} left to index)", latest_header, new_headers.len());
|
||||
};
|
||||
let height_map = HashMap::<Sha256dHash, usize>::from_iter(
|
||||
let height_map = HashMap::<BlockHash, usize>::from_iter(
|
||||
new_headers.iter().map(|h| (*h.hash(), h.height())),
|
||||
);
|
||||
|
||||
let chan = SyncChannel::new(1);
|
||||
let sender = chan.sender();
|
||||
let blockhashes: Vec<Sha256dHash> = new_headers.iter().map(|h| *h.hash()).collect();
|
||||
let blockhashes: Vec<BlockHash> = new_headers.iter().map(|h| *h.hash()).collect();
|
||||
let batch_size = self.batch_size;
|
||||
let fetcher = spawn_thread("fetcher", move || {
|
||||
for chunk in blockhashes.chunks(batch_size) {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use bitcoin::hash_types::Txid;
|
||||
use bitcoin::blockdata::transaction::Transaction;
|
||||
use bitcoin_hashes::sha256d::Hash as Sha256dHash;
|
||||
use hex;
|
||||
use std::collections::{BTreeMap, HashMap, HashSet};
|
||||
use std::iter::FromIterator;
|
||||
|
@ -139,7 +139,7 @@ impl Stats {
|
|||
}
|
||||
|
||||
pub struct Tracker {
|
||||
items: HashMap<Sha256dHash, Item>,
|
||||
items: HashMap<Txid, Item>,
|
||||
index: MempoolStore,
|
||||
histogram: Vec<(f32, u32)>,
|
||||
stats: Stats,
|
||||
|
@ -175,7 +175,7 @@ impl Tracker {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn get_txn(&self, txid: &Sha256dHash) -> Option<Transaction> {
|
||||
pub fn get_txn(&self, txid: &Txid) -> Option<Transaction> {
|
||||
self.items.get(txid).map(|stats| stats.tx.clone())
|
||||
}
|
||||
|
||||
|
@ -200,7 +200,7 @@ impl Tracker {
|
|||
|
||||
let timer = self.stats.start_timer("add");
|
||||
let txids_iter = new_txids.difference(&old_txids);
|
||||
let entries: Vec<(&Sha256dHash, MempoolEntry)> = txids_iter
|
||||
let entries: Vec<(&Txid, MempoolEntry)> = txids_iter
|
||||
.filter_map(|txid| {
|
||||
match daemon.getmempoolentry(txid) {
|
||||
Ok(entry) => Some((txid, entry)),
|
||||
|
@ -212,7 +212,7 @@ impl Tracker {
|
|||
})
|
||||
.collect();
|
||||
if !entries.is_empty() {
|
||||
let txids: Vec<&Sha256dHash> = entries.iter().map(|(txid, _)| *txid).collect();
|
||||
let txids: Vec<&Txid> = entries.iter().map(|(txid, _)| *txid).collect();
|
||||
let txs = match daemon.gettransactions(&txids) {
|
||||
Ok(txs) => txs,
|
||||
Err(err) => {
|
||||
|
@ -241,12 +241,12 @@ impl Tracker {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn add(&mut self, txid: &Sha256dHash, tx: Transaction, entry: MempoolEntry) {
|
||||
fn add(&mut self, txid: &Txid, tx: Transaction, entry: MempoolEntry) {
|
||||
self.index.add(&tx);
|
||||
self.items.insert(*txid, Item { tx, entry });
|
||||
}
|
||||
|
||||
fn remove(&mut self, txid: &Sha256dHash) {
|
||||
fn remove(&mut self, txid: &Txid) {
|
||||
let stats = self
|
||||
.items
|
||||
.remove(txid)
|
||||
|
|
|
@ -4,7 +4,7 @@ use bitcoin::network::constants::Network;
|
|||
use bitcoin::network::message::NetworkMessage;
|
||||
use bitcoin::network::message_blockdata::InvType;
|
||||
use bitcoin::network::socket::Socket;
|
||||
use bitcoin::util::hash::Sha256dHash;
|
||||
use bitcoin::hash_types::Txid;
|
||||
use bitcoin::util::Error;
|
||||
|
||||
use std::sync::mpsc::Sender;
|
||||
|
@ -19,7 +19,7 @@ fn connect() -> Result<Socket, Error> {
|
|||
Ok(sock)
|
||||
}
|
||||
|
||||
fn handle(mut sock: Socket, tx: Sender<Sha256dHash>) {
|
||||
fn handle(mut sock: Socket, tx: Sender<Txid>) {
|
||||
let mut outgoing = vec![sock.version_message(0).unwrap()];
|
||||
loop {
|
||||
for msg in outgoing.split_off(0) {
|
||||
|
@ -53,7 +53,7 @@ fn handle(mut sock: Socket, tx: Sender<Sha256dHash>) {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn run() -> util::Channel<Sha256dHash> {
|
||||
pub fn run() -> util::Channel<Txid> {
|
||||
let chan = util::Channel::new();
|
||||
let tx = chan.sender();
|
||||
|
||||
|
|
68
src/query.rs
68
src/query.rs
|
@ -1,7 +1,8 @@
|
|||
use bitcoin::blockdata::transaction::Transaction;
|
||||
use bitcoin::consensus::encode::deserialize;
|
||||
use bitcoin::hash_types::{Txid, BlockHash, TxMerkleNode};
|
||||
use bitcoin::hashes::sha256d::Hash as Sha256dHash;
|
||||
use bitcoin_hashes::hex::ToHex;
|
||||
use bitcoin_hashes::sha256d::Hash as Sha256dHash;
|
||||
use bitcoin_hashes::Hash;
|
||||
use crypto::digest::Digest;
|
||||
use crypto::sha2::Sha256;
|
||||
|
@ -19,16 +20,16 @@ use crate::store::{ReadStore, Row};
|
|||
use crate::util::{FullHash, HashPrefix, HeaderEntry};
|
||||
|
||||
pub struct FundingOutput {
|
||||
pub txn_id: Sha256dHash,
|
||||
pub txn_id: Txid,
|
||||
pub height: u32,
|
||||
pub output_index: usize,
|
||||
pub value: u64,
|
||||
}
|
||||
|
||||
type OutPoint = (Sha256dHash, usize); // (txid, output_index)
|
||||
type OutPoint = (Txid, usize); // (txid, output_index)
|
||||
|
||||
struct SpendingInput {
|
||||
txn_id: Sha256dHash,
|
||||
txn_id: Txid,
|
||||
height: u32,
|
||||
funding_output: OutPoint,
|
||||
value: u64,
|
||||
|
@ -62,15 +63,15 @@ impl Status {
|
|||
calc_balance(&self.mempool)
|
||||
}
|
||||
|
||||
pub fn history(&self) -> Vec<(i32, Sha256dHash)> {
|
||||
let mut txns_map = HashMap::<Sha256dHash, i32>::new();
|
||||
pub fn history(&self) -> Vec<(i32, Txid)> {
|
||||
let mut txns_map = HashMap::<Txid, i32>::new();
|
||||
for f in self.funding() {
|
||||
txns_map.insert(f.txn_id, f.height as i32);
|
||||
}
|
||||
for s in self.spending() {
|
||||
txns_map.insert(s.txn_id, s.height as i32);
|
||||
}
|
||||
let mut txns: Vec<(i32, Sha256dHash)> =
|
||||
let mut txns: Vec<(i32, Txid)> =
|
||||
txns_map.into_iter().map(|item| (item.1, item.0)).collect();
|
||||
txns.sort_unstable();
|
||||
txns
|
||||
|
@ -116,15 +117,15 @@ struct TxnHeight {
|
|||
height: u32,
|
||||
}
|
||||
|
||||
fn merklize(left: Sha256dHash, right: Sha256dHash) -> Sha256dHash {
|
||||
fn merklize<T: Hash>(left: T, right: T) -> T {
|
||||
let data = [&left[..], &right[..]].concat();
|
||||
Sha256dHash::hash(&data)
|
||||
<T as Hash>::hash(&data)
|
||||
}
|
||||
|
||||
fn create_merkle_branch_and_root(
|
||||
mut hashes: Vec<Sha256dHash>,
|
||||
fn create_merkle_branch_and_root<T: Hash>(
|
||||
mut hashes: Vec<T>,
|
||||
mut index: usize,
|
||||
) -> (Vec<Sha256dHash>, Sha256dHash) {
|
||||
) -> (Vec<T>, T) {
|
||||
let mut merkle = vec![];
|
||||
while hashes.len() > 1 {
|
||||
if hashes.len() % 2 != 0 {
|
||||
|
@ -143,7 +144,7 @@ fn create_merkle_branch_and_root(
|
|||
}
|
||||
|
||||
// TODO: the functions below can be part of ReadStore.
|
||||
fn txrow_by_txid(store: &dyn ReadStore, txid: &Sha256dHash) -> Option<TxRow> {
|
||||
fn txrow_by_txid(store: &dyn ReadStore, txid: &Txid) -> Option<TxRow> {
|
||||
let key = TxRow::filter_full(&txid);
|
||||
let value = store.get(&key)?;
|
||||
Some(TxRow::from_row(&Row { key, value }))
|
||||
|
@ -167,7 +168,7 @@ fn txids_by_script_hash(store: &dyn ReadStore, script_hash: &[u8]) -> Vec<HashPr
|
|||
|
||||
fn txids_by_funding_output(
|
||||
store: &dyn ReadStore,
|
||||
txn_id: &Sha256dHash,
|
||||
txn_id: &Txid,
|
||||
output_index: usize,
|
||||
) -> Vec<HashPrefix> {
|
||||
store
|
||||
|
@ -215,7 +216,7 @@ impl Query {
|
|||
let mut txns = vec![];
|
||||
for txid_prefix in prefixes {
|
||||
for tx_row in txrows_by_prefix(store, txid_prefix) {
|
||||
let txid: Sha256dHash = deserialize(&tx_row.key.txid).unwrap();
|
||||
let txid: Txid = deserialize(&tx_row.key.txid).unwrap();
|
||||
let txn = self.load_txn(&txid, Some(tx_row.height))?;
|
||||
txns.push(TxnHeight {
|
||||
txn,
|
||||
|
@ -345,9 +346,9 @@ impl Query {
|
|||
|
||||
fn lookup_confirmed_blockhash(
|
||||
&self,
|
||||
tx_hash: &Sha256dHash,
|
||||
tx_hash: &Txid,
|
||||
block_height: Option<u32>,
|
||||
) -> Result<Option<Sha256dHash>> {
|
||||
) -> Result<Option<BlockHash>> {
|
||||
let blockhash = if self.tracker.read().unwrap().get_txn(&tx_hash).is_some() {
|
||||
None // found in mempool (as unconfirmed transaction)
|
||||
} else {
|
||||
|
@ -371,7 +372,7 @@ impl Query {
|
|||
}
|
||||
|
||||
// Internal API for transaction retrieval
|
||||
fn load_txn(&self, txid: &Sha256dHash, block_height: Option<u32>) -> Result<Transaction> {
|
||||
fn load_txn(&self, txid: &Txid, block_height: Option<u32>) -> Result<Transaction> {
|
||||
let _timer = self.duration.with_label_values(&["load_txn"]).start_timer();
|
||||
self.tx_cache.get_or_else(&txid, || {
|
||||
let blockhash = self.lookup_confirmed_blockhash(txid, block_height)?;
|
||||
|
@ -385,7 +386,7 @@ impl Query {
|
|||
}
|
||||
|
||||
// Public API for transaction retrieval (for Electrum RPC)
|
||||
pub fn get_transaction(&self, tx_hash: &Sha256dHash, verbose: bool) -> Result<Value> {
|
||||
pub fn get_transaction(&self, tx_hash: &Txid, verbose: bool) -> Result<Value> {
|
||||
let _timer = self
|
||||
.duration
|
||||
.with_label_values(&["get_transaction"])
|
||||
|
@ -415,9 +416,9 @@ impl Query {
|
|||
|
||||
pub fn get_merkle_proof(
|
||||
&self,
|
||||
tx_hash: &Sha256dHash,
|
||||
tx_hash: &Txid,
|
||||
height: usize,
|
||||
) -> Result<(Vec<Sha256dHash>, usize)> {
|
||||
) -> Result<(Vec<TxMerkleNode>, usize)> {
|
||||
let header_entry = self
|
||||
.app
|
||||
.index()
|
||||
|
@ -428,7 +429,11 @@ impl Query {
|
|||
.iter()
|
||||
.position(|txid| txid == tx_hash)
|
||||
.chain_err(|| format!("missing txid {}", tx_hash))?;
|
||||
let (branch, _root) = create_merkle_branch_and_root(txids, pos);
|
||||
let tx_nodes: Vec<TxMerkleNode> = txids
|
||||
.into_iter()
|
||||
.map(|txid| TxMerkleNode::from_inner(txid.into_inner()))
|
||||
.collect();
|
||||
let (branch, _root) = create_merkle_branch_and_root(tx_nodes, pos);
|
||||
Ok((branch, pos))
|
||||
}
|
||||
|
||||
|
@ -451,13 +456,17 @@ impl Query {
|
|||
}
|
||||
|
||||
let heights: Vec<usize> = (0..=cp_height).collect();
|
||||
let header_hashes: Vec<Sha256dHash> = self
|
||||
let header_hashes: Vec<BlockHash> = self
|
||||
.get_headers(&heights)
|
||||
.into_iter()
|
||||
.map(|h| *h.hash())
|
||||
.collect();
|
||||
let merkle_nodes: Vec<Sha256dHash> = header_hashes
|
||||
.iter()
|
||||
.map(|block_hash| Sha256dHash::from_inner(block_hash.into_inner()))
|
||||
.collect();
|
||||
assert_eq!(header_hashes.len(), heights.len());
|
||||
Ok(create_merkle_branch_and_root(header_hashes, height))
|
||||
Ok(create_merkle_branch_and_root(merkle_nodes, height))
|
||||
}
|
||||
|
||||
pub fn get_id_from_pos(
|
||||
|
@ -465,7 +474,7 @@ impl Query {
|
|||
height: usize,
|
||||
tx_pos: usize,
|
||||
want_merkle: bool,
|
||||
) -> Result<(Sha256dHash, Vec<Sha256dHash>)> {
|
||||
) -> Result<(Txid, Vec<TxMerkleNode>)> {
|
||||
let header_entry = self
|
||||
.app
|
||||
.index()
|
||||
|
@ -477,15 +486,20 @@ impl Query {
|
|||
.get(tx_pos)
|
||||
.chain_err(|| format!("No tx in position #{} in block #{}", tx_pos, height))?;
|
||||
|
||||
let tx_nodes = txids
|
||||
.into_iter()
|
||||
.map(|txid| TxMerkleNode::from_inner(txid.into_inner()))
|
||||
.collect();
|
||||
|
||||
let branch = if want_merkle {
|
||||
create_merkle_branch_and_root(txids, tx_pos).0
|
||||
create_merkle_branch_and_root(tx_nodes, tx_pos).0
|
||||
} else {
|
||||
vec![]
|
||||
};
|
||||
Ok((txid, branch))
|
||||
}
|
||||
|
||||
pub fn broadcast(&self, txn: &Transaction) -> Result<Sha256dHash> {
|
||||
pub fn broadcast(&self, txn: &Transaction) -> Result<Txid> {
|
||||
self.app.daemon().broadcast(txn)
|
||||
}
|
||||
|
||||
|
|
14
src/rpc.rs
14
src/rpc.rs
|
@ -1,7 +1,7 @@
|
|||
use bitcoin::blockdata::transaction::Transaction;
|
||||
use bitcoin::consensus::encode::{deserialize, serialize};
|
||||
use bitcoin_hashes::hex::{FromHex, ToHex};
|
||||
use bitcoin_hashes::sha256d::Hash as Sha256dHash;
|
||||
use bitcoin_hashes::{Hash, sha256d::Hash as Sha256dHash};
|
||||
use error_chain::ChainedError;
|
||||
use hex;
|
||||
use serde_json::{from_str, Value};
|
||||
|
@ -21,10 +21,10 @@ const ELECTRS_VERSION: &str = env!("CARGO_PKG_VERSION");
|
|||
const PROTOCOL_VERSION: &str = "1.4";
|
||||
|
||||
// TODO: Sha256dHash should be a generic hash-container (since script hash is single SHA256)
|
||||
fn hash_from_value(val: Option<&Value>) -> Result<Sha256dHash> {
|
||||
fn hash_from_value<T: Hash>(val: Option<&Value>) -> Result<T> {
|
||||
let script_hash = val.chain_err(|| "missing hash")?;
|
||||
let script_hash = script_hash.as_str().chain_err(|| "non-string hash")?;
|
||||
let script_hash = Sha256dHash::from_hex(script_hash).chain_err(|| "non-hex hash")?;
|
||||
let script_hash = T::from_hex(script_hash).chain_err(|| "non-hex hash")?;
|
||||
Ok(script_hash)
|
||||
}
|
||||
|
||||
|
@ -202,7 +202,7 @@ impl Connection {
|
|||
}
|
||||
|
||||
fn blockchain_scripthash_subscribe(&mut self, params: &[Value]) -> Result<Value> {
|
||||
let script_hash = hash_from_value(params.get(0)).chain_err(|| "bad script_hash")?;
|
||||
let script_hash = hash_from_value::<Sha256dHash>(params.get(0)).chain_err(|| "bad script_hash")?;
|
||||
let status = self.query.status(&script_hash[..])?;
|
||||
let result = status.hash().map_or(Value::Null, |h| json!(hex::encode(h)));
|
||||
self.status_hashes.insert(script_hash, result.clone());
|
||||
|
@ -210,7 +210,7 @@ impl Connection {
|
|||
}
|
||||
|
||||
fn blockchain_scripthash_get_balance(&self, params: &[Value]) -> Result<Value> {
|
||||
let script_hash = hash_from_value(params.get(0)).chain_err(|| "bad script_hash")?;
|
||||
let script_hash = hash_from_value::<Sha256dHash>(params.get(0)).chain_err(|| "bad script_hash")?;
|
||||
let status = self.query.status(&script_hash[..])?;
|
||||
Ok(
|
||||
json!({ "confirmed": status.confirmed_balance(), "unconfirmed": status.mempool_balance() }),
|
||||
|
@ -218,7 +218,7 @@ impl Connection {
|
|||
}
|
||||
|
||||
fn blockchain_scripthash_get_history(&self, params: &[Value]) -> Result<Value> {
|
||||
let script_hash = hash_from_value(params.get(0)).chain_err(|| "bad script_hash")?;
|
||||
let script_hash = hash_from_value::<Sha256dHash>(params.get(0)).chain_err(|| "bad script_hash")?;
|
||||
let status = self.query.status(&script_hash[..])?;
|
||||
Ok(json!(Value::Array(
|
||||
status
|
||||
|
@ -230,7 +230,7 @@ impl Connection {
|
|||
}
|
||||
|
||||
fn blockchain_scripthash_listunspent(&self, params: &[Value]) -> Result<Value> {
|
||||
let script_hash = hash_from_value(params.get(0)).chain_err(|| "bad script_hash")?;
|
||||
let script_hash = hash_from_value::<Sha256dHash>(params.get(0)).chain_err(|| "bad script_hash")?;
|
||||
Ok(unspent_from_status(&self.query.status(&script_hash[..])?))
|
||||
}
|
||||
|
||||
|
|
34
src/util.rs
34
src/util.rs
|
@ -1,6 +1,6 @@
|
|||
use bitcoin::blockdata::block::BlockHeader;
|
||||
use bitcoin::hash_types::BlockHash;
|
||||
use bitcoin::util::hash::BitcoinHash;
|
||||
use bitcoin_hashes::sha256d::Hash as Sha256dHash;
|
||||
use bitcoin::blockdata::block::BlockHeader;
|
||||
use std::collections::HashMap;
|
||||
use std::convert::TryInto;
|
||||
use std::fmt;
|
||||
|
@ -11,7 +11,7 @@ use std::thread;
|
|||
use time;
|
||||
|
||||
pub type Bytes = Vec<u8>;
|
||||
pub type HeaderMap = HashMap<Sha256dHash, BlockHeader>;
|
||||
pub type HeaderMap = HashMap<BlockHash, BlockHeader>;
|
||||
|
||||
// TODO: consolidate serialization/deserialize code for bincode/bitcoin.
|
||||
const HASH_LEN: usize = 32;
|
||||
|
@ -33,12 +33,12 @@ pub fn full_hash(hash: &[u8]) -> FullHash {
|
|||
#[derive(Eq, PartialEq, Clone)]
|
||||
pub struct HeaderEntry {
|
||||
height: usize,
|
||||
hash: Sha256dHash,
|
||||
hash: BlockHash,
|
||||
header: BlockHeader,
|
||||
}
|
||||
|
||||
impl HeaderEntry {
|
||||
pub fn hash(&self) -> &Sha256dHash {
|
||||
pub fn hash(&self) -> &BlockHash {
|
||||
&self.hash
|
||||
}
|
||||
|
||||
|
@ -66,7 +66,7 @@ impl fmt::Debug for HeaderEntry {
|
|||
}
|
||||
|
||||
struct HashedHeader {
|
||||
blockhash: Sha256dHash,
|
||||
blockhash: BlockHash,
|
||||
header: BlockHeader,
|
||||
}
|
||||
|
||||
|
@ -88,7 +88,7 @@ fn hash_headers(headers: Vec<BlockHeader>) -> Vec<HashedHeader> {
|
|||
|
||||
pub struct HeaderList {
|
||||
headers: Vec<HeaderEntry>,
|
||||
heights: HashMap<Sha256dHash, usize>,
|
||||
heights: HashMap<BlockHash, usize>,
|
||||
}
|
||||
|
||||
impl HeaderList {
|
||||
|
@ -106,7 +106,7 @@ impl HeaderList {
|
|||
Some(h) => h.header.prev_blockhash,
|
||||
None => return vec![], // hashed_headers is empty
|
||||
};
|
||||
let null_hash = Sha256dHash::default();
|
||||
let null_hash = BlockHash::default();
|
||||
let new_height: usize = if prev_blockhash == null_hash {
|
||||
0
|
||||
} else {
|
||||
|
@ -125,8 +125,8 @@ impl HeaderList {
|
|||
.collect()
|
||||
}
|
||||
|
||||
pub fn apply(&mut self, new_headers: Vec<HeaderEntry>, tip: Sha256dHash) {
|
||||
if tip == Sha256dHash::default() {
|
||||
pub fn apply(&mut self, new_headers: Vec<HeaderEntry>, tip: BlockHash) {
|
||||
if tip == BlockHash::default() {
|
||||
assert!(new_headers.is_empty());
|
||||
self.heights.clear();
|
||||
self.headers.clear();
|
||||
|
@ -150,7 +150,7 @@ impl HeaderList {
|
|||
let expected_prev_blockhash = if height > 0 {
|
||||
*self.headers[height - 1].hash()
|
||||
} else {
|
||||
Sha256dHash::default()
|
||||
BlockHash::default()
|
||||
};
|
||||
assert_eq!(entry.header().prev_blockhash, expected_prev_blockhash);
|
||||
// First new header's height (may override existing headers)
|
||||
|
@ -182,7 +182,7 @@ impl HeaderList {
|
|||
assert!(self.heights.contains_key(&tip));
|
||||
}
|
||||
|
||||
pub fn header_by_blockhash(&self, blockhash: &Sha256dHash) -> Option<&HeaderEntry> {
|
||||
pub fn header_by_blockhash(&self, blockhash: &BlockHash) -> Option<&HeaderEntry> {
|
||||
let height = self.heights.get(blockhash)?;
|
||||
let header = self.headers.get(*height)?;
|
||||
if *blockhash == *header.hash() {
|
||||
|
@ -203,7 +203,7 @@ impl HeaderList {
|
|||
self.headers.last() == other.headers.last()
|
||||
}
|
||||
|
||||
pub fn tip(&self) -> Sha256dHash {
|
||||
pub fn tip(&self) -> BlockHash {
|
||||
self.headers.last().map(|h| *h.hash()).unwrap_or_default()
|
||||
}
|
||||
|
||||
|
@ -285,24 +285,24 @@ mod tests {
|
|||
#[test]
|
||||
fn test_headers() {
|
||||
use bitcoin::blockdata::block::BlockHeader;
|
||||
use bitcoin::hash_types::{BlockHash, TxMerkleNode};
|
||||
use bitcoin::util::hash::BitcoinHash;
|
||||
use bitcoin_hashes::sha256d::Hash as Sha256dHash;
|
||||
use bitcoin_hashes::Hash;
|
||||
|
||||
use super::HeaderList;
|
||||
|
||||
// Test an empty header list
|
||||
let null_hash = Sha256dHash::default();
|
||||
let null_hash = BlockHash::default();
|
||||
let mut header_list = HeaderList::empty();
|
||||
assert_eq!(header_list.tip(), null_hash);
|
||||
let ordered = header_list.order(vec![]);
|
||||
assert_eq!(ordered.len(), 0);
|
||||
header_list.apply(vec![], null_hash);
|
||||
|
||||
let merkle_root = Sha256dHash::hash(&[255]);
|
||||
let merkle_root = TxMerkleNode::hash(&[255]);
|
||||
let mut headers = vec![BlockHeader {
|
||||
version: 1,
|
||||
prev_blockhash: Sha256dHash::default(),
|
||||
prev_blockhash: BlockHash::default(),
|
||||
merkle_root,
|
||||
time: 0,
|
||||
bits: 0,
|
||||
|
|
Loading…
Add table
Reference in a new issue