zebra/zebra-chain/src/transaction.rs

159 lines
5.2 KiB
Rust
Raw Normal View History

//! Transaction types.
use std::{fmt, io};
use hex;
use crate::serialization::{SerializationError, ZcashDeserialize, ZcashSerialize};
use crate::sha256d_writer::Sha256dWriter;
/// A hash of a `Transaction`
///
/// TODO: I'm pretty sure this is also a SHA256d hash but I haven't
/// confirmed it yet.
#[derive(Copy, Clone, Eq, PartialEq)]
pub struct TransactionHash(pub [u8; 32]);
impl fmt::Debug for TransactionHash {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_tuple("TransactionHash")
.field(&hex::encode(&self.0))
.finish()
}
}
impl From<Transaction> for TransactionHash {
fn from(transaction: Transaction) -> Self {
let mut hash_writer = Sha256dWriter::default();
transaction
.zcash_serialize(&mut hash_writer)
2019-09-27 19:22:26 -07:00
.expect("Transactions must serialize into the hash.");
Self(hash_writer.finish())
}
}
/// OutPoint
///
/// A particular transaction output reference.
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub struct OutPoint {
2019-09-25 18:25:46 -07:00
/// References the transaction that contains the UTXO being spent.
pub hash: TransactionHash,
2019-09-25 18:25:46 -07:00
/// Identifies which UTXO from that transaction is referenced; the
/// first output is 0, etc.
pub index: u32,
}
/// Transaction Input
// `Copy` cannot be implemented for `Vec<u8>`
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct TransactionInput {
/// The previous output transaction reference.
pub previous_output: OutPoint,
/// Computational Script for confirming transaction authorization.
// XXX pzec uses their own `Bytes` type that wraps a `Vec<u8>`
// with some extra methods.
pub signature_script: Vec<u8>,
/// Transaction version as defined by the sender. Intended for
/// "replacement" of transactions when information is updated
/// before inclusion into a block.
pub sequence: u32,
}
/// Transaction Output
2019-09-25 18:25:46 -07:00
///
/// The most fundamental building block of a transaction is a
/// transaction output -- the ZEC you own in your "wallet" is in
/// fact a subset of unspent transaction outputs (or "UTXO"s) of the
2019-09-25 18:25:46 -07:00
/// global UTXO set.
///
/// UTXOs are indivisible, discrete units of value which can only be
/// consumed in their entirety. Thus, if I want to send you 1 ZEC and
/// I only own one UTXO worth 2 ZEC, I would construct a transaction
/// that spends my UTXO and sends 1 ZEC to you and 1 ZEC back to me
/// (just like receiving change).
// `Copy` cannot be implemented for `Vec<u8>`
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct TransactionOutput {
/// Transaction value.
// At https://en.bitcoin.it/wiki/Protocol_documentation#tx, this is an i64.
pub value: u64,
/// Usually contains the public key as a Bitcoin script setting up
/// conditions to claim this output.
pub pk_script: Vec<u8>,
}
2019-09-25 18:25:46 -07:00
/// Transaction
///
/// A transaction is an encoded data structure that facilitates the
2019-09-25 18:25:46 -07:00
/// transfer of value between two public key addresses on the Zcash
/// ecosystem. Everything is designed to ensure that transactions can
/// created, propagated on the network, validated, and finally added
/// to the global ledger of transactions (the blockchain).
// This is not up to date with the data included in the Zcash
// transaction format: https://zips.z.cash/protocol/protocol.pdf
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct Transaction {
/// Transaction data format version (note, this is signed).
pub version: i32,
/// A list of 1 or more transaction inputs or sources for coins.
pub tx_in: Vec<TransactionInput>,
/// A list of 1 or more transaction outputs or destinations for coins.
pub tx_out: Vec<TransactionOutput>,
/// The block number or timestamp at which this transaction is unlocked:
///
/// |Value |Description |
/// |------------|----------------------------------------------------|
/// |0 |Not locked (default) |
/// |< 500000000 |Block number at which this transaction is unlocked |
/// |>= 500000000|UNIX timestamp at which this transaction is unlocked|
///
/// If all `TransactionInput`s have final (0xffffffff) sequence
/// numbers, then lock_time is irrelevant. Otherwise, the
/// transaction may not be added to a block until after `lock_time`.
pub lock_time: u32,
}
impl ZcashSerialize for Transaction {
fn zcash_serialize<W: io::Write>(&self, _writer: W) -> Result<(), SerializationError> {
unimplemented!();
}
}
impl ZcashDeserialize for Transaction {
fn zcash_deserialize<R: io::Read>(_reader: R) -> Result<Self, SerializationError> {
unimplemented!();
}
}
#[cfg(test)]
mod tests {
use std::io::Write;
use super::TransactionHash;
use crate::sha256d_writer::Sha256dWriter;
#[test]
fn transactionhash_debug() {
let preimage = b"foo bar baz";
let mut sha_writer = Sha256dWriter::default();
let _ = sha_writer.write_all(preimage);
let hash = TransactionHash(sha_writer.finish());
assert_eq!(
format!("{:?}", hash),
"TransactionHash(\"bf46b4b5030752fedac6f884976162bbfb29a9398f104a280b3e34d51b416631\")"
);
}
}