mirror of
https://github.com/mimblewimble/grin.git
synced 2025-02-01 17:01:09 +03:00
Verify features in one place; comment on needed Features enum type (#2191)
This commit is contained in:
parent
976bf1dbae
commit
151aa1c842
1 changed files with 23 additions and 25 deletions
|
@ -36,6 +36,14 @@ use std::collections::HashSet;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::{error, fmt};
|
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! {
|
bitflags! {
|
||||||
/// Options for a kernel's structure or use
|
/// Options for a kernel's structure or use
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
|
@ -253,10 +261,6 @@ impl TxKernel {
|
||||||
/// as a public key and checking the signature verifies with the fee as
|
/// as a public key and checking the signature verifies with the fee as
|
||||||
/// message.
|
/// message.
|
||||||
pub fn verify(&self) -> Result<(), Error> {
|
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 = static_secp_instance();
|
||||||
let secp = secp.lock();
|
let secp = secp.lock();
|
||||||
let sig = &self.excess_sig;
|
let sig = &self.excess_sig;
|
||||||
|
@ -1349,36 +1353,30 @@ impl From<Output> for OutputIdentifier {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Construct msg from tx fee, lock_height and kernel features.
|
/// Construct msg from tx fee, lock_height and kernel features.
|
||||||
/// In testnet4 we did not include the kernel features in the message being signed.
|
/// msg = hash(features) for coinbase kernels
|
||||||
/// In mainnet we changed this to include features and we hash (fee || lock_height || features)
|
/// hash(features || fee) for plain kernels
|
||||||
/// to produce a 32 byte message to sign.
|
/// hash(features || fee || lock_height) for height locked kernels
|
||||||
///
|
|
||||||
/// 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(
|
pub fn kernel_sig_msg(
|
||||||
fee: u64,
|
fee: u64,
|
||||||
lock_height: u64,
|
lock_height: u64,
|
||||||
features: KernelFeatures,
|
features: KernelFeatures,
|
||||||
) -> Result<secp::Message, Error> {
|
) -> Result<secp::Message, Error> {
|
||||||
if features.is_coinbase() && fee != 0 || !features.is_height_locked() && lock_height != 0 {
|
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 {
|
||||||
return Err(Error::InvalidKernelFeatures);
|
return Err(Error::InvalidKernelFeatures);
|
||||||
}
|
}
|
||||||
let msg = if global::is_testnet() {
|
let hash = match features {
|
||||||
let mut bytes = [0; 32];
|
KernelFeatures::COINBASE => features.hash(),
|
||||||
BigEndian::write_u64(&mut bytes[16..24], fee);
|
KernelFeatures::PLAIN => (features, fee).hash(),
|
||||||
BigEndian::write_u64(&mut bytes[24..], lock_height);
|
_ => (features, fee, lock_height).hash(),
|
||||||
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)
|
Ok(msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue