mirror of
https://github.com/mimblewimble/grin.git
synced 2025-02-01 17:01:09 +03:00
Block header needs its own deserialization. Fixed pow verify to use the block target.
This commit is contained in:
parent
1d2b23a4a5
commit
ca26f0c3f7
2 changed files with 45 additions and 38 deletions
|
@ -64,8 +64,7 @@ impl Default for BlockHeader {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Only Writeable implementation is required for hashing, which is part of
|
/// Serialization of a block header
|
||||||
// core. Readable is in the ser package.
|
|
||||||
impl Writeable for BlockHeader {
|
impl Writeable for BlockHeader {
|
||||||
fn write(&self, writer: &mut Writer) -> Result<(), ser::Error> {
|
fn write(&self, writer: &mut Writer) -> Result<(), ser::Error> {
|
||||||
ser_multiwrite!(writer,
|
ser_multiwrite!(writer,
|
||||||
|
@ -88,6 +87,37 @@ impl Writeable for BlockHeader {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Deserialization of a block header
|
||||||
|
impl Readable<BlockHeader> for BlockHeader {
|
||||||
|
fn read(reader: &mut Reader) -> Result<BlockHeader, ser::Error> {
|
||||||
|
let (height, previous, timestamp, cuckoo_len) =
|
||||||
|
ser_multiread!(reader, read_u64, read_32_bytes, read_i64, read_u8);
|
||||||
|
let target = try!(Target::read(reader));
|
||||||
|
let (utxo_merkle, tx_merkle, nonce) =
|
||||||
|
ser_multiread!(reader, read_32_bytes, read_32_bytes, read_u64);
|
||||||
|
|
||||||
|
// cuckoo cycle of 42 nodes
|
||||||
|
let mut pow = [0; PROOFSIZE];
|
||||||
|
for n in 0..PROOFSIZE {
|
||||||
|
pow[n] = try!(reader.read_u32());
|
||||||
|
}
|
||||||
|
Ok(BlockHeader {
|
||||||
|
height: height,
|
||||||
|
previous: Hash::from_vec(previous),
|
||||||
|
timestamp: time::at_utc(time::Timespec {
|
||||||
|
sec: timestamp,
|
||||||
|
nsec: 0,
|
||||||
|
}),
|
||||||
|
cuckoo_len: cuckoo_len,
|
||||||
|
target: target,
|
||||||
|
utxo_merkle: Hash::from_vec(utxo_merkle),
|
||||||
|
tx_merkle: Hash::from_vec(tx_merkle),
|
||||||
|
pow: Proof(pow),
|
||||||
|
nonce: nonce,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// A block as expressed in the MimbleWimble protocol. The reward is
|
/// A block as expressed in the MimbleWimble protocol. The reward is
|
||||||
/// non-explicit, assumed to be deductible from block height (similar to
|
/// non-explicit, assumed to be deductible from block height (similar to
|
||||||
/// bitcoin's schedule) and expressed as a global transaction fee (added v.H),
|
/// bitcoin's schedule) and expressed as a global transaction fee (added v.H),
|
||||||
|
@ -127,24 +157,14 @@ impl Writeable for Block {
|
||||||
/// from a binary stream.
|
/// from a binary stream.
|
||||||
impl Readable<Block> for Block {
|
impl Readable<Block> for Block {
|
||||||
fn read(reader: &mut Reader) -> Result<Block, ser::Error> {
|
fn read(reader: &mut Reader) -> Result<Block, ser::Error> {
|
||||||
let (height, previous, timestamp, cuckoo_len) =
|
let header = try!(BlockHeader::read(reader));
|
||||||
ser_multiread!(reader, read_u64, read_32_bytes, read_i64, read_u8);
|
|
||||||
let target = try!(Target::read(reader));
|
|
||||||
let (utxo_merkle, tx_merkle, nonce) =
|
|
||||||
ser_multiread!(reader, read_32_bytes, read_32_bytes, read_u64);
|
|
||||||
|
|
||||||
// cuckoo cycle of 42 nodes
|
let (input_len, output_len, proof_len) =
|
||||||
let mut pow = [0; PROOFSIZE];
|
ser_multiread!(reader, read_u64, read_u64, read_u64);
|
||||||
for n in 0..PROOFSIZE {
|
|
||||||
pow[n] = try!(reader.read_u32());
|
|
||||||
}
|
|
||||||
|
|
||||||
let (td, input_len, output_len, proof_len) =
|
|
||||||
ser_multiread!(reader, read_u64, read_u64, read_u64, read_u64);
|
|
||||||
|
|
||||||
if input_len > MAX_IN_OUT_LEN || output_len > MAX_IN_OUT_LEN || proof_len > MAX_IN_OUT_LEN {
|
if input_len > MAX_IN_OUT_LEN || output_len > MAX_IN_OUT_LEN || proof_len > MAX_IN_OUT_LEN {
|
||||||
return Err(ser::Error::TooLargeReadErr("Too many inputs, outputs or proofs."
|
return Err(ser::Error::TooLargeReadErr(
|
||||||
.to_string()));
|
"Too many inputs, outputs or proofs.".to_string()));
|
||||||
}
|
}
|
||||||
|
|
||||||
let inputs = try!((0..input_len).map(|_| Input::read(reader)).collect());
|
let inputs = try!((0..input_len).map(|_| Input::read(reader)).collect());
|
||||||
|
@ -152,20 +172,7 @@ impl Readable<Block> for Block {
|
||||||
let proofs = try!((0..proof_len).map(|_| TxProof::read(reader)).collect());
|
let proofs = try!((0..proof_len).map(|_| TxProof::read(reader)).collect());
|
||||||
|
|
||||||
Ok(Block {
|
Ok(Block {
|
||||||
header: BlockHeader {
|
header: header,
|
||||||
height: height,
|
|
||||||
previous: Hash::from_vec(previous),
|
|
||||||
timestamp: time::at_utc(time::Timespec {
|
|
||||||
sec: timestamp,
|
|
||||||
nsec: 0,
|
|
||||||
}),
|
|
||||||
cuckoo_len: cuckoo_len,
|
|
||||||
target: target,
|
|
||||||
utxo_merkle: Hash::from_vec(utxo_merkle),
|
|
||||||
tx_merkle: Hash::from_vec(tx_merkle),
|
|
||||||
pow: Proof(pow),
|
|
||||||
nonce: nonce,
|
|
||||||
},
|
|
||||||
inputs: inputs,
|
inputs: inputs,
|
||||||
outputs: outputs,
|
outputs: outputs,
|
||||||
proofs: proofs,
|
proofs: proofs,
|
||||||
|
|
|
@ -88,21 +88,21 @@ impl PowHeader {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Validates the proof of work of a given header.
|
/// Validates the proof of work of a given header.
|
||||||
pub fn verify(b: &Block, target: Target) -> bool {
|
pub fn verify(b: &Block) -> bool {
|
||||||
verify_size(b, target, b.header.cuckoo_len as u32)
|
verify_size(b, b.header.cuckoo_len as u32)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Same as default verify function but uses the much easier Cuckoo20 (mostly
|
/// Same as default verify function but uses the much easier Cuckoo20 (mostly
|
||||||
/// for tests).
|
/// for tests).
|
||||||
pub fn verify20(b: &Block, target: Target) -> bool {
|
pub fn verify20(b: &Block) -> bool {
|
||||||
verify_size(b, target, 20)
|
verify_size(b, 20)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn verify_size(b: &Block, target: Target, sizeshift: u32) -> bool {
|
pub fn verify_size(b: &Block, sizeshift: u32) -> bool {
|
||||||
let hash = PowHeader::from_block(b).hash();
|
let hash = PowHeader::from_block(b).hash();
|
||||||
// make sure the hash is smaller than our target before going into more
|
// make sure the hash is smaller than our target before going into more
|
||||||
// expensive validation
|
// expensive validation
|
||||||
if target < b.header.pow.to_target() {
|
if b.header.target < b.header.pow.to_target() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
Cuckoo::new(hash.to_slice(), sizeshift).verify(b.header.pow, EASINESS as u64)
|
Cuckoo::new(hash.to_slice(), sizeshift).verify(b.header.pow, EASINESS as u64)
|
||||||
|
@ -165,6 +165,6 @@ mod test {
|
||||||
assert!(proof.to_target() < MAX_TARGET);
|
assert!(proof.to_target() < MAX_TARGET);
|
||||||
b.header.pow = proof;
|
b.header.pow = proof;
|
||||||
b.header.nonce = nonce;
|
b.header.nonce = nonce;
|
||||||
assert!(verify20(&b, MAX_TARGET));
|
assert!(verify20(&b));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue