From 46984cbb270c8d2717628668f2b23357ab1f7eb1 Mon Sep 17 00:00:00 2001 From: Deirdre Connolly Date: Wed, 18 Sep 2019 15:57:06 -0400 Subject: [PATCH] Add `tx` message, along with `Transaction`, `Transaction(In|Out)put`, and `OutPoint` types --- zebra-chain/src/types.rs | 73 +++++++++++++++++++++++++++++++++++- zebra-network/src/message.rs | 20 +++++++--- 2 files changed, 86 insertions(+), 7 deletions(-) diff --git a/zebra-chain/src/types.rs b/zebra-chain/src/types.rs index de17d1e6..47d9130a 100644 --- a/zebra-chain/src/types.rs +++ b/zebra-chain/src/types.rs @@ -6,7 +6,7 @@ pub struct Sha256dChecksum(pub [u8; 4]); impl<'a> From<&'a [u8]> for Sha256dChecksum { fn from(bytes: &'a [u8]) -> Self { - use sha2::{Sha256, Digest}; + use sha2::{Digest, Sha256}; let hash1 = Sha256::digest(bytes); let hash2 = Sha256::digest(&hash1); let mut checksum = [0u8; 4]; @@ -47,6 +47,7 @@ pub enum InventoryType { /// message. See /// [BIP-152](https://github.com/bitcoin/bips/blob/master/bip-0152.mediawiki) /// for more info. + // XXX We may not need this, pzec does not. MsgCmpctBlock = 0x04, } @@ -54,6 +55,74 @@ pub enum InventoryType { #[derive(Copy, Clone, Debug, Eq, PartialEq)] pub struct InventoryVector(pub InventoryType, pub [u8; 32]); +/// OutPoint +/// +/// A particular transaction output reference. +#[derive(Copy, Clone, Debug, Eq, PartialEq)] +pub struct OutPoint { + /// The hash of the referenced transaction. + pub hash: [u8; 32], + + /// The index of the specific output in the transaction. The first output is 0, etc. + pub index: u32, +} + +/// Transaction Input +// `Copy` cannot be implemented for `Vec` +#[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 Bytes https://docs.rs/bytes/0.4.12/bytes/ + pub signature_script: Vec, + + /// 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 +// `Copy` cannot be implemented for `Vec` +#[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, +} + +/// Transaction Input +#[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, + + /// A list of 1 or more transaction outputs or destinations for coins. + pub tx_out: Vec, + + /// 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, +} + #[cfg(test)] mod tests { use super::*; @@ -66,4 +135,4 @@ mod tests { let expected = Sha256dChecksum([0x95, 0x95, 0xc9, 0xdf]); assert_eq!(checksum, expected); } -} \ No newline at end of file +} diff --git a/zebra-network/src/message.rs b/zebra-network/src/message.rs index 59c95cd4..d5414479 100644 --- a/zebra-network/src/message.rs +++ b/zebra-network/src/message.rs @@ -2,14 +2,14 @@ use std::io; -use byteorder::{BigEndian, LittleEndian, ReadBytesExt, WriteBytesExt}; +use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt}; use chrono::{DateTime, TimeZone, Utc}; use zebra_chain::{ serialization::{ ReadZcashExt, SerializationError, WriteZcashExt, ZcashDeserialize, ZcashSerialize, }, - types::{BlockHeight, Sha256dChecksum}, + types::{BlockHeight, Sha256dChecksum, Transaction}, }; use crate::meta_addr::MetaAddr; @@ -200,7 +200,16 @@ pub enum Message { /// A `tx` message. /// /// [Bitcoin reference](https://en.bitcoin.it/wiki/Protocol_documentation#tx) - Tx {/* XXX add fields */}, + // `flag` is not included (it's optional), and therefore + // `tx_witnesses` aren't either, as they go if `flag` goes. + Tx { + /// Transaction data format version (note, this is signed). + version: Version, + + /// The `Transaction` type itself. + // XXX Is this ~aesthetic~? + transaction: Transaction, + }, /// A `mempool` message. /// @@ -327,6 +336,7 @@ impl Message { } /// Try to read `self` from the given `reader`. + #[allow(dead_code)] fn try_read( _reader: R, _magic: Magic, @@ -343,8 +353,8 @@ impl Message { fn write_body( &self, mut writer: W, - m: Magic, - v: Version, + _m: Magic, + _v: Version, ) -> Result<(), SerializationError> { use Message::*; match *self {