mirror of
https://github.com/mimblewimble/grin.git
synced 2025-02-01 17:01:09 +03:00
Implement kernel and output features as enums (#2312)
* use enums for kernel and output features * rustfmt * add test coverage around deserializing kernel features
This commit is contained in:
parent
c388af6603
commit
27801f6a93
15 changed files with 120 additions and 87 deletions
2
Cargo.lock
generated
2
Cargo.lock
generated
|
@ -771,11 +771,11 @@ dependencies = [
|
||||||
name = "grin_core"
|
name = "grin_core"
|
||||||
version = "0.5.1"
|
version = "0.5.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
|
||||||
"blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)",
|
"blake2-rfc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
"byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
"chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"croaring 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
"croaring 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"enum_primitive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"failure 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"failure 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"failure_derive 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"failure_derive 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"grin_keychain 0.5.1",
|
"grin_keychain 0.5.1",
|
||||||
|
|
|
@ -44,8 +44,8 @@ pub fn get_output(
|
||||||
// For now we can just try both (but this probably needs to be part of the api
|
// For now we can just try both (but this probably needs to be part of the api
|
||||||
// params)
|
// params)
|
||||||
let outputs = [
|
let outputs = [
|
||||||
OutputIdentifier::new(OutputFeatures::PLAIN, &commit),
|
OutputIdentifier::new(OutputFeatures::Plain, &commit),
|
||||||
OutputIdentifier::new(OutputFeatures::COINBASE, &commit),
|
OutputIdentifier::new(OutputFeatures::Coinbase, &commit),
|
||||||
];
|
];
|
||||||
|
|
||||||
for x in outputs.iter() {
|
for x in outputs.iter() {
|
||||||
|
|
|
@ -10,10 +10,10 @@ workspace = ".."
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
bitflags = "1"
|
|
||||||
blake2-rfc = "0.2"
|
blake2-rfc = "0.2"
|
||||||
byteorder = "1"
|
byteorder = "1"
|
||||||
croaring = "=0.3"
|
croaring = "=0.3"
|
||||||
|
enum_primitive = "0.1"
|
||||||
failure = "0.1"
|
failure = "0.1"
|
||||||
failure_derive = "0.1"
|
failure_derive = "0.1"
|
||||||
lazy_static = "1"
|
lazy_static = "1"
|
||||||
|
|
|
@ -28,32 +28,43 @@ use crate::util::secp;
|
||||||
use crate::util::secp::pedersen::{Commitment, RangeProof};
|
use crate::util::secp::pedersen::{Commitment, RangeProof};
|
||||||
use crate::util::static_secp_instance;
|
use crate::util::static_secp_instance;
|
||||||
use crate::util::RwLock;
|
use crate::util::RwLock;
|
||||||
|
use enum_primitive::FromPrimitive;
|
||||||
use std::cmp::max;
|
use std::cmp::max;
|
||||||
use std::cmp::Ordering;
|
use std::cmp::Ordering;
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::{error, fmt};
|
use std::{error, fmt};
|
||||||
|
|
||||||
bitflags! {
|
/// Enum of various supported kernel "features".
|
||||||
/// Options for a kernel's structure or use
|
enum_from_primitive! {
|
||||||
#[derive(Serialize, Deserialize)]
|
/// Various flavors of tx kernel.
|
||||||
pub struct KernelFeatures: u8 {
|
#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
|
||||||
/// plain kernel has fee, but no lock_height
|
#[repr(u8)]
|
||||||
const PLAIN = 0;
|
pub enum KernelFeatures {
|
||||||
/// coinbase kernel has neither fee nor lock_height (both zero)
|
/// Plain kernel (the default for Grin txs).
|
||||||
const COINBASE = 1;
|
Plain = 0,
|
||||||
/// absolute height locked kernel; has fee and lock_height
|
/// A coinbase kernel.
|
||||||
const HEIGHT_LOCKED = 2;
|
Coinbase = 1,
|
||||||
|
/// A kernel with an expicit lock height.
|
||||||
|
HeightLocked = 2,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Writeable for KernelFeatures {
|
impl Writeable for KernelFeatures {
|
||||||
fn write<W: Writer>(&self, writer: &mut W) -> Result<(), ser::Error> {
|
fn write<W: Writer>(&self, writer: &mut W) -> Result<(), ser::Error> {
|
||||||
writer.write_u8(self.bits())?;
|
writer.write_u8(*self as u8)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Readable for KernelFeatures {
|
||||||
|
fn read(reader: &mut dyn Reader) -> Result<KernelFeatures, ser::Error> {
|
||||||
|
let features =
|
||||||
|
KernelFeatures::from_u8(reader.read_u8()?).ok_or(ser::Error::CorruptedData)?;
|
||||||
|
Ok(features)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Errors thrown by Transaction validation
|
/// Errors thrown by Transaction validation
|
||||||
#[derive(Clone, Eq, Debug, PartialEq)]
|
#[derive(Clone, Eq, Debug, PartialEq)]
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
|
@ -181,10 +192,8 @@ impl Writeable for TxKernel {
|
||||||
|
|
||||||
impl Readable for TxKernel {
|
impl Readable for TxKernel {
|
||||||
fn read(reader: &mut dyn Reader) -> Result<TxKernel, ser::Error> {
|
fn read(reader: &mut dyn Reader) -> Result<TxKernel, ser::Error> {
|
||||||
let features =
|
|
||||||
KernelFeatures::from_bits(reader.read_u8()?).ok_or(ser::Error::CorruptedData)?;
|
|
||||||
Ok(TxKernel {
|
Ok(TxKernel {
|
||||||
features,
|
features: KernelFeatures::read(reader)?,
|
||||||
fee: reader.read_u64()?,
|
fee: reader.read_u64()?,
|
||||||
lock_height: reader.read_u64()?,
|
lock_height: reader.read_u64()?,
|
||||||
excess: Commitment::read(reader)?,
|
excess: Commitment::read(reader)?,
|
||||||
|
@ -205,17 +214,17 @@ impl PMMRable for TxKernel {
|
||||||
impl KernelFeatures {
|
impl KernelFeatures {
|
||||||
/// Is this a coinbase kernel?
|
/// Is this a coinbase kernel?
|
||||||
pub fn is_coinbase(&self) -> bool {
|
pub fn is_coinbase(&self) -> bool {
|
||||||
self.contains(KernelFeatures::COINBASE)
|
*self == KernelFeatures::Coinbase
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Is this a plain kernel?
|
/// Is this a plain kernel?
|
||||||
pub fn is_plain(&self) -> bool {
|
pub fn is_plain(&self) -> bool {
|
||||||
!self.is_coinbase() && !self.is_height_locked()
|
*self == KernelFeatures::Plain
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Is this a height locked kernel?
|
/// Is this a height locked kernel?
|
||||||
pub fn is_height_locked(&self) -> bool {
|
pub fn is_height_locked(&self) -> bool {
|
||||||
self.contains(KernelFeatures::HEIGHT_LOCKED)
|
*self == KernelFeatures::HeightLocked
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -278,7 +287,7 @@ impl TxKernel {
|
||||||
/// Build an empty tx kernel with zero values.
|
/// Build an empty tx kernel with zero values.
|
||||||
pub fn empty() -> TxKernel {
|
pub fn empty() -> TxKernel {
|
||||||
TxKernel {
|
TxKernel {
|
||||||
features: KernelFeatures::PLAIN,
|
features: KernelFeatures::Plain,
|
||||||
fee: 0,
|
fee: 0,
|
||||||
lock_height: 0,
|
lock_height: 0,
|
||||||
excess: Commitment::from_vec(vec![0; 33]),
|
excess: Commitment::from_vec(vec![0; 33]),
|
||||||
|
@ -1073,7 +1082,7 @@ impl ::std::hash::Hash for Input {
|
||||||
/// an Input as binary.
|
/// an Input as binary.
|
||||||
impl Writeable for Input {
|
impl Writeable for Input {
|
||||||
fn write<W: Writer>(&self, writer: &mut W) -> Result<(), ser::Error> {
|
fn write<W: Writer>(&self, writer: &mut W) -> Result<(), ser::Error> {
|
||||||
writer.write_u8(self.features.bits())?;
|
self.features.write(writer)?;
|
||||||
self.commit.write(writer)?;
|
self.commit.write(writer)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -1083,11 +1092,8 @@ impl Writeable for Input {
|
||||||
/// an Input from a binary stream.
|
/// an Input from a binary stream.
|
||||||
impl Readable for Input {
|
impl Readable for Input {
|
||||||
fn read(reader: &mut dyn Reader) -> Result<Input, ser::Error> {
|
fn read(reader: &mut dyn Reader) -> Result<Input, ser::Error> {
|
||||||
let features =
|
let features = OutputFeatures::read(reader)?;
|
||||||
OutputFeatures::from_bits(reader.read_u8()?).ok_or(ser::Error::CorruptedData)?;
|
|
||||||
|
|
||||||
let commit = Commitment::read(reader)?;
|
let commit = Commitment::read(reader)?;
|
||||||
|
|
||||||
Ok(Input::new(features, commit))
|
Ok(Input::new(features, commit))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1122,14 +1128,31 @@ impl Input {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bitflags! {
|
/// Enum of various supported kernel "features".
|
||||||
/// Options for block validation
|
enum_from_primitive! {
|
||||||
#[derive(Serialize, Deserialize)]
|
/// Various flavors of tx kernel.
|
||||||
pub struct OutputFeatures: u8 {
|
#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
|
||||||
/// No flags
|
#[repr(u8)]
|
||||||
const PLAIN = 0;
|
pub enum OutputFeatures {
|
||||||
/// Output is a coinbase output, must not be spent until maturity
|
/// Plain output (the default for Grin txs).
|
||||||
const COINBASE = 1;
|
Plain = 0,
|
||||||
|
/// A coinbase output.
|
||||||
|
Coinbase = 1,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Writeable for OutputFeatures {
|
||||||
|
fn write<W: Writer>(&self, writer: &mut W) -> Result<(), ser::Error> {
|
||||||
|
writer.write_u8(*self as u8)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Readable for OutputFeatures {
|
||||||
|
fn read(reader: &mut dyn Reader) -> Result<OutputFeatures, ser::Error> {
|
||||||
|
let features =
|
||||||
|
OutputFeatures::from_u8(reader.read_u8()?).ok_or(ser::Error::CorruptedData)?;
|
||||||
|
Ok(features)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1164,7 +1187,7 @@ impl ::std::hash::Hash for Output {
|
||||||
/// an Output as binary.
|
/// an Output as binary.
|
||||||
impl Writeable for Output {
|
impl Writeable for Output {
|
||||||
fn write<W: Writer>(&self, writer: &mut W) -> Result<(), ser::Error> {
|
fn write<W: Writer>(&self, writer: &mut W) -> Result<(), ser::Error> {
|
||||||
writer.write_u8(self.features.bits())?;
|
self.features.write(writer)?;
|
||||||
self.commit.write(writer)?;
|
self.commit.write(writer)?;
|
||||||
// The hash of an output doesn't include the range proof, which
|
// The hash of an output doesn't include the range proof, which
|
||||||
// is committed to separately
|
// is committed to separately
|
||||||
|
@ -1179,11 +1202,8 @@ impl Writeable for Output {
|
||||||
/// an Output from a binary stream.
|
/// an Output from a binary stream.
|
||||||
impl Readable for Output {
|
impl Readable for Output {
|
||||||
fn read(reader: &mut dyn Reader) -> Result<Output, ser::Error> {
|
fn read(reader: &mut dyn Reader) -> Result<Output, ser::Error> {
|
||||||
let features =
|
|
||||||
OutputFeatures::from_bits(reader.read_u8()?).ok_or(ser::Error::CorruptedData)?;
|
|
||||||
|
|
||||||
Ok(Output {
|
Ok(Output {
|
||||||
features,
|
features: OutputFeatures::read(reader)?,
|
||||||
commit: Commitment::read(reader)?,
|
commit: Commitment::read(reader)?,
|
||||||
proof: RangeProof::read(reader)?,
|
proof: RangeProof::read(reader)?,
|
||||||
})
|
})
|
||||||
|
@ -1202,12 +1222,12 @@ impl PMMRable for Output {
|
||||||
impl OutputFeatures {
|
impl OutputFeatures {
|
||||||
/// Is this a coinbase output?
|
/// Is this a coinbase output?
|
||||||
pub fn is_coinbase(&self) -> bool {
|
pub fn is_coinbase(&self) -> bool {
|
||||||
self.contains(OutputFeatures::COINBASE)
|
*self == OutputFeatures::Coinbase
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Is this a plain output?
|
/// Is this a plain output?
|
||||||
pub fn is_plain(&self) -> bool {
|
pub fn is_plain(&self) -> bool {
|
||||||
!self.contains(OutputFeatures::COINBASE)
|
*self == OutputFeatures::Plain
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1308,7 +1328,7 @@ impl OutputIdentifier {
|
||||||
pub fn to_hex(&self) -> String {
|
pub fn to_hex(&self) -> String {
|
||||||
format!(
|
format!(
|
||||||
"{:b}{}",
|
"{:b}{}",
|
||||||
self.features.bits(),
|
self.features as u8,
|
||||||
util::to_hex(self.commit.0.to_vec()),
|
util::to_hex(self.commit.0.to_vec()),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -1320,7 +1340,7 @@ impl FixedLength for OutputIdentifier {
|
||||||
|
|
||||||
impl Writeable for OutputIdentifier {
|
impl Writeable for OutputIdentifier {
|
||||||
fn write<W: Writer>(&self, writer: &mut W) -> Result<(), ser::Error> {
|
fn write<W: Writer>(&self, writer: &mut W) -> Result<(), ser::Error> {
|
||||||
writer.write_u8(self.features.bits())?;
|
self.features.write(writer)?;
|
||||||
self.commit.write(writer)?;
|
self.commit.write(writer)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -1328,10 +1348,8 @@ impl Writeable for OutputIdentifier {
|
||||||
|
|
||||||
impl Readable for OutputIdentifier {
|
impl Readable for OutputIdentifier {
|
||||||
fn read(reader: &mut dyn Reader) -> Result<OutputIdentifier, ser::Error> {
|
fn read(reader: &mut dyn Reader) -> Result<OutputIdentifier, ser::Error> {
|
||||||
let features =
|
|
||||||
OutputFeatures::from_bits(reader.read_u8()?).ok_or(ser::Error::CorruptedData)?;
|
|
||||||
Ok(OutputIdentifier {
|
Ok(OutputIdentifier {
|
||||||
features,
|
features: OutputFeatures::read(reader)?,
|
||||||
commit: Commitment::read(reader)?,
|
commit: Commitment::read(reader)?,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -1358,18 +1376,17 @@ pub fn kernel_sig_msg(
|
||||||
features: KernelFeatures,
|
features: KernelFeatures,
|
||||||
) -> Result<secp::Message, Error> {
|
) -> Result<secp::Message, Error> {
|
||||||
let valid_features = match features {
|
let valid_features = match features {
|
||||||
KernelFeatures::COINBASE => fee == 0 && lock_height == 0,
|
KernelFeatures::Coinbase => fee == 0 && lock_height == 0,
|
||||||
KernelFeatures::PLAIN => lock_height == 0,
|
KernelFeatures::Plain => lock_height == 0,
|
||||||
KernelFeatures::HEIGHT_LOCKED => true,
|
KernelFeatures::HeightLocked => true,
|
||||||
_ => false,
|
|
||||||
};
|
};
|
||||||
if !valid_features {
|
if !valid_features {
|
||||||
return Err(Error::InvalidKernelFeatures);
|
return Err(Error::InvalidKernelFeatures);
|
||||||
}
|
}
|
||||||
let hash = match features {
|
let hash = match features {
|
||||||
KernelFeatures::COINBASE => (features).hash(),
|
KernelFeatures::Coinbase => (features).hash(),
|
||||||
KernelFeatures::PLAIN => (features, fee).hash(),
|
KernelFeatures::Plain => (features, fee).hash(),
|
||||||
_ => (features, fee, lock_height).hash(),
|
KernelFeatures::HeightLocked => (features, fee, lock_height).hash(),
|
||||||
};
|
};
|
||||||
Ok(secp::Message::from_slice(&hash.as_bytes())?)
|
Ok(secp::Message::from_slice(&hash.as_bytes())?)
|
||||||
}
|
}
|
||||||
|
@ -1377,9 +1394,9 @@ pub fn kernel_sig_msg(
|
||||||
/// kernel features as determined by lock height
|
/// kernel features as determined by lock height
|
||||||
pub fn kernel_features(lock_height: u64) -> KernelFeatures {
|
pub fn kernel_features(lock_height: u64) -> KernelFeatures {
|
||||||
if lock_height > 0 {
|
if lock_height > 0 {
|
||||||
KernelFeatures::HEIGHT_LOCKED
|
KernelFeatures::HeightLocked
|
||||||
} else {
|
} else {
|
||||||
KernelFeatures::PLAIN
|
KernelFeatures::Plain
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1401,7 +1418,7 @@ mod test {
|
||||||
let sig = secp::Signature::from_raw_data(&[0; 64]).unwrap();
|
let sig = secp::Signature::from_raw_data(&[0; 64]).unwrap();
|
||||||
|
|
||||||
let kernel = TxKernel {
|
let kernel = TxKernel {
|
||||||
features: KernelFeatures::PLAIN,
|
features: KernelFeatures::Plain,
|
||||||
lock_height: 0,
|
lock_height: 0,
|
||||||
excess: commit,
|
excess: commit,
|
||||||
excess_sig: sig.clone(),
|
excess_sig: sig.clone(),
|
||||||
|
@ -1411,7 +1428,7 @@ mod test {
|
||||||
let mut vec = vec![];
|
let mut vec = vec![];
|
||||||
ser::serialize(&mut vec, &kernel).expect("serialized failed");
|
ser::serialize(&mut vec, &kernel).expect("serialized failed");
|
||||||
let kernel2: TxKernel = ser::deserialize(&mut &vec[..]).unwrap();
|
let kernel2: TxKernel = ser::deserialize(&mut &vec[..]).unwrap();
|
||||||
assert_eq!(kernel2.features, KernelFeatures::PLAIN);
|
assert_eq!(kernel2.features, KernelFeatures::Plain);
|
||||||
assert_eq!(kernel2.lock_height, 0);
|
assert_eq!(kernel2.lock_height, 0);
|
||||||
assert_eq!(kernel2.excess, commit);
|
assert_eq!(kernel2.excess, commit);
|
||||||
assert_eq!(kernel2.excess_sig, sig.clone());
|
assert_eq!(kernel2.excess_sig, sig.clone());
|
||||||
|
@ -1419,7 +1436,7 @@ mod test {
|
||||||
|
|
||||||
// now check a kernel with lock_height serialize/deserialize correctly
|
// now check a kernel with lock_height serialize/deserialize correctly
|
||||||
let kernel = TxKernel {
|
let kernel = TxKernel {
|
||||||
features: KernelFeatures::HEIGHT_LOCKED,
|
features: KernelFeatures::HeightLocked,
|
||||||
lock_height: 100,
|
lock_height: 100,
|
||||||
excess: commit,
|
excess: commit,
|
||||||
excess_sig: sig.clone(),
|
excess_sig: sig.clone(),
|
||||||
|
@ -1429,7 +1446,7 @@ mod test {
|
||||||
let mut vec = vec![];
|
let mut vec = vec![];
|
||||||
ser::serialize(&mut vec, &kernel).expect("serialized failed");
|
ser::serialize(&mut vec, &kernel).expect("serialized failed");
|
||||||
let kernel2: TxKernel = ser::deserialize(&mut &vec[..]).unwrap();
|
let kernel2: TxKernel = ser::deserialize(&mut &vec[..]).unwrap();
|
||||||
assert_eq!(kernel2.features, KernelFeatures::HEIGHT_LOCKED);
|
assert_eq!(kernel2.features, KernelFeatures::HeightLocked);
|
||||||
assert_eq!(kernel2.lock_height, 100);
|
assert_eq!(kernel2.lock_height, 100);
|
||||||
assert_eq!(kernel2.excess, commit);
|
assert_eq!(kernel2.excess, commit);
|
||||||
assert_eq!(kernel2.excess_sig, sig.clone());
|
assert_eq!(kernel2.excess_sig, sig.clone());
|
||||||
|
@ -1456,7 +1473,7 @@ mod test {
|
||||||
let commit = keychain.commit(5, &key_id).unwrap();
|
let commit = keychain.commit(5, &key_id).unwrap();
|
||||||
|
|
||||||
let input = Input {
|
let input = Input {
|
||||||
features: OutputFeatures::PLAIN,
|
features: OutputFeatures::Plain,
|
||||||
commit: commit,
|
commit: commit,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1472,11 +1489,27 @@ mod test {
|
||||||
// now generate the short_id for a *very* similar output (single feature flag
|
// now generate the short_id for a *very* similar output (single feature flag
|
||||||
// different) and check it generates a different short_id
|
// different) and check it generates a different short_id
|
||||||
let input = Input {
|
let input = Input {
|
||||||
features: OutputFeatures::COINBASE,
|
features: OutputFeatures::Coinbase,
|
||||||
commit: commit,
|
commit: commit,
|
||||||
};
|
};
|
||||||
|
|
||||||
let short_id = input.short_id(&block_hash, nonce);
|
let short_id = input.short_id(&block_hash, nonce);
|
||||||
assert_eq!(short_id, ShortId::from_hex("3f0377c624e9").unwrap());
|
assert_eq!(short_id, ShortId::from_hex("3f0377c624e9").unwrap());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn kernel_features_serialization() {
|
||||||
|
let features = KernelFeatures::from_u8(0).unwrap();
|
||||||
|
assert_eq!(features, KernelFeatures::Plain);
|
||||||
|
|
||||||
|
let features = KernelFeatures::from_u8(1).unwrap();
|
||||||
|
assert_eq!(features, KernelFeatures::Coinbase);
|
||||||
|
|
||||||
|
let features = KernelFeatures::from_u8(2).unwrap();
|
||||||
|
assert_eq!(features, KernelFeatures::HeightLocked);
|
||||||
|
|
||||||
|
// Verify we cannot deserialize an unexpected kernel feature
|
||||||
|
let features = KernelFeatures::from_u8(3);
|
||||||
|
assert_eq!(features, None);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -93,7 +93,7 @@ pub fn genesis_floo() -> core::Block {
|
||||||
..Default::default()
|
..Default::default()
|
||||||
});
|
});
|
||||||
let kernel = core::TxKernel {
|
let kernel = core::TxKernel {
|
||||||
features: core::KernelFeatures::COINBASE,
|
features: core::KernelFeatures::Coinbase,
|
||||||
fee: 0,
|
fee: 0,
|
||||||
lock_height: 0,
|
lock_height: 0,
|
||||||
excess: Commitment::from_vec(
|
excess: Commitment::from_vec(
|
||||||
|
@ -111,7 +111,7 @@ pub fn genesis_floo() -> core::Block {
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
};
|
};
|
||||||
let output = core::Output {
|
let output = core::Output {
|
||||||
features: core::OutputFeatures::COINBASE,
|
features: core::OutputFeatures::Coinbase,
|
||||||
commit: Commitment::from_vec(
|
commit: Commitment::from_vec(
|
||||||
util::from_hex(
|
util::from_hex(
|
||||||
"08c12007af16d1ee55fffe92cef808c77e318dae70c3bc70cb6361f49d517f1b68".to_string(),
|
"08c12007af16d1ee55fffe92cef808c77e318dae70c3bc70cb6361f49d517f1b68".to_string(),
|
||||||
|
@ -190,14 +190,14 @@ pub fn genesis_main() -> core::Block {
|
||||||
..Default::default()
|
..Default::default()
|
||||||
});
|
});
|
||||||
let kernel = core::TxKernel {
|
let kernel = core::TxKernel {
|
||||||
features: core::KernelFeatures::COINBASE,
|
features: core::KernelFeatures::Coinbase,
|
||||||
fee: 0,
|
fee: 0,
|
||||||
lock_height: 0,
|
lock_height: 0,
|
||||||
excess: Commitment::from_vec(vec![]), // REPLACE
|
excess: Commitment::from_vec(vec![]), // REPLACE
|
||||||
excess_sig: Signature::from_raw_data(&[0; 64]).unwrap(), //REPLACE
|
excess_sig: Signature::from_raw_data(&[0; 64]).unwrap(), //REPLACE
|
||||||
};
|
};
|
||||||
let output = core::Output {
|
let output = core::Output {
|
||||||
features: core::OutputFeatures::COINBASE,
|
features: core::OutputFeatures::Coinbase,
|
||||||
commit: Commitment::from_vec(vec![]), // REPLACE
|
commit: Commitment::from_vec(vec![]), // REPLACE
|
||||||
proof: RangeProof {
|
proof: RangeProof {
|
||||||
plen: SINGLE_BULLET_PROOF_SIZE,
|
plen: SINGLE_BULLET_PROOF_SIZE,
|
||||||
|
|
|
@ -21,9 +21,9 @@
|
||||||
#![deny(unused_mut)]
|
#![deny(unused_mut)]
|
||||||
#![warn(missing_docs)]
|
#![warn(missing_docs)]
|
||||||
|
|
||||||
#[macro_use]
|
|
||||||
extern crate bitflags;
|
|
||||||
use blake2_rfc as blake2;
|
use blake2_rfc as blake2;
|
||||||
|
#[macro_use]
|
||||||
|
extern crate enum_primitive;
|
||||||
use grin_keychain as keychain;
|
use grin_keychain as keychain;
|
||||||
use grin_util as util;
|
use grin_util as util;
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
|
|
|
@ -241,14 +241,14 @@ pub fn verify_partial_sig(
|
||||||
/// let commit = keychain.commit(value, &key_id).unwrap();
|
/// let commit = keychain.commit(value, &key_id).unwrap();
|
||||||
/// let rproof = proof::create(&keychain, value, &key_id, commit, None).unwrap();
|
/// let rproof = proof::create(&keychain, value, &key_id, commit, None).unwrap();
|
||||||
/// let output = Output {
|
/// let output = Output {
|
||||||
/// features: OutputFeatures::COINBASE,
|
/// features: OutputFeatures::Coinbase,
|
||||||
/// commit: commit,
|
/// commit: commit,
|
||||||
/// proof: rproof,
|
/// proof: rproof,
|
||||||
/// };
|
/// };
|
||||||
/// let height = 20;
|
/// let height = 20;
|
||||||
/// let over_commit = secp.commit_value(reward(fees)).unwrap();
|
/// let over_commit = secp.commit_value(reward(fees)).unwrap();
|
||||||
/// let out_commit = output.commitment();
|
/// let out_commit = output.commitment();
|
||||||
/// let msg = kernel_sig_msg(0, height, KernelFeatures::HEIGHT_LOCKED).unwrap();
|
/// let msg = kernel_sig_msg(0, height, KernelFeatures::HeightLocked).unwrap();
|
||||||
/// let excess = secp.commit_sum(vec![out_commit], vec![over_commit]).unwrap();
|
/// let excess = secp.commit_sum(vec![out_commit], vec![over_commit]).unwrap();
|
||||||
/// let pubkey = excess.to_pubkey(&secp).unwrap();
|
/// let pubkey = excess.to_pubkey(&secp).unwrap();
|
||||||
/// let sig = aggsig::sign_from_key_id(&secp, &keychain, &msg, value, &key_id, Some(&pubkey)).unwrap();
|
/// let sig = aggsig::sign_from_key_id(&secp, &keychain, &msg, value, &key_id, Some(&pubkey)).unwrap();
|
||||||
|
@ -306,14 +306,14 @@ where
|
||||||
/// let commit = keychain.commit(value, &key_id).unwrap();
|
/// let commit = keychain.commit(value, &key_id).unwrap();
|
||||||
/// let rproof = proof::create(&keychain, value, &key_id, commit, None).unwrap();
|
/// let rproof = proof::create(&keychain, value, &key_id, commit, None).unwrap();
|
||||||
/// let output = Output {
|
/// let output = Output {
|
||||||
/// features: OutputFeatures::COINBASE,
|
/// features: OutputFeatures::Coinbase,
|
||||||
/// commit: commit,
|
/// commit: commit,
|
||||||
/// proof: rproof,
|
/// proof: rproof,
|
||||||
/// };
|
/// };
|
||||||
/// let height = 20;
|
/// let height = 20;
|
||||||
/// let over_commit = secp.commit_value(reward(fees)).unwrap();
|
/// let over_commit = secp.commit_value(reward(fees)).unwrap();
|
||||||
/// let out_commit = output.commitment();
|
/// let out_commit = output.commitment();
|
||||||
/// let msg = kernel_sig_msg(0, height, KernelFeatures::HEIGHT_LOCKED).unwrap();
|
/// let msg = kernel_sig_msg(0, height, KernelFeatures::HeightLocked).unwrap();
|
||||||
/// let excess = secp.commit_sum(vec![out_commit], vec![over_commit]).unwrap();
|
/// let excess = secp.commit_sum(vec![out_commit], vec![over_commit]).unwrap();
|
||||||
/// let pubkey = excess.to_pubkey(&secp).unwrap();
|
/// let pubkey = excess.to_pubkey(&secp).unwrap();
|
||||||
/// let sig = aggsig::sign_from_key_id(&secp, &keychain, &msg, value, &key_id, Some(&pubkey)).unwrap();
|
/// let sig = aggsig::sign_from_key_id(&secp, &keychain, &msg, value, &key_id, Some(&pubkey)).unwrap();
|
||||||
|
|
|
@ -73,7 +73,7 @@ where
|
||||||
"Building input (spending regular output): {}, {}",
|
"Building input (spending regular output): {}, {}",
|
||||||
value, key_id
|
value, key_id
|
||||||
);
|
);
|
||||||
build_input(value, OutputFeatures::PLAIN, key_id)
|
build_input(value, OutputFeatures::Plain, key_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Adds a coinbase input spending a coinbase output.
|
/// Adds a coinbase input spending a coinbase output.
|
||||||
|
@ -82,7 +82,7 @@ where
|
||||||
K: Keychain,
|
K: Keychain,
|
||||||
{
|
{
|
||||||
debug!("Building input (spending coinbase): {}, {}", value, key_id);
|
debug!("Building input (spending coinbase): {}, {}", value, key_id);
|
||||||
build_input(value, OutputFeatures::COINBASE, key_id)
|
build_input(value, OutputFeatures::Coinbase, key_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Adds an output with the provided value and key identifier from the
|
/// Adds an output with the provided value and key identifier from the
|
||||||
|
@ -101,7 +101,7 @@ where
|
||||||
|
|
||||||
(
|
(
|
||||||
tx.with_output(Output {
|
tx.with_output(Output {
|
||||||
features: OutputFeatures::PLAIN,
|
features: OutputFeatures::Plain,
|
||||||
commit: commit,
|
commit: commit,
|
||||||
proof: rproof,
|
proof: rproof,
|
||||||
}),
|
}),
|
||||||
|
|
|
@ -35,7 +35,7 @@ where
|
||||||
let rproof = proof::create(keychain, value, key_id, commit, None)?;
|
let rproof = proof::create(keychain, value, key_id, commit, None)?;
|
||||||
|
|
||||||
let output = Output {
|
let output = Output {
|
||||||
features: OutputFeatures::COINBASE,
|
features: OutputFeatures::Coinbase,
|
||||||
commit: commit,
|
commit: commit,
|
||||||
proof: rproof,
|
proof: rproof,
|
||||||
};
|
};
|
||||||
|
@ -49,11 +49,11 @@ where
|
||||||
|
|
||||||
// NOTE: Remember we sign the fee *and* the lock_height.
|
// NOTE: Remember we sign the fee *and* the lock_height.
|
||||||
// For a coinbase output the fee is 0 and the lock_height is 0
|
// For a coinbase output the fee is 0 and the lock_height is 0
|
||||||
let msg = kernel_sig_msg(0, 0, KernelFeatures::COINBASE)?;
|
let msg = kernel_sig_msg(0, 0, KernelFeatures::Coinbase)?;
|
||||||
let sig = aggsig::sign_from_key_id(&secp, keychain, &msg, value, &key_id, Some(&pubkey))?;
|
let sig = aggsig::sign_from_key_id(&secp, keychain, &msg, value, &key_id, Some(&pubkey))?;
|
||||||
|
|
||||||
let proof = TxKernel {
|
let proof = TxKernel {
|
||||||
features: KernelFeatures::COINBASE,
|
features: KernelFeatures::Coinbase,
|
||||||
excess: excess,
|
excess: excess,
|
||||||
excess_sig: sig,
|
excess_sig: sig,
|
||||||
fee: 0,
|
fee: 0,
|
||||||
|
|
|
@ -162,7 +162,7 @@ fn remove_coinbase_output_flag() {
|
||||||
let mut b = new_block(vec![], &keychain, &prev, &key_id);
|
let mut b = new_block(vec![], &keychain, &prev, &key_id);
|
||||||
|
|
||||||
assert!(b.outputs()[0].is_coinbase());
|
assert!(b.outputs()[0].is_coinbase());
|
||||||
b.outputs_mut()[0].features = OutputFeatures::PLAIN;
|
b.outputs_mut()[0].features = OutputFeatures::Plain;
|
||||||
|
|
||||||
assert_eq!(b.verify_coinbase(), Err(Error::CoinbaseSumMismatch));
|
assert_eq!(b.verify_coinbase(), Err(Error::CoinbaseSumMismatch));
|
||||||
assert!(b
|
assert!(b
|
||||||
|
@ -184,7 +184,7 @@ fn remove_coinbase_kernel_flag() {
|
||||||
let mut b = new_block(vec![], &keychain, &prev, &key_id);
|
let mut b = new_block(vec![], &keychain, &prev, &key_id);
|
||||||
|
|
||||||
assert!(b.kernels()[0].is_coinbase());
|
assert!(b.kernels()[0].is_coinbase());
|
||||||
b.kernels_mut()[0].features = KernelFeatures::PLAIN;
|
b.kernels_mut()[0].features = KernelFeatures::Plain;
|
||||||
|
|
||||||
// Flipping the coinbase flag results in kernels not summing correctly.
|
// Flipping the coinbase flag results in kernels not summing correctly.
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
|
|
@ -122,7 +122,7 @@ fn build_tx_kernel() {
|
||||||
let kern = &tx.kernels()[0];
|
let kern = &tx.kernels()[0];
|
||||||
kern.verify().unwrap();
|
kern.verify().unwrap();
|
||||||
|
|
||||||
assert_eq!(kern.features, KernelFeatures::PLAIN);
|
assert_eq!(kern.features, KernelFeatures::Plain);
|
||||||
assert_eq!(kern.fee, tx.fee());
|
assert_eq!(kern.fee, tx.fee());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -31,7 +31,7 @@ fn test_output_ser_deser() {
|
||||||
let proof = proof::create(&keychain, 5, &key_id, commit, None).unwrap();
|
let proof = proof::create(&keychain, 5, &key_id, commit, None).unwrap();
|
||||||
|
|
||||||
let out = Output {
|
let out = Output {
|
||||||
features: OutputFeatures::PLAIN,
|
features: OutputFeatures::Plain,
|
||||||
commit: commit,
|
commit: commit,
|
||||||
proof: proof,
|
proof: proof,
|
||||||
};
|
};
|
||||||
|
@ -40,7 +40,7 @@ fn test_output_ser_deser() {
|
||||||
ser::serialize(&mut vec, &out).expect("serialized failed");
|
ser::serialize(&mut vec, &out).expect("serialized failed");
|
||||||
let dout: Output = ser::deserialize(&mut &vec[..]).unwrap();
|
let dout: Output = ser::deserialize(&mut &vec[..]).unwrap();
|
||||||
|
|
||||||
assert_eq!(dout.features, OutputFeatures::PLAIN);
|
assert_eq!(dout.features, OutputFeatures::Plain);
|
||||||
assert_eq!(dout.commit, out.commit);
|
assert_eq!(dout.commit, out.commit);
|
||||||
assert_eq!(dout.proof, out.proof);
|
assert_eq!(dout.proof, out.proof);
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,7 +38,7 @@ fn test_verifier_cache_rangeproofs() {
|
||||||
let proof = proof::create(&keychain, 5, &key_id, commit, None).unwrap();
|
let proof = proof::create(&keychain, 5, &key_id, commit, None).unwrap();
|
||||||
|
|
||||||
let out = Output {
|
let out = Output {
|
||||||
features: OutputFeatures::PLAIN,
|
features: OutputFeatures::Plain,
|
||||||
commit: commit,
|
commit: commit,
|
||||||
proof: proof,
|
proof: proof,
|
||||||
};
|
};
|
||||||
|
|
|
@ -45,8 +45,8 @@ pub use self::{testclient::LocalWalletClient, testclient::WalletProxy};
|
||||||
/// Get an output from the chain locally and present it back as an API output
|
/// Get an output from the chain locally and present it back as an API output
|
||||||
fn get_output_local(chain: &chain::Chain, commit: &pedersen::Commitment) -> Option<api::Output> {
|
fn get_output_local(chain: &chain::Chain, commit: &pedersen::Commitment) -> Option<api::Output> {
|
||||||
let outputs = [
|
let outputs = [
|
||||||
OutputIdentifier::new(OutputFeatures::PLAIN, commit),
|
OutputIdentifier::new(OutputFeatures::Plain, commit),
|
||||||
OutputIdentifier::new(OutputFeatures::COINBASE, commit),
|
OutputIdentifier::new(OutputFeatures::Coinbase, commit),
|
||||||
];
|
];
|
||||||
|
|
||||||
for x in outputs.iter() {
|
for x in outputs.iter() {
|
||||||
|
|
|
@ -26,7 +26,7 @@ use grin_wallet as wallet;
|
||||||
use rand::thread_rng;
|
use rand::thread_rng;
|
||||||
|
|
||||||
fn kernel_sig_msg() -> secp::Message {
|
fn kernel_sig_msg() -> secp::Message {
|
||||||
transaction::kernel_sig_msg(0, 0, transaction::KernelFeatures::PLAIN).unwrap()
|
transaction::kernel_sig_msg(0, 0, transaction::KernelFeatures::Plain).unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
Loading…
Reference in a new issue