Render byte slices as hex more often in `Debug` impls
This is more generally useful for debugging purposes than the default `Debug` impl for `&[u8]`. We also provide an alternate `Debug` impl for `legacy::Script` that parses and renders known opcodes. Note that we only parse a subset of the full opcode set.
This commit is contained in:
parent
57a3914e3a
commit
c8e2d81f58
|
@ -19,6 +19,8 @@
|
|||
#![deny(unsafe_code)]
|
||||
// TODO: #![deny(missing_docs)]
|
||||
|
||||
use core::fmt::{self, Write};
|
||||
|
||||
#[cfg(feature = "alloc")]
|
||||
extern crate alloc;
|
||||
#[cfg(feature = "alloc")]
|
||||
|
@ -72,9 +74,28 @@ impl AsRef<[u8]> for OutgoingCipherKey {
|
|||
/// Newtype representing the byte encoding of an [`EphemeralPublicKey`].
|
||||
///
|
||||
/// [`EphemeralPublicKey`]: Domain::EphemeralPublicKey
|
||||
#[derive(Clone, Debug)]
|
||||
#[derive(Clone)]
|
||||
pub struct EphemeralKeyBytes(pub [u8; 32]);
|
||||
|
||||
impl fmt::Debug for EphemeralKeyBytes {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
struct HexFmt<'b>(&'b [u8]);
|
||||
impl<'b> fmt::Debug for HexFmt<'b> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.write_char('"')?;
|
||||
for b in self.0 {
|
||||
f.write_fmt(format_args!("{:02x}", b))?;
|
||||
}
|
||||
f.write_char('"')
|
||||
}
|
||||
}
|
||||
|
||||
f.debug_tuple("EphemeralKeyBytes")
|
||||
.field(&HexFmt(&self.0))
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<[u8]> for EphemeralKeyBytes {
|
||||
fn as_ref(&self) -> &[u8] {
|
||||
&self.0
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
//! Support for legacy transparent addresses and scripts.
|
||||
|
||||
use byteorder::{ReadBytesExt, WriteBytesExt};
|
||||
|
||||
use std::fmt;
|
||||
use std::io::{self, Read, Write};
|
||||
use std::ops::Shl;
|
||||
|
||||
|
@ -10,6 +12,7 @@ use zcash_encoding::Vector;
|
|||
pub mod keys;
|
||||
|
||||
/// Minimal subset of script opcodes.
|
||||
#[derive(Debug)]
|
||||
enum OpCode {
|
||||
// push value
|
||||
PushData1 = 0x4c,
|
||||
|
@ -28,10 +31,64 @@ enum OpCode {
|
|||
CheckSig = 0xac,
|
||||
}
|
||||
|
||||
impl OpCode {
|
||||
fn parse(b: u8) -> Option<Self> {
|
||||
match b {
|
||||
0x4c => Some(OpCode::PushData1),
|
||||
0x4d => Some(OpCode::PushData2),
|
||||
0x4e => Some(OpCode::PushData4),
|
||||
0x76 => Some(OpCode::Dup),
|
||||
0x87 => Some(OpCode::Equal),
|
||||
0x88 => Some(OpCode::EqualVerify),
|
||||
0xa9 => Some(OpCode::Hash160),
|
||||
0xac => Some(OpCode::CheckSig),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A serialized script, used inside transparent inputs and outputs of a transaction.
|
||||
#[derive(Clone, Debug, Default, PartialEq, Eq)]
|
||||
#[derive(Clone, Default, PartialEq, Eq)]
|
||||
pub struct Script(pub Vec<u8>);
|
||||
|
||||
impl fmt::Debug for Script {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
struct ScriptPrinter<'s>(&'s [u8]);
|
||||
impl<'s> fmt::Debug for ScriptPrinter<'s> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let mut l = f.debug_list();
|
||||
let mut unknown: Option<String> = None;
|
||||
for b in self.0 {
|
||||
if let Some(opcode) = OpCode::parse(*b) {
|
||||
if let Some(s) = unknown.take() {
|
||||
l.entry(&s);
|
||||
}
|
||||
l.entry(&opcode);
|
||||
} else {
|
||||
let encoded = format!("{:02x}", b);
|
||||
if let Some(s) = &mut unknown {
|
||||
s.push_str(&encoded);
|
||||
} else {
|
||||
unknown = Some(encoded);
|
||||
}
|
||||
}
|
||||
}
|
||||
l.finish()
|
||||
}
|
||||
}
|
||||
|
||||
if f.alternate() {
|
||||
f.debug_tuple("Script")
|
||||
.field(&ScriptPrinter(&self.0))
|
||||
.finish()
|
||||
} else {
|
||||
f.debug_tuple("Script")
|
||||
.field(&hex::encode(&self.0))
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Script {
|
||||
pub fn read<R: Read>(mut reader: R) -> io::Result<Self> {
|
||||
let script = Vector::read(&mut reader, |r| r.read_u8())?;
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
use std::array::TryFromSliceError;
|
||||
use std::fmt;
|
||||
|
||||
use subtle::{Choice, ConstantTimeEq};
|
||||
|
||||
|
@ -9,9 +10,17 @@ use crate::sapling::{
|
|||
};
|
||||
|
||||
/// Typesafe wrapper for nullifier values.
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||
#[derive(Copy, Clone, PartialEq, Eq)]
|
||||
pub struct Nullifier(pub [u8; 32]);
|
||||
|
||||
impl fmt::Debug for Nullifier {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_tuple("Nullifier")
|
||||
.field(&hex::encode(self.0))
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl Nullifier {
|
||||
pub fn from_slice(bytes: &[u8]) -> Result<Nullifier, TryFromSliceError> {
|
||||
bytes.try_into().map(Nullifier)
|
||||
|
|
|
@ -7,6 +7,8 @@ use ff::{Field, PrimeField};
|
|||
use group::GroupEncoding;
|
||||
use jubjub::{AffinePoint, ExtendedPoint, SubgroupPoint};
|
||||
use rand_core::RngCore;
|
||||
|
||||
use std::fmt;
|
||||
use std::io::{self, Read, Write};
|
||||
use std::ops::{AddAssign, MulAssign, Neg};
|
||||
|
||||
|
@ -28,12 +30,21 @@ fn h_star(a: &[u8], b: &[u8]) -> jubjub::Fr {
|
|||
hash_to_scalar(b"Zcash_RedJubjubH", a, b)
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct Signature {
|
||||
rbar: [u8; 32],
|
||||
sbar: [u8; 32],
|
||||
}
|
||||
|
||||
impl fmt::Debug for Signature {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_struct("Signature")
|
||||
.field("rbar", &hex::encode(self.rbar))
|
||||
.field("sbar", &hex::encode(self.sbar))
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
pub struct PrivateKey(pub jubjub::Fr);
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
|
|
Loading…
Reference in New Issue