2019-09-19 07:45:37 -07:00
|
|
|
//! Transaction types.
|
|
|
|
|
2019-12-04 21:47:50 -08:00
|
|
|
use std::{fmt, io};
|
|
|
|
|
|
|
|
use hex;
|
2019-09-27 18:25:35 -07:00
|
|
|
|
|
|
|
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.
|
2019-12-04 21:47:50 -08:00
|
|
|
#[derive(Copy, Clone, Eq, PartialEq)]
|
2019-09-27 18:25:35 -07:00
|
|
|
pub struct TransactionHash(pub [u8; 32]);
|
|
|
|
|
2019-12-04 21:47:50 -08:00
|
|
|
impl fmt::Debug for TransactionHash {
|
|
|
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
|
|
f.debug_tuple("TransactionHash")
|
|
|
|
.field(&hex::encode(&self.0))
|
|
|
|
.finish()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-09-27 18:25:35 -07:00
|
|
|
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.");
|
2019-09-27 18:25:35 -07:00
|
|
|
Self(hash_writer.finish())
|
|
|
|
}
|
|
|
|
}
|
2019-09-27 18:08:25 -07:00
|
|
|
|
2019-09-19 07:45:37 -07:00
|
|
|
/// 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.
|
2019-09-27 18:25:35 -07:00
|
|
|
pub hash: TransactionHash,
|
2019-09-19 07:45:37 -07:00
|
|
|
|
2019-09-25 18:25:46 -07:00
|
|
|
/// Identifies which UTXO from that transaction is referenced; the
|
|
|
|
/// first output is 0, etc.
|
2019-09-19 07:45:37 -07:00
|
|
|
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
|
2019-09-26 19:48:48 -07:00
|
|
|
/// 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).
|
2019-09-19 07:45:37 -07:00
|
|
|
// `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
|
|
|
|
///
|
2019-09-25 23:23:04 -07:00
|
|
|
/// 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).
|
2019-09-25 23:23:04 -07:00
|
|
|
// This is not up to date with the data included in the Zcash
|
|
|
|
// transaction format: https://zips.z.cash/protocol/protocol.pdf
|
2019-09-19 07:45:37 -07:00
|
|
|
#[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,
|
|
|
|
}
|
2019-09-27 18:25:35 -07:00
|
|
|
|
|
|
|
impl ZcashSerialize for Transaction {
|
2019-09-30 11:21:53 -07:00
|
|
|
fn zcash_serialize<W: io::Write>(&self, _writer: W) -> Result<(), SerializationError> {
|
2019-09-27 18:25:35 -07:00
|
|
|
unimplemented!();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl ZcashDeserialize for Transaction {
|
2019-09-30 11:21:53 -07:00
|
|
|
fn zcash_deserialize<R: io::Read>(_reader: R) -> Result<Self, SerializationError> {
|
2019-09-27 18:25:35 -07:00
|
|
|
unimplemented!();
|
|
|
|
}
|
|
|
|
}
|
2019-12-04 21:47:50 -08:00
|
|
|
|
|
|
|
#[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\")"
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|