Skip to content

Commit

Permalink
Add signature_hash xfield
Browse files Browse the repository at this point in the history
  • Loading branch information
Yamaguchi committed Jun 14, 2024
1 parent d8a3ec7 commit 6087bec
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 5 deletions.
62 changes: 58 additions & 4 deletions tapyrus/src/blockdata/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,12 @@ use hashes::{Hash, HashEngine};
use super::Weight;
use crate::blockdata::script;
use crate::blockdata::transaction::Transaction;
use crate::consensus::encode::serialize_hex;
use crate::consensus::encode::{serialize_hex, Error};
use crate::consensus::{encode, serialize, Decodable, Encodable};
use crate::crypto::key::PublicKey;
use crate::crypto::schnorr::Signature;
pub use crate::hash_types::BlockHash;
use crate::hash_types::{BlockSigHash, TxMerkleNode, WitnessCommitment, WitnessMerkleNode, Wtxid};
use crate::hash_types::{BlockSigHash, TxMerkleNode, WitnessCommitment, WitnessMerkleNode, Wtxid, XFieldHash};
use crate::internal_macros::impl_consensus_encoding;
use crate::prelude::*;
use crate::{crypto, io, merkle_tree, VarInt};
Expand Down Expand Up @@ -266,6 +266,16 @@ impl XField {
XField::Unknown(_, data) => 1 + VarInt::from(data.len()).size() + data.len(),
}
}

/// Return hash of serialized XField for signing
pub fn signature_hash(&self) ->Result<XFieldHash, Error> {
match self {
XField::None => Err(Error::XFieldNone),
XField::AggregatePublicKey(_) => Ok(XFieldHash::hash(&serialize(self))),
XField::MaxBlockSize(_) => Ok(XFieldHash::hash(&serialize(self))),
XField::Unknown(i, _) => Err(Error::UnknownXField(*i)),
}
}
}

impl FromStr for XField {
Expand Down Expand Up @@ -665,7 +675,7 @@ mod tests {
use hex::{test_hex_unwrap as hex, FromHex};

use super::*;
use crate::consensus::encode::{deserialize, serialize};
use crate::consensus::encode::{deserialize, serialize, Error};
use crate::crypto::key::PublicKey;
use crate::hash_types::BlockSigHash;

Expand Down Expand Up @@ -906,10 +916,54 @@ mod tests {
fn xfield_max_block_size_panic_test() {
// larger than u32::MAX
let overflow_value:u64 = (u32::MAX as u64) + 1;
let overflow_bytes = Vec::from_hex(&format!("{:016x}", overflow_value)).unwrap();
let overflow_bytes = hex!(&format!("{:016x}", overflow_value));
assert!(deserialize::<u32>(&overflow_bytes).is_err());
assert!(XField::from_str(&format!("{:016x}", overflow_value)).is_err());
}

#[test]
fn xfield_signature_hash_test_aggpubkey() {
let xfield = XField::AggregatePublicKey(PublicKey::from_str("02459adb8a8f052be94874aef7d4c3d3ddb71fcdaa869b1d515a92d63cb29c2806").unwrap());
assert_eq!(serialize(&xfield), hex!("012102459adb8a8f052be94874aef7d4c3d3ddb71fcdaa869b1d515a92d63cb29c2806"));
assert_eq!(xfield.signature_hash().unwrap(), XFieldHash::from_str("5eb6038f90ec3b530ebed8789afd4f3f49af83fa4b00f34238c93ce0327ff9ad").unwrap());
}

#[test]
fn xfield_signature_hash_test_maxblocksize() {
let xfield = XField::MaxBlockSize(200000);
assert_eq!(serialize(&xfield), hex!("02400d0300"));
assert_eq!(xfield.signature_hash().unwrap(), XFieldHash::from_str("b2a51fb82acc2125508f323fa9567340c32257997dfd4af4e70788031d5b1915").unwrap());
}

#[test]
fn xfield_signature_hash_test_aggpubkey1() {
let xfield = XField::AggregatePublicKey(PublicKey::from_str("0376c3265e7d81839c1b2312b95697d47cc5b3ab3369a92a5af52ef1c945792f50").unwrap());
assert_eq!(serialize(&xfield), hex!("01210376c3265e7d81839c1b2312b95697d47cc5b3ab3369a92a5af52ef1c945792f50"));
assert_eq!(xfield.signature_hash().unwrap(), XFieldHash::from_str("e70d5478d63e19ab2d9aa059340785b810f82cc288e83752e726a0f9817fcc88").unwrap());
}

#[test]
fn xfield_signature_hash_test_maxblocksize1() {
let xfield = XField::MaxBlockSize(400000);
assert_eq!(serialize(&xfield), hex!("02801a0600"));
assert_eq!(xfield.signature_hash().unwrap(), XFieldHash::from_str("7b5a43d2dae273d564ec0db616efe75a31725707fc3865124e3477684f5faec0").unwrap());
}

#[test]
fn xfield_signature_hash_test_none() {
let xfield = XField::None;
let result = xfield.signature_hash();

assert!(matches!(result, Err(Error::XFieldNone)));
}

#[test]
fn xfield_signature_hash_test_unknown() {
let xfield = XField::Unknown(3, hex!("012345"));
let result = xfield.signature_hash();

assert!(matches!(result, Err(Error::UnknownXField(3))));
}
}

#[cfg(bench)]
Expand Down
10 changes: 9 additions & 1 deletion tapyrus/src/consensus/encode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,10 @@ pub enum Error {
ParseFailed(&'static str),
/// Unsupported Segwit flag.
UnsupportedSegwitFlag(u8),
/// Invalid Xfield
UnknownXField(u8),
/// XField was None which is unexpected as a hash
XFieldNone,
}

impl fmt::Display for Error {
Expand All @@ -80,6 +84,8 @@ impl fmt::Display for Error {
ParseFailed(ref s) => write!(f, "parse failed: {}", s),
UnsupportedSegwitFlag(ref swflag) =>
write!(f, "unsupported segwit version: {}", swflag),
UnknownXField(ref tp) => write!(f, "Unknown XField. XField type: {}", tp),
XFieldNone => write!(f, "XField type None cannot be hashed or signed"),
}
}
}
Expand All @@ -96,7 +102,9 @@ impl std::error::Error for Error {
| InvalidChecksum { .. }
| NonMinimalVarInt
| ParseFailed(_)
| UnsupportedSegwitFlag(_) => None,
| UnsupportedSegwitFlag(_)
| UnknownXField(_)
| XFieldNone => None ,
}
}
}
Expand Down
2 changes: 2 additions & 0 deletions tapyrus/src/consensus/serde.rs
Original file line number Diff line number Diff line change
Expand Up @@ -392,6 +392,8 @@ fn consensus_error_into_serde<E: serde::de::Error>(error: ConsensusError) -> E {
ConsensusError::ParseFailed(msg) => E::custom(msg),
ConsensusError::UnsupportedSegwitFlag(flag) =>
E::invalid_value(Unexpected::Unsigned(flag.into()), &"segwit version 1 flag"),
ConsensusError::UnknownXField(xfield_type) => E::custom(format!("unknown xfield type: {}", xfield_type)),
ConsensusError::XFieldNone => E::custom("XField type None cannot be hashed or signed"),
}
}

Expand Down
3 changes: 3 additions & 0 deletions tapyrus/src/hash_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,8 @@ mod newtypes {
pub struct BlockHash(sha256d::Hash);
/// A hash of the block for sigining.
pub struct BlockSigHash(sha256d::Hash);
/// A hash of the xfield for signing
pub struct XFieldHash(sha256d::Hash);

/// A hash of the Merkle tree branch or root for transactions
pub struct TxMerkleNode(sha256d::Hash);
Expand All @@ -89,6 +91,7 @@ mod newtypes {
impl_hashencode!(Wtxid);
impl_hashencode!(BlockHash);
impl_hashencode!(BlockSigHash);
impl_hashencode!(XFieldHash);
impl_hashencode!(TxMerkleNode);
impl_hashencode!(WitnessMerkleNode);

Expand Down

0 comments on commit 6087bec

Please sign in to comment.