diff --git a/src/internal_macros.rs b/src/internal_macros.rs index d6e2b3a..2513701 100644 --- a/src/internal_macros.rs +++ b/src/internal_macros.rs @@ -159,6 +159,39 @@ macro_rules! impl_array_newtype( } ) +macro_rules! impl_array_newtype_encodable( + ($thing:ident, $ty:ty, $len:expr) => { + impl, E> ::serialize::Decodable for $thing { + fn decode(d: &mut D) -> ::std::prelude::Result<$thing, E> { + use serialize::Decodable; + + ::assert_type_is_copy::<$ty>(); + + d.read_seq(|d, len| { + if len != $len { + Err(d.error("Invalid length")) + } else { + unsafe { + use std::mem; + let mut ret: [$ty, ..$len] = mem::uninitialized(); + for i in range(0, len) { + ret[i] = try!(d.read_seq_elt(i, |d| Decodable::decode(d))); + } + Ok($thing(ret)) + } + } + }) + } + } + + impl, S> ::serialize::Encodable for $thing { + fn encode(&self, e: &mut E) -> ::std::prelude::Result<(), S> { + self.as_slice().encode(e) + } + } + } +) + macro_rules! impl_array_newtype_show( ($thing:ident) => { impl ::std::fmt::Show for $thing { diff --git a/src/lib.rs b/src/lib.rs index 4a26682..cf1fa7e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -68,3 +68,6 @@ pub mod blockdata; pub mod util; pub mod wallet; +/// I dunno where else to put this.. +fn assert_type_is_copy() { } + diff --git a/src/macros.rs b/src/macros.rs index 6f4d882..2dab6e8 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -84,4 +84,35 @@ macro_rules! nu_select( }) ) +#[macro_export] +macro_rules! user_enum( + ($(#[$attr:meta])* pub enum $name:ident { $(#[$doc:meta] $elem:ident <-> $txt:expr),* }) => ( + $(#[$attr])* + pub enum $name { + $(#[$doc] $elem),* + } + + impl ::std::fmt::Show for $name { + fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + f.pad(match *self { + $($elem => $txt),* + }) + } + } + + impl, E> ::serialize::Encodable for $name { + fn encode(&self, s: &mut S) -> Result<(), E> { + s.emit_str(self.to_string().as_slice()) + } + } + + impl , E> ::serialize::Decodable for $name { + fn decode(d: &mut D) -> Result<$name, E> { + let s = try!(d.read_str()); + $( if s.as_slice() == $txt { Ok($elem) } )else* + else { Err(d.error(format!("unknown `{}`", s).as_slice())) } + } + } + ); +) diff --git a/src/network/constants.rs b/src/network/constants.rs index 0971b45..9188eea 100644 --- a/src/network/constants.rs +++ b/src/network/constants.rs @@ -18,46 +18,19 @@ //! protocol, such as protocol versioning and magic header bytes. //! -use std::fmt; -use serialize::{Decoder, Encoder, Encodable, Decodable}; - use network::encodable::{ConsensusDecodable, ConsensusEncodable}; use network::serialize::{SimpleEncoder, SimpleDecoder}; -/// The cryptocurrency to operate on -#[deriving(PartialEq, Eq, Clone, Hash)] -pub enum Network { - /// Classic Bitcoin - Bitcoin, - /// Bitcoin's testnet - BitcoinTestnet, -} - -impl fmt::Show for Network { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.pad(match *self { - Bitcoin => "bitcoin", - BitcoinTestnet => "testnet", - }) +user_enum!( + #[deriving(PartialEq, Eq, Clone, Hash)] + #[doc="The cryptocurrency to act on"] + pub enum Network { + #[doc="Classic Bitcoin"] + Bitcoin <-> "bitcoin", + #[doc="Bitcoin's testnet"] + BitcoinTestnet <-> "testnet" } -} - -impl, E> Encodable for Network { - fn encode(&self, s: &mut S) -> Result<(), E> { - s.emit_str(self.to_string().as_slice()) - } -} - -impl , E> Decodable for Network { - fn decode(d: &mut D) -> Result { - let s = try!(d.read_str()); - match s.as_slice() { - "bitcoin" => Ok(Bitcoin), - "testnet" => Ok(BitcoinTestnet), - _ => Err(d.error(format!("Unknown network {}", s).as_slice())) - } - } -} +) pub static PROTOCOL_VERSION: u32 = 70001; pub static SERVICES: u64 = 0; diff --git a/src/wallet/address_index.rs b/src/wallet/address_index.rs index d2b35b1..7f1e3aa 100644 --- a/src/wallet/address_index.rs +++ b/src/wallet/address_index.rs @@ -28,7 +28,7 @@ use util::hash::Sha256dHash; /// An address index #[deriving(Clone, PartialEq, Eq, Show)] pub struct AddressIndex { - index: HashMap + index: HashMap> } impl AddressIndex { @@ -40,7 +40,9 @@ impl AddressIndex { }; for (key, idx, txo) in utxo_set.iter() { if wallet.might_be_mine(txo) { - ret.index.insert(txo.script_pubkey.clone(), (key, idx)); + ret.index.insert_or_update_with(txo.script_pubkey.clone(), + vec![(key, idx)], + |_, v| v.push((key, idx))); } } ret diff --git a/src/wallet/bip32.rs b/src/wallet/bip32.rs index 7503dab..d59053f 100644 --- a/src/wallet/bip32.rs +++ b/src/wallet/bip32.rs @@ -37,18 +37,20 @@ use util::base58::{Base58Error, pub struct ChainCode([u8, ..32]); impl_array_newtype!(ChainCode, u8, 32) impl_array_newtype_show!(ChainCode) +impl_array_newtype_encodable!(ChainCode, u8, 32) /// A fingerprint pub struct Fingerprint([u8, ..4]); impl_array_newtype!(Fingerprint, u8, 4) impl_array_newtype_show!(Fingerprint) +impl_array_newtype_encodable!(Fingerprint, u8, 4) impl Default for Fingerprint { fn default() -> Fingerprint { Fingerprint([0, 0, 0, 0]) } } /// Extended private key -#[deriving(Clone, PartialEq, Eq, Show)] +#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Show)] pub struct ExtendedPrivKey { /// The network this key is to be used on pub network: Network, @@ -65,7 +67,7 @@ pub struct ExtendedPrivKey { } /// Extended public key -#[deriving(Clone, PartialEq, Eq, Show)] +#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Show)] pub struct ExtendedPubKey { /// The network this key is to be used on pub network: Network, @@ -82,7 +84,7 @@ pub struct ExtendedPubKey { } /// A child number for a derived key -#[deriving(Clone, PartialEq, Eq, Show)] +#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Show)] pub enum ChildNumber { /// Hardened key index, within [0, 2^31 - 1] Hardened(u32), @@ -98,7 +100,9 @@ pub enum Error { /// A secp256k1 error occured EcdsaError(secp256k1::Error), /// A child number was provided that was out of range - InvalidChildNumber(ChildNumber) + InvalidChildNumber(ChildNumber), + /// Error creating a master seed --- for application use + RngError(String) } impl ExtendedPrivKey { diff --git a/src/wallet/wallet.rs b/src/wallet/wallet.rs index 49d35ce..8b48732 100644 --- a/src/wallet/wallet.rs +++ b/src/wallet/wallet.rs @@ -34,7 +34,7 @@ pub enum Error { } /// An account -#[deriving(Clone, PartialEq, Eq, Show)] +#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Show)] pub struct Account { name: String, internal_path: Vec, @@ -52,7 +52,7 @@ impl Default for Account { } /// A wallet -#[deriving(Clone, PartialEq, Eq, Show)] +#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Show)] pub struct Wallet { master: ExtendedPrivKey, accounts: HashMap