From 7a52c0ecd54ee2db49b7fbf1309cf54ea912e5ca Mon Sep 17 00:00:00 2001 From: Ignotus Peverell Date: Sat, 22 Dec 2018 19:42:07 +0000 Subject: [PATCH] Revert "Verify features in one place; comment on needed Features enum type (#2191)" This reverts commit 151aa1c842835c51a251e17d12751e3651a021e5. --- core/src/core/transaction.rs | 48 +++++++++++++++++++----------------- 1 file changed, 25 insertions(+), 23 deletions(-) diff --git a/core/src/core/transaction.rs b/core/src/core/transaction.rs index 8bcc993c9..845116d90 100644 --- a/core/src/core/transaction.rs +++ b/core/src/core/transaction.rs @@ -36,14 +36,6 @@ use std::collections::HashSet; use std::sync::Arc; use std::{error, fmt}; -/// KernelFeatures needs to be a sumtype / tagged union as -/// pub enum KernelFeatures { -/// COINBASE, -/// PLAIN { fee: u64 }, -/// HEIGHTLOCKED { fee: u64, lock_height: u64 }, -/// } -/// Similarly for OutputFeatures -/// bitflags! { /// Options for a kernel's structure or use #[derive(Serialize, Deserialize)] @@ -261,6 +253,10 @@ impl TxKernel { /// as a public key and checking the signature verifies with the fee as /// message. pub fn verify(&self) -> Result<(), Error> { + if self.is_coinbase() && self.fee != 0 || !self.is_height_locked() && self.lock_height != 0 + { + return Err(Error::InvalidKernelFeatures); + } let secp = static_secp_instance(); let secp = secp.lock(); let sig = &self.excess_sig; @@ -1353,30 +1349,36 @@ impl From for OutputIdentifier { } /// Construct msg from tx fee, lock_height and kernel features. -/// msg = hash(features) for coinbase kernels -/// hash(features || fee) for plain kernels -/// hash(features || fee || lock_height) for height locked kernels +/// In testnet4 we did not include the kernel features in the message being signed. +/// In mainnet we changed this to include features and we hash (fee || lock_height || features) +/// to produce a 32 byte message to sign. +/// +/// testnet4: msg = (fee || lock_height) +/// mainnet: msg = hash(features) for coinbase kernels +/// hash(features || fee) for plain kernels +/// hash(features || fee || lock_height) for height locked kernels /// pub fn kernel_sig_msg( fee: u64, lock_height: u64, features: KernelFeatures, ) -> Result { - let features_ok = match features { - KernelFeatures::COINBASE => fee == 0 && lock_height == 0, - KernelFeatures::PLAIN => lock_height == 0, - KernelFeatures::HEIGHT_LOCKED => true, - _ => false - }; - if !features_ok { + if features.is_coinbase() && fee != 0 || !features.is_height_locked() && lock_height != 0 { return Err(Error::InvalidKernelFeatures); } - let hash = match features { - KernelFeatures::COINBASE => features.hash(), - KernelFeatures::PLAIN => (features, fee).hash(), - _ => (features, fee, lock_height).hash(), + let msg = if global::is_testnet() { + let mut bytes = [0; 32]; + BigEndian::write_u64(&mut bytes[16..24], fee); + BigEndian::write_u64(&mut bytes[24..], lock_height); + secp::Message::from_slice(&bytes)? + } else { + let hash = match features { + KernelFeatures::COINBASE => (features).hash(), + KernelFeatures::PLAIN => (features, fee).hash(), + _ => (features, fee, lock_height).hash(), + }; + secp::Message::from_slice(&hash.as_bytes())? }; - let msg = secp::Message::from_slice(&hash.as_bytes())?; Ok(msg) }