diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 3292561a5f..31d06ea2b0 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -145,7 +145,7 @@ grammar fixes. Pull request merge requirements: - all CI test should pass, -- at least two "accepts"/ACKs from the repository maintainers +- at least two "accepts"/ACKs from the repository maintainers (see "refactor carve out"). - no reasonable "rejects"/NACKs from anybody who reviewed the code. Current list of the project maintainers: @@ -153,6 +153,15 @@ Current list of the project maintainers: - [Hashengineering](https://github.com/hashengineering) - [Gruve-p](https://github.com/gruve-p) +#### Refactor carve output + +The repository is going through heavy refactoring and "trivial" API redesign +(eg, rename `Foo::empty` to `Foo::new`) as we push towards API stabilization. As +such reviewers are either bored or overloaded with notifications, hence we have +created a carve out to the 2-ACK rule. + +A PR may be considered for merge if it has a single ACK and has sat open for at +least two weeks with no comments, questions, or NACKs. ## Coding conventions diff --git a/fuzz/fuzz_targets/groestlcoin/deser_net_msg.rs b/fuzz/fuzz_targets/groestlcoin/deser_net_msg.rs index 3394f0cb40..c9e7a19654 100644 --- a/fuzz/fuzz_targets/groestlcoin/deser_net_msg.rs +++ b/fuzz/fuzz_targets/groestlcoin/deser_net_msg.rs @@ -1,7 +1,7 @@ use honggfuzz::fuzz; fn do_test(data: &[u8]) { - let _: Result = + let _: Result = groestlcoin::consensus::encode::deserialize(data); } diff --git a/fuzz/fuzz_targets/groestlcoin/deserialize_script.rs b/fuzz/fuzz_targets/groestlcoin/deserialize_script.rs index ec687ce4d1..17fd6b3caf 100644 --- a/fuzz/fuzz_targets/groestlcoin/deserialize_script.rs +++ b/fuzz/fuzz_targets/groestlcoin/deserialize_script.rs @@ -1,7 +1,7 @@ use groestlcoin::address::Address; use groestlcoin::blockdata::script; use groestlcoin::consensus::encode; -use groestlcoin::network::constants::Network; +use groestlcoin::Network; use honggfuzz::fuzz; fn do_test(data: &[u8]) { diff --git a/groestlcoin/examples/handshake.rs b/groestlcoin/examples/handshake.rs index 804027a8cd..6d81772d8e 100644 --- a/groestlcoin/examples/handshake.rs +++ b/groestlcoin/examples/handshake.rs @@ -6,7 +6,7 @@ use std::time::{SystemTime, UNIX_EPOCH}; use std::{env, process}; use groestlcoin::consensus::{encode, Decodable}; -use groestlcoin::network::{address, constants, message, message_network}; +use groestlcoin::p2p::{self, address, message, message_network}; use groestlcoin::secp256k1; use groestlcoin::secp256k1::rand::Rng; @@ -29,7 +29,7 @@ fn main() { let version_message = build_version_message(address); let first_message = - message::RawNetworkMessage::new(constants::Network::Groestlcoin.magic(), version_message); + message::RawNetworkMessage::new(bitcoin::Network::Groestlcoin.magic(), version_message); if let Ok(mut stream) = TcpStream::connect(address) { // Send the message @@ -47,7 +47,7 @@ fn main() { println!("Received version message: {:?}", reply.payload()); let second_message = message::RawNetworkMessage::new( - constants::Network::Groestlcoin.magic(), + groestlcoin::Network::Groestlcoin.magic(), message::NetworkMessage::Verack, ); @@ -75,16 +75,16 @@ fn build_version_message(address: SocketAddr) -> message::NetworkMessage { let my_address = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)), 0); // "bitfield of features to be enabled for this connection" - let services = constants::ServiceFlags::NONE; + let services = p2p::ServiceFlags::NONE; // "standard UNIX timestamp in seconds" let timestamp = SystemTime::now().duration_since(UNIX_EPOCH).expect("Time error").as_secs(); // "The network address of the node receiving this message" - let addr_recv = address::Address::new(&address, constants::ServiceFlags::NONE); + let addr_recv = address::Address::new(&address, p2p::ServiceFlags::NONE); // "The network address of the node emitting this message" - let addr_from = address::Address::new(&my_address, constants::ServiceFlags::NONE); + let addr_from = address::Address::new(&my_address, p2p::ServiceFlags::NONE); // "Node random nonce, randomly generated every time a version packet is sent. This nonce is used to detect connections to self." let nonce: u64 = secp256k1::rand::thread_rng().gen(); diff --git a/groestlcoin/src/address.rs b/groestlcoin/src/address.rs index 2c1f3decac..e0bc84fd54 100644 --- a/groestlcoin/src/address.rs +++ b/groestlcoin/src/address.rs @@ -43,10 +43,9 @@ use crate::blockdata::constants::{ }; use crate::blockdata::script::witness_program::{self, WitnessProgram}; use crate::blockdata::script::witness_version::{self, WitnessVersion}; -use crate::blockdata::script::{self, Script, ScriptBuf}; -use crate::crypto::key::{PublicKey, TapTweak, TweakedPublicKey, UntweakedPublicKey}; -use crate::hash_types::{PubkeyHash, ScriptHash}; -use crate::network::constants::Network; +use crate::blockdata::script::{self, Script, ScriptBuf, ScriptHash}; +use crate::crypto::key::{PubkeyHash, PublicKey, TapTweak, TweakedPublicKey, UntweakedPublicKey}; +use crate::network::Network; use crate::prelude::*; use crate::taproot::TapNodeHash; @@ -718,13 +717,6 @@ impl Address { /// pub fn is_spend_standard(&self) -> bool { self.address_type().is_some() } - /// Checks whether or not the address is following Bitcoin standardness rules. - /// - /// SegWit addresses with unassigned witness versions or non-standard program sizes are - /// considered non-standard. - #[deprecated(since = "0.30.0", note = "Use Address::is_spend_standard instead")] - pub fn is_standard(&self) -> bool { self.address_type().is_some() } - /// Constructs an [`Address`] from an output script (`scriptPubkey`). pub fn from_script(script: &Script, network: Network) -> Result { Ok(Address::new(network, Payload::from_script(script)?)) @@ -996,7 +988,7 @@ mod tests { use super::*; use crate::crypto::key::PublicKey; - use crate::network::constants::Network::{Groestlcoin, Testnet}; + use crate::network::Network::{Groestlcoin, Testnet}; fn roundtrips(addr: &Address) { assert_eq!( diff --git a/groestlcoin/src/base58.rs b/groestlcoin/src/base58.rs index 1b804b5743..659c5d3e1a 100644 --- a/groestlcoin/src/base58.rs +++ b/groestlcoin/src/base58.rs @@ -35,10 +35,6 @@ static BASE58_DIGITS: [Option; 128] = [ Some(55), Some(56), Some(57), None, None, None, None, None, // 120-127 ]; -/// Decodes a base58-encoded string into a byte vector. -#[deprecated(since = "0.30.0", note = "Use base58::decode() instead")] -pub fn from(data: &str) -> Result, Error> { decode(data) } - /// Decodes a base58-encoded string into a byte vector. pub fn decode(data: &str) -> Result, Error> { // 11/15 is just over log_256(58) @@ -70,10 +66,6 @@ pub fn decode(data: &str) -> Result, Error> { Ok(ret) } -/// Decodes a base58check-encoded string into a byte vector verifying the checksum. -#[deprecated(since = "0.30.0", note = "Use base58::decode_check() instead")] -pub fn from_check(data: &str) -> Result, Error> { decode_check(data) } - /// Decodes a base58check-encoded string into a byte vector verifying the checksum. pub fn decode_check(data: &str) -> Result, Error> { let mut ret: Vec = decode(data)?; @@ -97,19 +89,9 @@ pub fn decode_check(data: &str) -> Result, Error> { Ok(ret) } -/// Encodes `data` as a base58 string. -#[deprecated(since = "0.30.0", note = "Use base58::encode() instead")] -pub fn encode_slice(data: &[u8]) -> String { encode(data) } - /// Encodes `data` as a base58 string (see also `base58::encode_check()`). pub fn encode(data: &[u8]) -> String { encode_iter(data.iter().cloned()) } -/// Encodes `data` as a base58 string including the checksum. -/// -/// The checksum is the first four bytes of the groestld of the data, concatenated onto the end. -#[deprecated(since = "0.30.0", note = "Use base58::encode_check() instead")] -pub fn check_encode_slice(data: &[u8]) -> String { encode_check(data) } - /// Encodes `data` as a base58 string including the checksum. /// /// The checksum is the first four bytes of the groestld of the data, concatenated onto the end. @@ -118,14 +100,6 @@ pub fn encode_check(data: &[u8]) -> String { encode_iter(data.iter().cloned().chain(checksum[0..4].iter().cloned())) } -/// Encodes `data` as base58, including the checksum, into a formatter. -/// -/// The checksum is the first four bytes of the groestld of the data, concatenated onto the end. -#[deprecated(since = "0.30.0", note = "Use base58::encode_check_to_fmt() instead")] -pub fn check_encode_slice_to_fmt(fmt: &mut fmt::Formatter, data: &[u8]) -> fmt::Result { - encode_check_to_fmt(fmt, data) -} - /// Encodes a slice as base58, including the checksum, into a formatter. /// /// The checksum is the first four bytes of the groestld of the data, concatenated onto the end. diff --git a/groestlcoin/src/bip32.rs b/groestlcoin/src/bip32.rs index 84dcb07d1a..6ff1039f7a 100644 --- a/groestlcoin/src/bip32.rs +++ b/groestlcoin/src/bip32.rs @@ -23,7 +23,7 @@ use crate::crypto::key::{self, KeyPair, PrivateKey, PublicKey}; use crate::hash_types::XpubIdentifier; use crate::internal_macros::impl_bytes_newtype; use crate::io::Write; -use crate::network::constants::Network; +use crate::network::Network; use crate::prelude::*; /// A chain code @@ -866,7 +866,7 @@ mod tests { use super::ChildNumber::{Hardened, Normal}; use super::*; use crate::internal_macros::hex; - use crate::network::constants::Network::{self, Groestlcoin}; + use crate::network::Network::{self, Groestlcoin}; #[test] fn test_parse_derivation_path() { diff --git a/groestlcoin/src/blockdata/constants.rs b/groestlcoin/src/blockdata/constants.rs index 1700960a51..d3ec90046d 100644 --- a/groestlcoin/src/blockdata/constants.rs +++ b/groestlcoin/src/blockdata/constants.rs @@ -20,7 +20,7 @@ use crate::blockdata::script; use crate::blockdata::transaction::{OutPoint, Sequence, Transaction, TxIn, TxOut}; use crate::blockdata::witness::Witness; use crate::internal_macros::impl_bytes_newtype; -use crate::network::constants::Network; +use crate::network::Network; use crate::pow::CompactTarget; use crate::Amount; @@ -198,7 +198,7 @@ mod test { use crate::blockdata::locktime::absolute; use crate::consensus::encode::serialize; use crate::internal_macros::hex; - use crate::network::constants::Network; + use crate::network::Network; #[test] fn bitcoin_genesis_first_transaction() { diff --git a/groestlcoin/src/blockdata/fee_rate.rs b/groestlcoin/src/blockdata/fee_rate.rs index 1a7ccdeda0..4bb0404e43 100644 --- a/groestlcoin/src/blockdata/fee_rate.rs +++ b/groestlcoin/src/blockdata/fee_rate.rs @@ -82,11 +82,37 @@ impl FeeRate { /// Checked weight multiplication. /// - /// Computes `self * rhs` where rhs is of type Weight. `None` is returned if an overflow - /// occured. + /// Computes `self * rhs` where rhs is of type Weight. `None` is returned if an overflow + /// occurred. pub fn checked_mul_by_weight(self, rhs: Weight) -> Option { self.0.checked_mul(rhs.to_wu()).map(Amount::from_sat) } + + /// Calculates fee by multiplying this fee rate by weight, in weight units, returning `None` + /// if overflow occurred. + /// + /// This is equivalent to `Self::checked_mul_by_weight()`. + /// + /// # Examples + /// + /// ```no_run + /// # use bitcoin::{absolute, FeeRate, Transaction}; + /// # // Dummy transaction. + /// # let tx = Transaction { version: 1, lock_time: absolute::LockTime::ZERO, input: vec![], output: vec![] }; + /// + /// let rate = FeeRate::from_sat_per_vb(1).expect("1 sat/vbyte is valid"); + /// let fee = rate.fee_wu(tx.weight()); + /// ``` + pub fn fee_wu(self, weight: Weight) -> Option { self.checked_mul_by_weight(weight) } + + /// Calculates fee by multiplying this fee rate by weight, in virtual bytes, returning `None` + /// if overflow occurred. + /// + /// This is equivalent to converting `vb` to `weight` using `Weight::from_vb` and then calling + /// `Self::fee_wu(weight)`. + pub fn fee_vb(self, vb: u64) -> Option { + Weight::from_vb(vb).and_then(|w| self.fee_wu(w)) + } } /// Alternative will display the unit. @@ -199,4 +225,20 @@ mod tests { let fee_rate = FeeRate(10).checked_div(0); assert!(fee_rate.is_none()); } + + #[test] + fn fee_convenience_functions_agree() { + use crate::blockdata::transaction::Transaction; + use crate::consensus::Decodable; + use crate::internal_macros::hex; + + const SOME_TX: &str = "0100000001a15d57094aa7a21a28cb20b59aab8fc7d1149a3bdbcddba9c622e4f5f6a99ece010000006c493046022100f93bb0e7d8db7bd46e40132d1f8242026e045f03a0efe71bbb8e3f475e970d790221009337cd7f1f929f00cc6ff01f03729b069a7c21b59b1736ddfee5db5946c5da8c0121033b9b137ee87d5a812d6f506efdd37f0affa7ffc310711c06c7f3e097c9447c52ffffffff0100e1f505000000001976a9140389035a9225b3839e2bbf32d826a1e222031fd888ac00000000"; + + let raw_tx = hex!(SOME_TX); + let tx: Transaction = Decodable::consensus_decode(&mut raw_tx.as_slice()).unwrap(); + + let rate = FeeRate::from_sat_per_vb(1).expect("1 sat/byte is valid"); + + assert_eq!(rate.fee_vb(tx.vsize() as u64), rate.fee_wu(tx.weight())); + } } diff --git a/groestlcoin/src/blockdata/script/borrowed.rs b/groestlcoin/src/blockdata/script/borrowed.rs index 7aa014355b..25113b8d6d 100644 --- a/groestlcoin/src/blockdata/script/borrowed.rs +++ b/groestlcoin/src/blockdata/script/borrowed.rs @@ -14,9 +14,9 @@ use crate::blockdata::opcodes::{self}; use crate::blockdata::script::witness_version::WitnessVersion; use crate::blockdata::script::{ bytes_to_asm_fmt, Builder, Instruction, InstructionIndices, Instructions, ScriptBuf, + ScriptHash, WScriptHash, }; use crate::consensus::Encodable; -use crate::hash_types::{ScriptHash, WScriptHash}; use crate::key::{PublicKey, UntweakedPublicKey}; use crate::policy::DUST_RELAY_TX_FEE; use crate::prelude::*; diff --git a/groestlcoin/src/blockdata/script/mod.rs b/groestlcoin/src/blockdata/script/mod.rs index ee45ed45ce..3c024ccfe6 100644 --- a/groestlcoin/src/blockdata/script/mod.rs +++ b/groestlcoin/src/blockdata/script/mod.rs @@ -55,13 +55,13 @@ use core::cmp::Ordering; use core::fmt; use core::ops::{Deref, DerefMut}; +use hashes::{hash160, sha256}; #[cfg(feature = "serde")] use serde; use crate::blockdata::opcodes::all::*; use crate::blockdata::opcodes::{self}; use crate::consensus::{encode, Decodable, Encodable}; -use crate::hash_types::{ScriptHash, WScriptHash}; use crate::prelude::*; use crate::{io, OutPoint}; @@ -81,6 +81,38 @@ pub use self::instruction::*; pub use self::owned::*; pub use self::push_bytes::*; +hashes::hash_newtype! { + /// A hash of Bitcoin Script bytecode. + pub struct ScriptHash(hash160::Hash); + /// SegWit version of a Bitcoin Script bytecode hash. + pub struct WScriptHash(sha256::Hash); +} +crate::hash_types::impl_asref_push_bytes!(ScriptHash, WScriptHash); + +impl From for ScriptHash { + fn from(script: ScriptBuf) -> ScriptHash { script.script_hash() } +} + +impl From<&ScriptBuf> for ScriptHash { + fn from(script: &ScriptBuf) -> ScriptHash { script.script_hash() } +} + +impl From<&Script> for ScriptHash { + fn from(script: &Script) -> ScriptHash { script.script_hash() } +} + +impl From for WScriptHash { + fn from(script: ScriptBuf) -> WScriptHash { script.wscript_hash() } +} + +impl From<&ScriptBuf> for WScriptHash { + fn from(script: &ScriptBuf) -> WScriptHash { script.wscript_hash() } +} + +impl From<&Script> for WScriptHash { + fn from(script: &Script) -> WScriptHash { script.wscript_hash() } +} + /// Encodes an integer in script(minimal CScriptNum) format. /// /// Writes bytes into the buffer and returns the number of bytes written. @@ -182,24 +214,6 @@ pub fn read_scriptbool(v: &[u8]) -> bool { } } -/// Decodes a script-encoded unsigned integer. -/// -/// ## Errors -/// -/// This function returns an error in these cases: -/// -/// * `data` is shorter than `size` => `EarlyEndOfScript` -/// * `size` is greater than `u16::MAX / 8` (8191) => `NumericOverflow` -/// * The number being read overflows `usize` => `NumericOverflow` -/// -/// Note that this does **not** return an error for `size` between `core::size_of::()` -/// and `u16::MAX / 8` if there's no overflow. -#[inline] -#[deprecated(since = "0.30.0", note = "bitcoin integers are signed 32 bits, use read_scriptint")] -pub fn read_uint(data: &[u8], size: usize) -> Result { - read_uint_iter(&mut data.iter(), size).map_err(Into::into) -} - // We internally use implementation based on iterator so that it automatically advances as needed // Errors are same as above, just different type. fn read_uint_iter(data: &mut core::slice::Iter<'_, u8>, size: usize) -> Result { @@ -304,30 +318,6 @@ impl From for Vec { fn from(v: ScriptBuf) -> Self { v.0 } } -impl From for ScriptHash { - fn from(script: ScriptBuf) -> ScriptHash { script.script_hash() } -} - -impl From<&ScriptBuf> for ScriptHash { - fn from(script: &ScriptBuf) -> ScriptHash { script.script_hash() } -} - -impl From<&Script> for ScriptHash { - fn from(script: &Script) -> ScriptHash { script.script_hash() } -} - -impl From for WScriptHash { - fn from(script: ScriptBuf) -> WScriptHash { script.wscript_hash() } -} - -impl From<&ScriptBuf> for WScriptHash { - fn from(script: &ScriptBuf) -> WScriptHash { script.wscript_hash() } -} - -impl From<&Script> for WScriptHash { - fn from(script: &Script) -> WScriptHash { script.wscript_hash() } -} - impl AsRef