Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Upgrade bitcoin version and remove lightning #40

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,9 @@ name = "murmel"
path = "src/lib.rs"

[dependencies]
lightning = { version ="0.0.9", optional=true }
bitcoin = { version= "0.21", features=["use-serde"]}
bitcoin = { version= "0.23", features=["use-serde"]}
bitcoin_hashes = "0.7"
hammersbald = { version= "2.4", features=["bitcoin_support"]}
hammersbald = { git= "https://github.com/jrawsthorne/hammersbald.git", branch="upgrade-bitcoin", features=["bitcoin_support"]}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should change once the upgrade-bitcoin branch is merged in the hammersbald repo.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah I'll change it when that gets merged. Wanted to make sure tests passed

mio = "0.6"
rand = "0.7"
log = "0.4"
Expand Down
34 changes: 16 additions & 18 deletions src/chaindb.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,8 @@ use std::path::Path;

use bitcoin::{BitcoinHash, Network};
use bitcoin::blockdata::block::BlockHeader;
use bitcoin::blockdata::constants::genesis_block;
use bitcoin::{BlockHash, blockdata::constants::genesis_block};

use bitcoin_hashes::sha256d;
use hammersbald::{BitcoinAdaptor, HammersbaldAPI, persistent, transient};

use crate::error::Error;
Expand Down Expand Up @@ -80,7 +79,7 @@ impl ChainDB {
while let Some(stored) = self.fetch_header(&h)? {
debug!("read stored header {}", &stored.bitcoin_hash());
self.headercache.add_header_unchecked(&h, &stored);
if stored.header.prev_blockhash != sha256d::Hash::default() {
if stored.header.prev_blockhash != BlockHash::default() {
h = stored.header.prev_blockhash;
} else {
break;
Expand All @@ -103,7 +102,7 @@ impl ChainDB {
let genesis = genesis_block(self.network).header;
if let Some((cached, _, _)) = self.headercache.add_header(&genesis)? {
info!("initialized with genesis header {}", genesis.bitcoin_hash());
self.db.put_hash_keyed(&cached.stored)?;
self.db.put_hash_keyed(&cached.bitcoin_hash().as_hash(), &cached.stored)?;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we preserve the API here?

self.db.batch()?;
self.store_header_tip(&cached.bitcoin_hash())?;
self.db.batch()?;
Expand All @@ -115,9 +114,9 @@ impl ChainDB {
}

/// Store a header
pub fn add_header(&mut self, header: &BlockHeader) -> Result<Option<(StoredHeader, Option<Vec<sha256d::Hash>>, Option<Vec<sha256d::Hash>>)>, Error> {
pub fn add_header(&mut self, header: &BlockHeader) -> Result<Option<(StoredHeader, Option<Vec<BlockHash>>, Option<Vec<BlockHash>>)>, Error> {
if let Some((cached, unwinds, forward)) = self.headercache.add_header(header)? {
self.db.put_hash_keyed(&cached.stored)?;
self.db.put_hash_keyed(&cached.bitcoin_hash().as_hash(), &cached.stored)?;
if let Some(forward) = forward.clone() {
if forward.len() > 0 {
self.store_header_tip(forward.last().unwrap())?;
Expand All @@ -129,7 +128,7 @@ impl ChainDB {
}

/// return position of hash on trunk if hash is on trunk
pub fn pos_on_trunk(&self, hash: &sha256d::Hash) -> Option<u32> {
pub fn pos_on_trunk(&self, hash: &BlockHash) -> Option<u32> {
self.headercache.pos_on_trunk(hash)
}

Expand All @@ -149,7 +148,7 @@ impl ChainDB {
}

/// Fetch a header by its id from cache
pub fn get_header(&self, id: &sha256d::Hash) -> Option<CachedHeader> {
pub fn get_header(&self, id: &BlockHash) -> Option<CachedHeader> {
self.headercache.get_header(id)
}

Expand All @@ -159,24 +158,24 @@ impl ChainDB {
}

/// locator for getheaders message
pub fn header_locators(&self) -> Vec<sha256d::Hash> {
pub fn header_locators(&self) -> Vec<BlockHash> {
self.headercache.locator_hashes()
}

/// Store the header id with most work
pub fn store_header_tip(&mut self, tip: &sha256d::Hash) -> Result<(), Error> {
pub fn store_header_tip(&mut self, tip: &BlockHash) -> Result<(), Error> {
self.db.put_keyed_encodable(HEADER_TIP_KEY, tip)?;
Ok(())
}

/// Find header id with most work
pub fn fetch_header_tip(&self) -> Result<Option<sha256d::Hash>, Error> {
Ok(self.db.get_keyed_decodable::<sha256d::Hash>(HEADER_TIP_KEY)?.map(|(_, h)| h.clone()))
pub fn fetch_header_tip(&self) -> Result<Option<BlockHash>, Error> {
Ok(self.db.get_keyed_decodable::<BlockHash>(HEADER_TIP_KEY)?.map(|(_, h)| h.clone()))
}

/// Read header from the DB
pub fn fetch_header(&self, id: &sha256d::Hash) -> Result<Option<StoredHeader>, Error> {
Ok(self.db.get_hash_keyed::<StoredHeader>(id)?.map(|(_, header)| header))
pub fn fetch_header(&self, id: &BlockHash) -> Result<Option<StoredHeader>, Error> {
Ok(self.db.get_hash_keyed::<StoredHeader>(&id.as_hash())?.map(|(_, header)| header))
}

/// Shutdown db
Expand All @@ -198,8 +197,8 @@ pub struct StoredHeader {
}

// need to implement if put_hash_keyed and get_hash_keyed should be used
impl BitcoinHash for StoredHeader {
fn bitcoin_hash(&self) -> sha256d::Hash {
impl BitcoinHash<BlockHash> for StoredHeader {
fn bitcoin_hash(&self) -> BlockHash {
self.header.bitcoin_hash()
}
}
Expand All @@ -209,7 +208,6 @@ const HEADER_TIP_KEY: &[u8] = &[0u8; 1];
#[cfg(test)]
mod test {
use bitcoin::{Network, BitcoinHash};
use bitcoin_hashes::sha256d::Hash;
use bitcoin::blockdata::constants::genesis_block;

use crate::chaindb::ChainDB;
Expand All @@ -234,7 +232,7 @@ mod test {
let genesis_header = genesis_block(network).header;

let mut chaindb = ChainDB::mem(network).unwrap();
let missing_tip_header_hash: Hash = "6cfb35868c4465b7c289d7d5641563aa973db6a929655282a7bf95c8257f53ef".parse().unwrap();
let missing_tip_header_hash = "6cfb35868c4465b7c289d7d5641563aa973db6a929655282a7bf95c8257f53ef".parse().unwrap();
chaindb.store_header_tip(&missing_tip_header_hash).unwrap();

chaindb.init().unwrap();
Expand Down
13 changes: 5 additions & 8 deletions src/constructor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@

use bitcoin::{
network::{
constants::Network
constants::{ServiceFlags, Network}
}
};
use crate::chaindb::{ChainDB, SharedChainDB};
Expand All @@ -39,7 +39,6 @@ use futures::{
use std::pin::Pin;
use futures_timer::Interval;
use crate::headerdownload::HeaderDownload;
#[cfg(feature = "lightning")] use crate::lightning::LightningConnector;
use crate::p2p::{P2P, P2PControl, PeerMessageSender, PeerSource};
use crate::ping::Ping;
use rand::{RngCore, thread_rng};
Expand Down Expand Up @@ -98,22 +97,20 @@ impl Constructor {
let (p2p, p2p_control) =
P2P::new(p2pconfig, PeerMessageSender::new(to_dispatcher), BACK_PRESSURE);

#[cfg(feature = "lightning")] let lightning = Arc::new(Mutex::new(LightningConnector::new(network, p2p_control.clone())));
#[cfg(not(feature = "lightning"))] let lightning = Arc::new(Mutex::new(DownStreamDummy {}));

let downstream = Arc::new(Mutex::new(DownStreamDummy {}));

let timeout = Arc::new(Mutex::new(Timeout::new(p2p_control.clone())));

let mut dispatcher = Dispatcher::new(from_p2p);

dispatcher.add_listener(HeaderDownload::new(chaindb.clone(), p2p_control.clone(), timeout.clone(), lightning.clone()));
dispatcher.add_listener(HeaderDownload::new(chaindb.clone(), p2p_control.clone(), timeout.clone(), downstream.clone()));
dispatcher.add_listener(Ping::new(p2p_control.clone(), timeout.clone()));

for addr in &listen {
p2p_control.send(P2PControl::Bind(addr.clone()));
}

Ok(Constructor { p2p, downstream: lightning })
Ok(Constructor { p2p, downstream })
}

/// Run the stack. This should be called AFTER registering listener of the ChainWatchInterface,
Expand Down Expand Up @@ -141,7 +138,7 @@ impl Constructor {
let p2p = self.p2p.clone();
let mut cex = executor.clone();
executor.run(future::poll_fn(move |_| {
let needed_services = 0;
let needed_services = ServiceFlags::NONE;
p2p.poll_events("bitcoin", needed_services, &mut cex);
Async::Ready(())
}));
Expand Down
33 changes: 16 additions & 17 deletions src/headercache.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,8 @@ use bitcoin::{
network::constants::Network,
util::{
uint::Uint256,
},
}, BlockHash,
};
use bitcoin_hashes::sha256d::Hash as Sha256dHash;
use bitcoin_hashes::Hash;
use crate::chaindb::StoredHeader;
use crate::error::Error;
Expand All @@ -37,11 +36,11 @@ use std::{
#[derive(Clone)]
pub struct CachedHeader {
pub stored : StoredHeader,
id: Sha256dHash
id: BlockHash
}

impl CachedHeader {
pub fn new (id: &Sha256dHash, header: StoredHeader) -> CachedHeader {
pub fn new (id: &BlockHash, header: StoredHeader) -> CachedHeader {
CachedHeader{ stored: header, id: id.clone() }
}

Expand Down Expand Up @@ -97,8 +96,8 @@ impl CachedHeader {
}
}

impl BitcoinHash for CachedHeader {
fn bitcoin_hash(&self) -> Sha256dHash {
impl BitcoinHash<BlockHash> for CachedHeader {
fn bitcoin_hash(&self) -> BlockHash {
self.id
}
}
Expand All @@ -107,9 +106,9 @@ pub struct HeaderCache {
// network
network: Network,
// all known headers
headers: HashMap<Sha256dHash, CachedHeader>,
headers: HashMap<BlockHash, CachedHeader>,
// header chain with most work
trunk: Vec<Sha256dHash>,
trunk: Vec<BlockHash>,
}

const EXPECTED_CHAIN_LENGTH: usize = 600000;
Expand All @@ -119,7 +118,7 @@ impl HeaderCache {
HeaderCache { network, headers: HashMap::with_capacity(EXPECTED_CHAIN_LENGTH), trunk: Vec::with_capacity(EXPECTED_CHAIN_LENGTH) }
}

pub fn add_header_unchecked(&mut self, id: &Sha256dHash, stored: &StoredHeader) {
pub fn add_header_unchecked(&mut self, id: &BlockHash, stored: &StoredHeader) {
let cached = CachedHeader::new(id, stored.clone());
self.headers.insert(id.clone(), cached);
self.trunk.push(id.clone());
Expand All @@ -134,12 +133,12 @@ impl HeaderCache {
}

/// add a Bitcoin header
pub fn add_header(&mut self, header: &BlockHeader) -> Result<Option<(CachedHeader, Option<Vec<Sha256dHash>>, Option<Vec<Sha256dHash>>)>, Error> {
pub fn add_header(&mut self, header: &BlockHeader) -> Result<Option<(CachedHeader, Option<Vec<BlockHash>>, Option<Vec<BlockHash>>)>, Error> {
if self.headers.get(&header.bitcoin_hash()).is_some() {
// ignore already known header
return Ok(None);
}
if header.prev_blockhash != Sha256dHash::default() {
if header.prev_blockhash != BlockHash::default() {
// regular update
let previous;
if let Some(prev) = self.headers.get(&header.prev_blockhash) {
Expand Down Expand Up @@ -186,7 +185,7 @@ impl HeaderCache {
}

// add header to tree, return stored, optional list of unwinds, optional list of extensions
fn add_header_to_tree(&mut self, prev: &CachedHeader, next: &BlockHeader) -> Result<(CachedHeader, Option<Vec<Sha256dHash>>, Option<Vec<Sha256dHash>>), Error> {
fn add_header_to_tree(&mut self, prev: &CachedHeader, next: &BlockHeader) -> Result<(CachedHeader, Option<Vec<BlockHash>>, Option<Vec<BlockHash>>), Error> {
const DIFFCHANGE_INTERVAL: u32 = 2016;
const DIFFCHANGE_TIMESPAN: u32 = 14 * 24 * 3600;
const TARGET_BLOCK_SPACING: u32 = 600;
Expand Down Expand Up @@ -238,7 +237,7 @@ impl HeaderCache {
let mut scan = prev.clone();
let mut height = prev.stored.height;
let max_target = Self::max_target();
while height % DIFFCHANGE_INTERVAL != 0 && scan.stored.header.prev_blockhash != Sha256dHash::default() && scan.stored.header.target() == max_target {
while height % DIFFCHANGE_INTERVAL != 0 && scan.stored.header.prev_blockhash != BlockHash::default() && scan.stored.header.target() == max_target {
if let Some(header) = self.headers.get(&scan.stored.header.prev_blockhash) {
scan = header.clone();
height = header.stored.height;
Expand Down Expand Up @@ -317,7 +316,7 @@ impl HeaderCache {
}

/// position on trunk (chain with most work from genesis to tip)
pub fn pos_on_trunk(&self, hash: &Sha256dHash) -> Option<u32> {
pub fn pos_on_trunk(&self, hash: &BlockHash) -> Option<u32> {
self.trunk.iter().rev().position(|e| { *e == *hash }).map(|p| (self.trunk.len() - p - 1) as u32)
}

Expand All @@ -329,7 +328,7 @@ impl HeaderCache {
None
}

pub fn tip_hash(&self) -> Option<Sha256dHash> {
pub fn tip_hash(&self) -> Option<BlockHash> {
if let Some(tip) = self.trunk.last() {
return Some(*tip);
}
Expand All @@ -355,7 +354,7 @@ impl HeaderCache {
}

/// Fetch a header by its id from cache
pub fn get_header(&self, id: &Sha256dHash) -> Option<CachedHeader> {
pub fn get_header(&self, id: &BlockHash) -> Option<CachedHeader> {
if let Some(header) = self.headers.get(id) {
return Some(header.clone());
}
Expand Down Expand Up @@ -386,7 +385,7 @@ impl HeaderCache {
}

// locator for getheaders message
pub fn locator_hashes(&self) -> Vec<Sha256dHash> {
pub fn locator_hashes(&self) -> Vec<BlockHash> {
let mut locator = vec!();
let mut skip = 1;
let mut count = 0;
Expand Down
17 changes: 8 additions & 9 deletions src/headerdownload.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,11 @@
//!
use bitcoin::{BitcoinHash, network::{
message::NetworkMessage,
message_blockdata::{GetHeadersMessage, Inventory, InvType},
}, BlockHeader};
use bitcoin_hashes::sha256d::Hash as Sha256dHash;
message_blockdata::{GetHeadersMessage, Inventory}, constants::ServiceFlags,
}, BlockHeader, BlockHash};
use crate::chaindb::SharedChainDB;
use crate::error::Error;
use crate::p2p::{P2PControl, P2PControlSender, PeerId, PeerMessage, PeerMessageReceiver, PeerMessageSender, SERVICE_BLOCKS};
use crate::p2p::{P2PControl, P2PControlSender, PeerId, PeerMessage, PeerMessageReceiver, PeerMessageSender};
use log::{info, trace, debug, error};
use std::{
collections::VecDeque,
Expand Down Expand Up @@ -86,7 +85,7 @@ impl HeaderDownload {

fn is_serving_blocks(&self, peer: PeerId) -> bool {
if let Some(peer_version) = self.p2p.peer_version(peer) {
return peer_version.services & SERVICE_BLOCKS != 0;
return peer_version.services.has(ServiceFlags::NETWORK);
}
false
}
Expand All @@ -96,10 +95,10 @@ impl HeaderDownload {
let mut ask_for_headers = false;
for inventory in v {
// only care for blocks
if inventory.inv_type == InvType::Block {
if let Inventory::Block(hash) = inventory {
let chaindb = self.chaindb.read().unwrap();
if chaindb.get_header(&inventory.hash).is_none() {
debug!("received inv for new block {} peer={}", inventory.hash, peer);
if chaindb.get_header(&hash).is_none() {
debug!("received inv for new block {} peer={}", hash, peer);
// ask for header(s) if observing a new block
ask_for_headers = true;
}
Expand All @@ -122,7 +121,7 @@ impl HeaderDownload {
let first = if locator.len() > 0 {
*locator.first().unwrap()
} else {
Sha256dHash::default()
BlockHash::default()
};
self.timeout.lock().unwrap().expect(peer, 1, ExpectedReply::Headers);
self.p2p.send_network(peer, NetworkMessage::GetHeaders(GetHeadersMessage::new(locator, first)));
Expand Down
1 change: 0 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@
#![deny(unused_must_use)]
#![forbid(unsafe_code)]

#[cfg(feature="lightning")] mod lightning;
mod headercache;

pub mod ping;
Expand Down
Loading