2018-03-06 11:18:17 -08:00
|
|
|
//! The `transaction` crate provides functionality for creating log transactions.
|
|
|
|
|
2018-03-06 11:48:26 -08:00
|
|
|
use signature::{get_pubkey, verify_signature, PublicKey, Signature};
|
2018-03-06 11:18:17 -08:00
|
|
|
use ring::signature::Ed25519KeyPair;
|
|
|
|
use serde::Serialize;
|
|
|
|
use bincode::serialize;
|
|
|
|
use log::Sha256Hash;
|
|
|
|
|
|
|
|
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
|
|
|
|
pub struct Transaction<T> {
|
|
|
|
pub from: PublicKey,
|
|
|
|
pub to: PublicKey,
|
|
|
|
pub data: T,
|
|
|
|
pub last_id: Sha256Hash,
|
|
|
|
pub sig: Signature,
|
|
|
|
}
|
|
|
|
|
2018-03-06 11:26:39 -08:00
|
|
|
impl<T: Serialize> Transaction<T> {
|
2018-03-06 11:18:17 -08:00
|
|
|
pub fn new_claim(to: PublicKey, data: T, last_id: Sha256Hash, sig: Signature) -> Self {
|
|
|
|
Transaction {
|
|
|
|
from: to,
|
|
|
|
to,
|
|
|
|
data,
|
|
|
|
last_id,
|
|
|
|
sig,
|
|
|
|
}
|
|
|
|
}
|
2018-03-06 11:26:39 -08:00
|
|
|
|
|
|
|
pub fn verify(&self) -> bool {
|
|
|
|
let sign_data = serialize(&(&self.from, &self.to, &self.data, &self.last_id)).unwrap();
|
|
|
|
verify_signature(&self.from, &sign_data, &self.sig)
|
|
|
|
}
|
2018-03-06 11:18:17 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
fn sign_serialized<T: Serialize>(data: &T, keypair: &Ed25519KeyPair) -> Signature {
|
|
|
|
let serialized = serialize(data).unwrap();
|
2018-03-06 11:48:26 -08:00
|
|
|
Signature::clone_from_slice(keypair.sign(&serialized).as_ref())
|
2018-03-06 11:18:17 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Return a signature for the given transaction data using the private key from the given keypair.
|
|
|
|
pub fn sign_transaction_data<T: Serialize>(
|
|
|
|
data: &T,
|
|
|
|
keypair: &Ed25519KeyPair,
|
|
|
|
to: &PublicKey,
|
|
|
|
last_id: &Sha256Hash,
|
|
|
|
) -> Signature {
|
|
|
|
let from = &get_pubkey(keypair);
|
|
|
|
sign_serialized(&(from, to, data, last_id), keypair)
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Return a signature for the given data using the private key from the given keypair.
|
|
|
|
pub fn sign_claim_data<T: Serialize>(
|
|
|
|
data: &T,
|
|
|
|
keypair: &Ed25519KeyPair,
|
|
|
|
last_id: &Sha256Hash,
|
|
|
|
) -> Signature {
|
|
|
|
sign_transaction_data(data, keypair, &get_pubkey(keypair), last_id)
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
mod tests {
|
|
|
|
use super::*;
|
|
|
|
use bincode::{deserialize, serialize};
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_serialize_claim() {
|
|
|
|
let claim0 = Transaction::new_claim(
|
|
|
|
Default::default(),
|
|
|
|
0u8,
|
|
|
|
Default::default(),
|
|
|
|
Default::default(),
|
|
|
|
);
|
|
|
|
let buf = serialize(&claim0).unwrap();
|
|
|
|
let claim1: Transaction<u8> = deserialize(&buf).unwrap();
|
|
|
|
assert_eq!(claim1, claim0);
|
|
|
|
}
|
|
|
|
}
|