Compute TxId for Transaction

This commit is contained in:
Jack Grigg
2018-12-03 12:54:11 +00:00
parent 670bb277e9
commit 4289843852
5 changed files with 98 additions and 32 deletions

View File

@@ -13,6 +13,7 @@ lazy_static = "1"
pairing = { path = "../pairing" }
rand = "0.4"
sapling-crypto = { path = "../sapling-crypto" }
sha2 = "0.8"
[dependencies.blake2-rfc]
git = "https://github.com/gtank/blake2-rfc"

View File

@@ -8,6 +8,7 @@ extern crate hex;
extern crate pairing;
extern crate rand;
extern crate sapling_crypto;
extern crate sha2;
use sapling_crypto::jubjub::JubjubBls12;

View File

@@ -1,6 +1,7 @@
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
use hex;
use sapling_crypto::redjubjub::Signature;
use sha2::{Digest, Sha256};
use std::fmt;
use std::io::{self, Read, Write};
use std::ops::Deref;
@@ -35,7 +36,7 @@ impl fmt::Display for TxId {
/// A Zcash transaction.
#[derive(Debug)]
pub struct Transaction(TransactionData);
pub struct Transaction(TransactionData, TxId);
impl Deref for Transaction {
type Target = TransactionData;
@@ -125,12 +126,26 @@ impl TransactionData {
header
}
pub fn freeze(self) -> Transaction {
Transaction(self)
pub fn freeze(self) -> io::Result<Transaction> {
Transaction::from_data(self)
}
}
impl Transaction {
fn from_data(data: TransactionData) -> io::Result<Self> {
let mut tx = Transaction(data, TxId([0; 32]));
let mut raw = vec![];
tx.write(&mut raw)?;
(tx.1)
.0
.copy_from_slice(&Sha256::digest(&Sha256::digest(&raw)));
Ok(tx)
}
pub fn txid(&self) -> TxId {
self.1
}
pub fn read<R: Read>(mut reader: R) -> io::Result<Self> {
let header = reader.read_u32::<LittleEndian>()?;
let overwintered = (header >> 31) == 1;
@@ -195,7 +210,7 @@ impl Transaction {
false => None,
};
Ok(Transaction(TransactionData {
Transaction::from_data(TransactionData {
overwintered,
version,
version_group_id,
@@ -210,7 +225,7 @@ impl Transaction {
joinsplit_pubkey,
joinsplit_sig,
binding_sig,
}))
})
}
pub fn write<W: Write>(&self, mut writer: W) -> io::Result<()> {

View File

@@ -159,51 +159,33 @@ fn tx_read_write() {
#[test]
fn tx_write_rejects_unexpected_joinsplit_pubkey() {
// Succeeds without a JoinSplit pubkey
{
let tx = TransactionData::new().freeze();
let mut encoded = Vec::new();
assert!(tx.write(&mut encoded).is_ok());
}
assert!(TransactionData::new().freeze().is_ok());
// Fails with an unexpected JoinSplit pubkey
{
let mut tx = TransactionData::new();
tx.joinsplit_pubkey = Some([0; 32]);
let tx = tx.freeze();
let mut encoded = Vec::new();
assert!(tx.write(&mut encoded).is_err());
assert!(tx.freeze().is_err());
}
}
#[test]
fn tx_write_rejects_unexpected_joinsplit_sig() {
// Succeeds without a JoinSplit signature
{
let tx = TransactionData::new().freeze();
let mut encoded = Vec::new();
assert!(tx.write(&mut encoded).is_ok());
}
assert!(TransactionData::new().freeze().is_ok());
// Fails with an unexpected JoinSplit signature
{
let mut tx = TransactionData::new();
tx.joinsplit_sig = Some([0; 64]);
let tx = tx.freeze();
let mut encoded = Vec::new();
assert!(tx.write(&mut encoded).is_err());
assert!(tx.freeze().is_err());
}
}
#[test]
fn tx_write_rejects_unexpected_binding_sig() {
// Succeeds without a binding signature
{
let tx = TransactionData::new().freeze();
let mut encoded = Vec::new();
assert!(tx.write(&mut encoded).is_ok());
}
assert!(TransactionData::new().freeze().is_ok());
// Fails with an unexpected binding signature
{
@@ -218,10 +200,7 @@ fn tx_write_rejects_unexpected_binding_sig() {
let mut tx = TransactionData::new();
tx.binding_sig = Some(sig);
let tx = tx.freeze();
let mut encoded = Vec::new();
assert!(tx.write(&mut encoded).is_err());
assert!(tx.freeze().is_err());
}
}