From 33f921235d6d9847b54f5b4504ec46f599ca1676 Mon Sep 17 00:00:00 2001 From: Greg Fitzgerald Date: Fri, 25 Jan 2019 23:41:20 -0700 Subject: [PATCH] Improve message-signing ergonomics --- sdk/src/signature.rs | 7 ++++++- sdk/src/transaction.rs | 8 ++++---- src/entry.rs | 8 +++----- src/leader_scheduler.rs | 5 ++--- src/sigverify.rs | 10 +++++----- src/storage_stage.rs | 9 ++++----- src/vote_signer_proxy.rs | 7 +++---- vote-signer/src/rpc.rs | 21 +++++++++------------ 8 files changed, 36 insertions(+), 39 deletions(-) diff --git a/sdk/src/signature.rs b/sdk/src/signature.rs index 90e0b2b84d..1e132e402d 100644 --- a/sdk/src/signature.rs +++ b/sdk/src/signature.rs @@ -35,7 +35,7 @@ impl Signature { pub trait Signable { fn sign(&mut self, keypair: &Keypair) { let data = self.signable_data(); - self.set_signature(Signature::new(&keypair.sign(&data).as_ref())); + self.set_signature(keypair.sign_message(&data)); } fn verify(&self) -> bool { self.get_signature() @@ -69,6 +69,7 @@ impl fmt::Display for Signature { pub trait KeypairUtil { fn new() -> Self; fn pubkey(&self) -> Pubkey; + fn sign_message(&self, message: &[u8]) -> Signature; } impl KeypairUtil for Ed25519KeyPair { @@ -83,6 +84,10 @@ impl KeypairUtil for Ed25519KeyPair { fn pubkey(&self) -> Pubkey { Pubkey::new(self.public_key_bytes()) } + + fn sign_message(&self, message: &[u8]) -> Signature { + Signature::new(self.sign(message).as_ref()) + } } pub fn read_pkcs8(path: &str) -> Result, Box> { diff --git a/sdk/src/transaction.rs b/sdk/src/transaction.rs index d595f14dbe..6e13c40739 100644 --- a/sdk/src/transaction.rs +++ b/sdk/src/transaction.rs @@ -193,7 +193,7 @@ impl Transaction { &self.program_ids[program_ids_index as usize] } /// Get the transaction data to sign. - pub fn get_sign_data(&self) -> Vec { + pub fn message(&self) -> Vec { let mut buf = vec![0u8; PACKET_DATA_SIZE]; let mut wr = Cursor::new(&mut buf[..]); serialize_vec_with(&mut wr, &self.account_keys, Transaction::serialize_pubkey) @@ -213,10 +213,10 @@ impl Transaction { /// Sign this transaction. pub fn sign(&mut self, keypairs: &[&Keypair], last_id: Hash) { self.last_id = last_id; - let sign_data = self.get_sign_data(); + let message = self.message(); self.signatures = keypairs .iter() - .map(|keypair| Signature::new(&keypair.sign(&sign_data).as_ref())) + .map(|keypair| keypair.sign_message(&message)) .collect(); } @@ -224,7 +224,7 @@ impl Transaction { pub fn verify_signature(&self) -> bool { self.signatures .iter() - .all(|s| s.verify(&self.from().as_ref(), &self.get_sign_data())) + .all(|s| s.verify(&self.from().as_ref(), &self.message())) } /// Verify that references in the instructions are valid diff --git a/src/entry.rs b/src/entry.rs index 6840e85f89..5dd701d3bc 100644 --- a/src/entry.rs +++ b/src/entry.rs @@ -486,7 +486,7 @@ mod tests { use crate::packet::{to_blobs, BLOB_DATA_SIZE, PACKET_DATA_SIZE}; use solana_sdk::budget_transaction::BudgetTransaction; use solana_sdk::hash::hash; - use solana_sdk::signature::{Keypair, KeypairUtil, Signature}; + use solana_sdk::signature::{Keypair, KeypairUtil}; use solana_sdk::system_transaction::SystemTransaction; use solana_sdk::transaction::Transaction; use std::net::{IpAddr, Ipv4Addr, SocketAddr}; @@ -608,8 +608,7 @@ mod tests { let keypair = Keypair::new(); let vote_account = Keypair::new(); let tx = Transaction::vote_new(&vote_account.pubkey(), Vote { tick_height: 1 }, one, 1); - let msg = tx.get_sign_data(); - let sig = Signature::new(&vote_account.sign(&msg).as_ref()); + let sig = vote_account.sign_message(&tx.message()); let tx0 = Transaction { signatures: vec![sig], account_keys: tx.account_keys, @@ -666,8 +665,7 @@ mod tests { let keypair = Keypair::new(); let vote_account = Keypair::new(); let tx = Transaction::vote_new(&vote_account.pubkey(), Vote { tick_height: 1 }, next_id, 2); - let msg = tx.get_sign_data(); - let sig = Signature::new(&vote_account.sign(&msg).as_ref()); + let sig = vote_account.sign_message(&tx.message()); let tx_small = Transaction { signatures: vec![sig], account_keys: tx.account_keys, diff --git a/src/leader_scheduler.rs b/src/leader_scheduler.rs index 50f0f7c767..76424950f0 100644 --- a/src/leader_scheduler.rs +++ b/src/leader_scheduler.rs @@ -10,7 +10,7 @@ use byteorder::{LittleEndian, ReadBytesExt}; use hashbrown::HashSet; use solana_sdk::hash::{hash, Hash}; use solana_sdk::pubkey::Pubkey; -use solana_sdk::signature::{Keypair, KeypairUtil, Signature}; +use solana_sdk::signature::{Keypair, KeypairUtil}; use solana_sdk::system_transaction::SystemTransaction; use solana_sdk::transaction::Transaction; use solana_sdk::vote_program::{self, Vote, VoteProgram}; @@ -505,8 +505,7 @@ pub fn make_active_set_entries( // 3) Create vote entry let vote = Vote { tick_height: 1 }; let tx = Transaction::vote_new(&vote_account_id, vote, *last_tick_id, 0); - let msg = tx.get_sign_data(); - let sig = Signature::new(&active_keypair.sign(&msg).as_ref()); + let sig = active_keypair.sign_message(&tx.message()); let vote_tx = Transaction { signatures: vec![sig], account_keys: tx.account_keys, diff --git a/src/sigverify.rs b/src/sigverify.rs index 885d0cdedb..a227b858ca 100644 --- a/src/sigverify.rs +++ b/src/sigverify.rs @@ -370,7 +370,7 @@ mod tests { fn test_system_transaction_layout() { let tx = test_tx(); let tx_bytes = serialize(&tx).unwrap(); - let sign_data = tx.get_sign_data(); + let message = tx.message(); let packet = sigverify::make_packet_from_transaction(tx.clone()); let (sig_len, sig_start, msg_start_offset, pubkey_offset) = @@ -385,7 +385,7 @@ mod tests { Some(pubkey_offset as usize) ); assert_eq!( - memfind(&tx_bytes, &sign_data), + memfind(&tx_bytes, &message), Some(msg_start_offset as usize) ); assert_eq!( @@ -401,7 +401,7 @@ mod tests { use crate::packet::PACKET_DATA_SIZE; let mut tx0 = test_tx(); tx0.instructions[0].userdata = vec![1, 2, 3]; - let sign_data0a = tx0.get_sign_data(); + let message0a = tx0.message(); let tx_bytes = serialize(&tx0).unwrap(); assert!(tx_bytes.len() < PACKET_DATA_SIZE); assert_eq!( @@ -413,8 +413,8 @@ mod tests { assert_eq!(tx1.instructions[0].userdata, vec![1, 2, 3]); tx0.instructions[0].userdata = vec![1, 2, 4]; - let sign_data0b = tx0.get_sign_data(); - assert_ne!(sign_data0a, sign_data0b); + let message0b = tx0.message(); + assert_ne!(message0a, message0b); } #[test] diff --git a/src/storage_stage.rs b/src/storage_stage.rs index 0597cdf8a7..a98ffb3cf5 100644 --- a/src/storage_stage.rs +++ b/src/storage_stage.rs @@ -452,7 +452,7 @@ mod tests { use solana_sdk::hash::Hash; use solana_sdk::hash::Hasher; use solana_sdk::pubkey::Pubkey; - use solana_sdk::signature::{Keypair, KeypairUtil, Signature}; + use solana_sdk::signature::{Keypair, KeypairUtil}; use solana_sdk::transaction::Transaction; use solana_sdk::vote_program::Vote; use solana_sdk::vote_transaction::VoteTransaction; @@ -531,7 +531,7 @@ mod tests { let keypair = Keypair::new(); let hash = Hash::default(); - let signature = Signature::new(keypair.sign(&hash.as_ref()).as_ref()); + let signature = keypair.sign_message(&hash.as_ref()); let mut result = storage_state.get_mining_result(&signature); assert_eq!(result, Hash::default()); @@ -609,8 +609,7 @@ mod tests { }; let keypair = Keypair::new(); let tx = Transaction::vote_new(&keypair.pubkey(), vote, Hash::default(), 1); - let msg = tx.get_sign_data(); - let sig = Signature::new(&keypair.sign(&msg).as_ref()); + let sig = keypair.sign_message(&tx.message()); let vote_tx = Transaction { signatures: vec![sig], account_keys: tx.account_keys, @@ -661,7 +660,7 @@ mod tests { .for_each(move |_| { let keypair = Keypair::new(); let hash = hasher.clone().result(); - let signature = Signature::new(keypair.sign(&hash.as_ref()).as_ref()); + let signature = keypair.sign_message(&hash.as_ref()); let ix = get_identity_index_from_signature(&signature); hist[ix].fetch_add(1, Ordering::Relaxed); }); diff --git a/src/vote_signer_proxy.rs b/src/vote_signer_proxy.rs index 8a1318e0e5..4477bb9d95 100644 --- a/src/vote_signer_proxy.rs +++ b/src/vote_signer_proxy.rs @@ -86,7 +86,7 @@ pub struct VoteSignerProxy { impl VoteSignerProxy { pub fn new(keypair: &Arc, signer: Box) -> Self { let msg = "Registering a new node"; - let sig = Signature::new(&keypair.sign(msg.as_bytes()).as_ref()); + let sig = keypair.sign_message(msg.as_bytes()); let vote_account = signer .register(keypair.pubkey(), &sig, msg.as_bytes()) .unwrap(); @@ -161,9 +161,8 @@ impl VoteSignerProxy { pub fn new_signed_vote_transaction(&self, last_id: &Hash, tick_height: u64) -> Transaction { let vote = Vote { tick_height }; let tx = Transaction::vote_new(&self.vote_account, vote, *last_id, 0); - - let msg = tx.get_sign_data(); - let sig = Signature::new(&self.keypair.sign(&msg).as_ref()); + let msg = tx.message(); + let sig = self.keypair.sign_message(&msg); let keypair = self.keypair.clone(); let vote_signature = self.signer.sign(keypair.pubkey(), &sig, &msg).unwrap(); diff --git a/vote-signer/src/rpc.rs b/vote-signer/src/rpc.rs index 40245afd28..843e8ab8e9 100644 --- a/vote-signer/src/rpc.rs +++ b/vote-signer/src/rpc.rs @@ -156,10 +156,7 @@ impl VoteSigner for LocalVoteSigner { fn sign(&self, pubkey: Pubkey, sig: &Signature, msg: &[u8]) -> Result { verify_signature(&sig, &pubkey, &msg)?; match self.nodes.read().unwrap().get(&pubkey) { - Some(voting_keypair) => { - let sig = Signature::new(&voting_keypair.sign(&msg).as_ref()); - Ok(sig) - } + Some(voting_keypair) => Ok(voting_keypair.sign_message(&msg)), None => Err(Error::invalid_request()), } } @@ -201,7 +198,7 @@ mod tests { let node_keypair = Keypair::new(); let node_pubkey = node_keypair.pubkey(); let msg = "This is a test"; - let sig = Signature::new(&node_keypair.sign(msg.as_bytes()).as_ref()); + let sig = node_keypair.sign_message(msg.as_bytes()); let req = json!({ "jsonrpc": "2.0", "id": 1, @@ -238,7 +235,7 @@ mod tests { let node_pubkey = node_keypair.pubkey(); let msg = "This is a test"; let msg1 = "This is a Test1"; - let sig = Signature::new(&node_keypair.sign(msg.as_bytes()).as_ref()); + let sig = node_keypair.sign_message(msg.as_bytes()); let req = json!({ "jsonrpc": "2.0", "id": 1, @@ -269,7 +266,7 @@ mod tests { let node_keypair = Keypair::new(); let node_pubkey = node_keypair.pubkey(); let msg = "This is a test"; - let sig = Signature::new(&node_keypair.sign(msg.as_bytes()).as_ref()); + let sig = node_keypair.sign_message(msg.as_bytes()); let req = json!({ "jsonrpc": "2.0", "id": 1, @@ -301,7 +298,7 @@ mod tests { let node_pubkey = node_keypair.pubkey(); let msg = "This is a test"; let msg1 = "This is a Test1"; - let sig = Signature::new(&node_keypair.sign(msg.as_bytes()).as_ref()); + let sig = node_keypair.sign_message(msg.as_bytes()); let req = json!({ "jsonrpc": "2.0", "id": 1, @@ -332,7 +329,7 @@ mod tests { let node_keypair = Keypair::new(); let node_pubkey = node_keypair.pubkey(); let msg = "This is a test"; - let sig = Signature::new(&node_keypair.sign(msg.as_bytes()).as_ref()); + let sig = node_keypair.sign_message(msg.as_bytes()); let req = json!({ "jsonrpc": "2.0", @@ -396,7 +393,7 @@ mod tests { let node_keypair = Keypair::new(); let node_pubkey = node_keypair.pubkey(); let msg = "This is a test"; - let sig = Signature::new(&node_keypair.sign(msg.as_bytes()).as_ref()); + let sig = node_keypair.sign_message(msg.as_bytes()); let req = json!({ "jsonrpc": "2.0", "id": 1, @@ -427,7 +424,7 @@ mod tests { let node_keypair = Keypair::new(); let node_pubkey = node_keypair.pubkey(); let msg = "This is a test"; - let sig = Signature::new(&node_keypair.sign(msg.as_bytes()).as_ref()); + let sig = node_keypair.sign_message(msg.as_bytes()); let req = json!({ "jsonrpc": "2.0", @@ -476,7 +473,7 @@ mod tests { let node_pubkey = node_keypair.pubkey(); let msg = "This is a test"; let msg1 = "This is a Test"; - let sig = Signature::new(&node_keypair.sign(msg.as_bytes()).as_ref()); + let sig = node_keypair.sign_message(msg.as_bytes()); let req = json!({ "jsonrpc": "2.0",