shuttle_core/
transaction.rs

1use amount::Stroops;
2use time_bounds::TimeBounds;
3use memo::Memo;
4use network::Network;
5use crypto::{KeyPair, PublicKey};
6use signature::DecoratedSignature;
7use operation::Operation;
8use error::Result;
9use xdr::ToXdr;
10use crypto;
11
12const BASE_FEE: Stroops = Stroops(100);
13
14/// A transaction containing operations that change the ledger state.
15#[derive(Debug, Clone)]
16pub struct Transaction {
17    /// The source account.
18    pub source: PublicKey,
19    /// The sequence number.
20    pub sequence: u64,
21    /// The fee.
22    pub fee: Stroops,
23    /// The validity time bounds.
24    pub time_bounds: Option<TimeBounds>,
25    /// The attached memo.
26    pub memo: Memo,
27    /// The operations.
28    pub operations: Vec<Operation>,
29}
30
31impl Transaction {
32    /// Create a new transaction.
33    pub fn new(
34        source: PublicKey,
35        sequence: u64,
36        time_bounds: Option<TimeBounds>,
37        memo: Memo,
38        operations: Vec<Operation>,
39    ) -> Transaction {
40        let fee = BASE_FEE * operations.len();
41        Transaction {
42            source,
43            sequence,
44            fee,
45            time_bounds,
46            memo,
47            operations,
48        }
49    }
50
51    /// The transaction source account.
52    pub fn source(&self) -> &PublicKey {
53        &self.source
54    }
55
56    /// The transaction fee.
57    pub fn base_fee(&self) -> &Stroops {
58        &self.fee
59    }
60
61    /// The transaction time bounds for its validity.
62    pub fn time_bounds(&self) -> &Option<TimeBounds> {
63        &self.time_bounds
64    }
65
66    /// The memo attached to the transaction.
67    pub fn memo(&self) -> &Memo {
68        &self.memo
69    }
70
71    /// The transaction sequence number.
72    pub fn sequence(&self) -> u64 {
73        self.sequence
74    }
75
76    /// The operations included in the transaction.
77    pub fn operations(&self) -> &Vec<Operation> {
78        &self.operations
79    }
80
81    /// Sign the transaction, returning a signed transaction that can be submitted to the `network`.
82    pub fn sign(self, keypair: &KeyPair, network: &Network) -> Result<SignedTransaction> {
83        let mut sig = SignedTransaction::new(self, network)?;
84        sig.sign(keypair)?;
85        Ok(sig)
86    }
87}
88
89/// A transaction that was signed.
90#[derive(Debug, Clone)]
91pub struct SignedTransaction {
92    network_id: Vec<u8>,
93    transaction: Transaction,
94    signatures: Vec<DecoratedSignature>,
95}
96
97impl SignedTransaction {
98    /// Create a new signed transaction on the `network`.
99    pub fn new(transaction: Transaction, network: &Network) -> Result<SignedTransaction> {
100        Ok(SignedTransaction {
101            network_id: network.network_id().clone(),
102            transaction,
103            signatures: Vec::new(),
104        })
105    }
106
107    /// Create a new transaction without the network information attached.
108    pub fn new_without_network(
109        transaction: Transaction,
110        signatures: Vec<DecoratedSignature>,
111    ) -> SignedTransaction {
112        SignedTransaction {
113            network_id: Vec::new(),
114            transaction,
115            signatures,
116        }
117    }
118
119    /// Add one more signature to the transaction.
120    pub fn sign(&mut self, keypair: &KeyPair) -> Result<()> {
121        let payload = self.hash()?;
122        let new_signature = keypair.sign_decorated(&payload);
123        self.signatures.push(new_signature);
124        Ok(())
125    }
126
127    /// Return the transaction hash, suitable for signing.
128    pub fn hash(&self) -> Result<Vec<u8>> {
129        let payload = self.signature_base()?;
130        Ok(crypto::hash(&payload))
131    }
132
133    /// Return the *signature base* of the transaction, which is the value
134    /// that, when hashed, should be signed.
135    pub fn signature_base(&self) -> Result<Vec<u8>> {
136        let sig_payload = TransactionSignaturePayload {
137            network_id: &self.network_id,
138            transaction: &self.transaction,
139        };
140        let mut payload = Vec::new();
141        sig_payload.to_writer(&mut payload)?;
142        Ok(payload)
143    }
144
145    /// Return the transaction.
146    pub fn transaction(&self) -> &Transaction {
147        &self.transaction
148    }
149
150    /// Return the signatures.
151    pub fn signatures(&self) -> &Vec<DecoratedSignature> {
152        &self.signatures
153    }
154}
155
156/// Represent the data, when signed, will be signed.
157#[derive(Debug)]
158pub struct TransactionSignaturePayload<'a> {
159    /// The network where the transaction will be submitted to.
160    pub network_id: &'a Vec<u8>,
161    /// The transaction.
162    pub transaction: &'a Transaction,
163}