mirror of
https://github.com/mimblewimble/grin.git
synced 2025-02-01 08:51:08 +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
|
||||
// core. Readable is in the ser package.
|
||||
/// Serialization of a block header
|
||||
impl Writeable for BlockHeader {
|
||||
fn write(&self, writer: &mut Writer) -> Result<(), ser::Error> {
|
||||
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
|
||||
/// non-explicit, assumed to be deductible from block height (similar to
|
||||
/// 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.
|
||||
impl Readable<Block> for Block {
|
||||
fn read(reader: &mut Reader) -> Result<Block, 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);
|
||||
let header = try!(BlockHeader::read(reader));
|
||||
|
||||
// cuckoo cycle of 42 nodes
|
||||
let mut pow = [0; PROOFSIZE];
|
||||
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);
|
||||
let (input_len, output_len, proof_len) =
|
||||
ser_multiread!(reader, 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 {
|
||||
return Err(ser::Error::TooLargeReadErr("Too many inputs, outputs or proofs."
|
||||
.to_string()));
|
||||
return Err(ser::Error::TooLargeReadErr(
|
||||
"Too many inputs, outputs or proofs.".to_string()));
|
||||
}
|
||||
|
||||
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());
|
||||
|
||||
Ok(Block {
|
||||
header: 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,
|
||||
},
|
||||
header: header,
|
||||
inputs: inputs,
|
||||
outputs: outputs,
|
||||
proofs: proofs,
|
||||
|
|
|
@ -88,21 +88,21 @@ impl PowHeader {
|
|||
}
|
||||
|
||||
/// Validates the proof of work of a given header.
|
||||
pub fn verify(b: &Block, target: Target) -> bool {
|
||||
verify_size(b, target, b.header.cuckoo_len as u32)
|
||||
pub fn verify(b: &Block) -> bool {
|
||||
verify_size(b, b.header.cuckoo_len as u32)
|
||||
}
|
||||
|
||||
/// Same as default verify function but uses the much easier Cuckoo20 (mostly
|
||||
/// for tests).
|
||||
pub fn verify20(b: &Block, target: Target) -> bool {
|
||||
verify_size(b, target, 20)
|
||||
pub fn verify20(b: &Block) -> bool {
|
||||
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();
|
||||
// make sure the hash is smaller than our target before going into more
|
||||
// expensive validation
|
||||
if target < b.header.pow.to_target() {
|
||||
if b.header.target < b.header.pow.to_target() {
|
||||
return false;
|
||||
}
|
||||
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);
|
||||
b.header.pow = proof;
|
||||
b.header.nonce = nonce;
|
||||
assert!(verify20(&b, MAX_TARGET));
|
||||
assert!(verify20(&b));
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue