Improve message-signing ergonomics
This commit is contained in:
@ -35,7 +35,7 @@ impl Signature {
|
|||||||
pub trait Signable {
|
pub trait Signable {
|
||||||
fn sign(&mut self, keypair: &Keypair) {
|
fn sign(&mut self, keypair: &Keypair) {
|
||||||
let data = self.signable_data();
|
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 {
|
fn verify(&self) -> bool {
|
||||||
self.get_signature()
|
self.get_signature()
|
||||||
@ -69,6 +69,7 @@ impl fmt::Display for Signature {
|
|||||||
pub trait KeypairUtil {
|
pub trait KeypairUtil {
|
||||||
fn new() -> Self;
|
fn new() -> Self;
|
||||||
fn pubkey(&self) -> Pubkey;
|
fn pubkey(&self) -> Pubkey;
|
||||||
|
fn sign_message(&self, message: &[u8]) -> Signature;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl KeypairUtil for Ed25519KeyPair {
|
impl KeypairUtil for Ed25519KeyPair {
|
||||||
@ -83,6 +84,10 @@ impl KeypairUtil for Ed25519KeyPair {
|
|||||||
fn pubkey(&self) -> Pubkey {
|
fn pubkey(&self) -> Pubkey {
|
||||||
Pubkey::new(self.public_key_bytes())
|
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<Vec<u8>, Box<error::Error>> {
|
pub fn read_pkcs8(path: &str) -> Result<Vec<u8>, Box<error::Error>> {
|
||||||
|
@ -193,7 +193,7 @@ impl Transaction {
|
|||||||
&self.program_ids[program_ids_index as usize]
|
&self.program_ids[program_ids_index as usize]
|
||||||
}
|
}
|
||||||
/// Get the transaction data to sign.
|
/// Get the transaction data to sign.
|
||||||
pub fn get_sign_data(&self) -> Vec<u8> {
|
pub fn message(&self) -> Vec<u8> {
|
||||||
let mut buf = vec![0u8; PACKET_DATA_SIZE];
|
let mut buf = vec![0u8; PACKET_DATA_SIZE];
|
||||||
let mut wr = Cursor::new(&mut buf[..]);
|
let mut wr = Cursor::new(&mut buf[..]);
|
||||||
serialize_vec_with(&mut wr, &self.account_keys, Transaction::serialize_pubkey)
|
serialize_vec_with(&mut wr, &self.account_keys, Transaction::serialize_pubkey)
|
||||||
@ -213,10 +213,10 @@ impl Transaction {
|
|||||||
/// Sign this transaction.
|
/// Sign this transaction.
|
||||||
pub fn sign(&mut self, keypairs: &[&Keypair], last_id: Hash) {
|
pub fn sign(&mut self, keypairs: &[&Keypair], last_id: Hash) {
|
||||||
self.last_id = last_id;
|
self.last_id = last_id;
|
||||||
let sign_data = self.get_sign_data();
|
let message = self.message();
|
||||||
self.signatures = keypairs
|
self.signatures = keypairs
|
||||||
.iter()
|
.iter()
|
||||||
.map(|keypair| Signature::new(&keypair.sign(&sign_data).as_ref()))
|
.map(|keypair| keypair.sign_message(&message))
|
||||||
.collect();
|
.collect();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -224,7 +224,7 @@ impl Transaction {
|
|||||||
pub fn verify_signature(&self) -> bool {
|
pub fn verify_signature(&self) -> bool {
|
||||||
self.signatures
|
self.signatures
|
||||||
.iter()
|
.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
|
/// Verify that references in the instructions are valid
|
||||||
|
@ -486,7 +486,7 @@ mod tests {
|
|||||||
use crate::packet::{to_blobs, BLOB_DATA_SIZE, PACKET_DATA_SIZE};
|
use crate::packet::{to_blobs, BLOB_DATA_SIZE, PACKET_DATA_SIZE};
|
||||||
use solana_sdk::budget_transaction::BudgetTransaction;
|
use solana_sdk::budget_transaction::BudgetTransaction;
|
||||||
use solana_sdk::hash::hash;
|
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::system_transaction::SystemTransaction;
|
||||||
use solana_sdk::transaction::Transaction;
|
use solana_sdk::transaction::Transaction;
|
||||||
use std::net::{IpAddr, Ipv4Addr, SocketAddr};
|
use std::net::{IpAddr, Ipv4Addr, SocketAddr};
|
||||||
@ -608,8 +608,7 @@ mod tests {
|
|||||||
let keypair = Keypair::new();
|
let keypair = Keypair::new();
|
||||||
let vote_account = Keypair::new();
|
let vote_account = Keypair::new();
|
||||||
let tx = Transaction::vote_new(&vote_account.pubkey(), Vote { tick_height: 1 }, one, 1);
|
let tx = Transaction::vote_new(&vote_account.pubkey(), Vote { tick_height: 1 }, one, 1);
|
||||||
let msg = tx.get_sign_data();
|
let sig = vote_account.sign_message(&tx.message());
|
||||||
let sig = Signature::new(&vote_account.sign(&msg).as_ref());
|
|
||||||
let tx0 = Transaction {
|
let tx0 = Transaction {
|
||||||
signatures: vec![sig],
|
signatures: vec![sig],
|
||||||
account_keys: tx.account_keys,
|
account_keys: tx.account_keys,
|
||||||
@ -666,8 +665,7 @@ mod tests {
|
|||||||
let keypair = Keypair::new();
|
let keypair = Keypair::new();
|
||||||
let vote_account = Keypair::new();
|
let vote_account = Keypair::new();
|
||||||
let tx = Transaction::vote_new(&vote_account.pubkey(), Vote { tick_height: 1 }, next_id, 2);
|
let tx = Transaction::vote_new(&vote_account.pubkey(), Vote { tick_height: 1 }, next_id, 2);
|
||||||
let msg = tx.get_sign_data();
|
let sig = vote_account.sign_message(&tx.message());
|
||||||
let sig = Signature::new(&vote_account.sign(&msg).as_ref());
|
|
||||||
let tx_small = Transaction {
|
let tx_small = Transaction {
|
||||||
signatures: vec![sig],
|
signatures: vec![sig],
|
||||||
account_keys: tx.account_keys,
|
account_keys: tx.account_keys,
|
||||||
|
@ -10,7 +10,7 @@ use byteorder::{LittleEndian, ReadBytesExt};
|
|||||||
use hashbrown::HashSet;
|
use hashbrown::HashSet;
|
||||||
use solana_sdk::hash::{hash, Hash};
|
use solana_sdk::hash::{hash, Hash};
|
||||||
use solana_sdk::pubkey::Pubkey;
|
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::system_transaction::SystemTransaction;
|
||||||
use solana_sdk::transaction::Transaction;
|
use solana_sdk::transaction::Transaction;
|
||||||
use solana_sdk::vote_program::{self, Vote, VoteProgram};
|
use solana_sdk::vote_program::{self, Vote, VoteProgram};
|
||||||
@ -505,8 +505,7 @@ pub fn make_active_set_entries(
|
|||||||
// 3) Create vote entry
|
// 3) Create vote entry
|
||||||
let vote = Vote { tick_height: 1 };
|
let vote = Vote { tick_height: 1 };
|
||||||
let tx = Transaction::vote_new(&vote_account_id, vote, *last_tick_id, 0);
|
let tx = Transaction::vote_new(&vote_account_id, vote, *last_tick_id, 0);
|
||||||
let msg = tx.get_sign_data();
|
let sig = active_keypair.sign_message(&tx.message());
|
||||||
let sig = Signature::new(&active_keypair.sign(&msg).as_ref());
|
|
||||||
let vote_tx = Transaction {
|
let vote_tx = Transaction {
|
||||||
signatures: vec![sig],
|
signatures: vec![sig],
|
||||||
account_keys: tx.account_keys,
|
account_keys: tx.account_keys,
|
||||||
|
@ -370,7 +370,7 @@ mod tests {
|
|||||||
fn test_system_transaction_layout() {
|
fn test_system_transaction_layout() {
|
||||||
let tx = test_tx();
|
let tx = test_tx();
|
||||||
let tx_bytes = serialize(&tx).unwrap();
|
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 packet = sigverify::make_packet_from_transaction(tx.clone());
|
||||||
|
|
||||||
let (sig_len, sig_start, msg_start_offset, pubkey_offset) =
|
let (sig_len, sig_start, msg_start_offset, pubkey_offset) =
|
||||||
@ -385,7 +385,7 @@ mod tests {
|
|||||||
Some(pubkey_offset as usize)
|
Some(pubkey_offset as usize)
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
memfind(&tx_bytes, &sign_data),
|
memfind(&tx_bytes, &message),
|
||||||
Some(msg_start_offset as usize)
|
Some(msg_start_offset as usize)
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
@ -401,7 +401,7 @@ mod tests {
|
|||||||
use crate::packet::PACKET_DATA_SIZE;
|
use crate::packet::PACKET_DATA_SIZE;
|
||||||
let mut tx0 = test_tx();
|
let mut tx0 = test_tx();
|
||||||
tx0.instructions[0].userdata = vec![1, 2, 3];
|
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();
|
let tx_bytes = serialize(&tx0).unwrap();
|
||||||
assert!(tx_bytes.len() < PACKET_DATA_SIZE);
|
assert!(tx_bytes.len() < PACKET_DATA_SIZE);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
@ -413,8 +413,8 @@ mod tests {
|
|||||||
assert_eq!(tx1.instructions[0].userdata, vec![1, 2, 3]);
|
assert_eq!(tx1.instructions[0].userdata, vec![1, 2, 3]);
|
||||||
|
|
||||||
tx0.instructions[0].userdata = vec![1, 2, 4];
|
tx0.instructions[0].userdata = vec![1, 2, 4];
|
||||||
let sign_data0b = tx0.get_sign_data();
|
let message0b = tx0.message();
|
||||||
assert_ne!(sign_data0a, sign_data0b);
|
assert_ne!(message0a, message0b);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -452,7 +452,7 @@ mod tests {
|
|||||||
use solana_sdk::hash::Hash;
|
use solana_sdk::hash::Hash;
|
||||||
use solana_sdk::hash::Hasher;
|
use solana_sdk::hash::Hasher;
|
||||||
use solana_sdk::pubkey::Pubkey;
|
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::transaction::Transaction;
|
||||||
use solana_sdk::vote_program::Vote;
|
use solana_sdk::vote_program::Vote;
|
||||||
use solana_sdk::vote_transaction::VoteTransaction;
|
use solana_sdk::vote_transaction::VoteTransaction;
|
||||||
@ -531,7 +531,7 @@ mod tests {
|
|||||||
|
|
||||||
let keypair = Keypair::new();
|
let keypair = Keypair::new();
|
||||||
let hash = Hash::default();
|
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);
|
let mut result = storage_state.get_mining_result(&signature);
|
||||||
assert_eq!(result, Hash::default());
|
assert_eq!(result, Hash::default());
|
||||||
|
|
||||||
@ -609,8 +609,7 @@ mod tests {
|
|||||||
};
|
};
|
||||||
let keypair = Keypair::new();
|
let keypair = Keypair::new();
|
||||||
let tx = Transaction::vote_new(&keypair.pubkey(), vote, Hash::default(), 1);
|
let tx = Transaction::vote_new(&keypair.pubkey(), vote, Hash::default(), 1);
|
||||||
let msg = tx.get_sign_data();
|
let sig = keypair.sign_message(&tx.message());
|
||||||
let sig = Signature::new(&keypair.sign(&msg).as_ref());
|
|
||||||
let vote_tx = Transaction {
|
let vote_tx = Transaction {
|
||||||
signatures: vec![sig],
|
signatures: vec![sig],
|
||||||
account_keys: tx.account_keys,
|
account_keys: tx.account_keys,
|
||||||
@ -661,7 +660,7 @@ mod tests {
|
|||||||
.for_each(move |_| {
|
.for_each(move |_| {
|
||||||
let keypair = Keypair::new();
|
let keypair = Keypair::new();
|
||||||
let hash = hasher.clone().result();
|
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);
|
let ix = get_identity_index_from_signature(&signature);
|
||||||
hist[ix].fetch_add(1, Ordering::Relaxed);
|
hist[ix].fetch_add(1, Ordering::Relaxed);
|
||||||
});
|
});
|
||||||
|
@ -86,7 +86,7 @@ pub struct VoteSignerProxy {
|
|||||||
impl VoteSignerProxy {
|
impl VoteSignerProxy {
|
||||||
pub fn new(keypair: &Arc<Keypair>, signer: Box<VoteSigner + Send + Sync>) -> Self {
|
pub fn new(keypair: &Arc<Keypair>, signer: Box<VoteSigner + Send + Sync>) -> Self {
|
||||||
let msg = "Registering a new node";
|
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
|
let vote_account = signer
|
||||||
.register(keypair.pubkey(), &sig, msg.as_bytes())
|
.register(keypair.pubkey(), &sig, msg.as_bytes())
|
||||||
.unwrap();
|
.unwrap();
|
||||||
@ -161,9 +161,8 @@ impl VoteSignerProxy {
|
|||||||
pub fn new_signed_vote_transaction(&self, last_id: &Hash, tick_height: u64) -> Transaction {
|
pub fn new_signed_vote_transaction(&self, last_id: &Hash, tick_height: u64) -> Transaction {
|
||||||
let vote = Vote { tick_height };
|
let vote = Vote { tick_height };
|
||||||
let tx = Transaction::vote_new(&self.vote_account, vote, *last_id, 0);
|
let tx = Transaction::vote_new(&self.vote_account, vote, *last_id, 0);
|
||||||
|
let msg = tx.message();
|
||||||
let msg = tx.get_sign_data();
|
let sig = self.keypair.sign_message(&msg);
|
||||||
let sig = Signature::new(&self.keypair.sign(&msg).as_ref());
|
|
||||||
|
|
||||||
let keypair = self.keypair.clone();
|
let keypair = self.keypair.clone();
|
||||||
let vote_signature = self.signer.sign(keypair.pubkey(), &sig, &msg).unwrap();
|
let vote_signature = self.signer.sign(keypair.pubkey(), &sig, &msg).unwrap();
|
||||||
|
@ -156,10 +156,7 @@ impl VoteSigner for LocalVoteSigner {
|
|||||||
fn sign(&self, pubkey: Pubkey, sig: &Signature, msg: &[u8]) -> Result<Signature> {
|
fn sign(&self, pubkey: Pubkey, sig: &Signature, msg: &[u8]) -> Result<Signature> {
|
||||||
verify_signature(&sig, &pubkey, &msg)?;
|
verify_signature(&sig, &pubkey, &msg)?;
|
||||||
match self.nodes.read().unwrap().get(&pubkey) {
|
match self.nodes.read().unwrap().get(&pubkey) {
|
||||||
Some(voting_keypair) => {
|
Some(voting_keypair) => Ok(voting_keypair.sign_message(&msg)),
|
||||||
let sig = Signature::new(&voting_keypair.sign(&msg).as_ref());
|
|
||||||
Ok(sig)
|
|
||||||
}
|
|
||||||
None => Err(Error::invalid_request()),
|
None => Err(Error::invalid_request()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -201,7 +198,7 @@ mod tests {
|
|||||||
let node_keypair = Keypair::new();
|
let node_keypair = Keypair::new();
|
||||||
let node_pubkey = node_keypair.pubkey();
|
let node_pubkey = node_keypair.pubkey();
|
||||||
let msg = "This is a test";
|
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!({
|
let req = json!({
|
||||||
"jsonrpc": "2.0",
|
"jsonrpc": "2.0",
|
||||||
"id": 1,
|
"id": 1,
|
||||||
@ -238,7 +235,7 @@ mod tests {
|
|||||||
let node_pubkey = node_keypair.pubkey();
|
let node_pubkey = node_keypair.pubkey();
|
||||||
let msg = "This is a test";
|
let msg = "This is a test";
|
||||||
let msg1 = "This is a Test1";
|
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!({
|
let req = json!({
|
||||||
"jsonrpc": "2.0",
|
"jsonrpc": "2.0",
|
||||||
"id": 1,
|
"id": 1,
|
||||||
@ -269,7 +266,7 @@ mod tests {
|
|||||||
let node_keypair = Keypair::new();
|
let node_keypair = Keypair::new();
|
||||||
let node_pubkey = node_keypair.pubkey();
|
let node_pubkey = node_keypair.pubkey();
|
||||||
let msg = "This is a test";
|
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!({
|
let req = json!({
|
||||||
"jsonrpc": "2.0",
|
"jsonrpc": "2.0",
|
||||||
"id": 1,
|
"id": 1,
|
||||||
@ -301,7 +298,7 @@ mod tests {
|
|||||||
let node_pubkey = node_keypair.pubkey();
|
let node_pubkey = node_keypair.pubkey();
|
||||||
let msg = "This is a test";
|
let msg = "This is a test";
|
||||||
let msg1 = "This is a Test1";
|
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!({
|
let req = json!({
|
||||||
"jsonrpc": "2.0",
|
"jsonrpc": "2.0",
|
||||||
"id": 1,
|
"id": 1,
|
||||||
@ -332,7 +329,7 @@ mod tests {
|
|||||||
let node_keypair = Keypair::new();
|
let node_keypair = Keypair::new();
|
||||||
let node_pubkey = node_keypair.pubkey();
|
let node_pubkey = node_keypair.pubkey();
|
||||||
let msg = "This is a test";
|
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!({
|
let req = json!({
|
||||||
"jsonrpc": "2.0",
|
"jsonrpc": "2.0",
|
||||||
@ -396,7 +393,7 @@ mod tests {
|
|||||||
let node_keypair = Keypair::new();
|
let node_keypair = Keypair::new();
|
||||||
let node_pubkey = node_keypair.pubkey();
|
let node_pubkey = node_keypair.pubkey();
|
||||||
let msg = "This is a test";
|
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!({
|
let req = json!({
|
||||||
"jsonrpc": "2.0",
|
"jsonrpc": "2.0",
|
||||||
"id": 1,
|
"id": 1,
|
||||||
@ -427,7 +424,7 @@ mod tests {
|
|||||||
let node_keypair = Keypair::new();
|
let node_keypair = Keypair::new();
|
||||||
let node_pubkey = node_keypair.pubkey();
|
let node_pubkey = node_keypair.pubkey();
|
||||||
let msg = "This is a test";
|
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!({
|
let req = json!({
|
||||||
"jsonrpc": "2.0",
|
"jsonrpc": "2.0",
|
||||||
@ -476,7 +473,7 @@ mod tests {
|
|||||||
let node_pubkey = node_keypair.pubkey();
|
let node_pubkey = node_keypair.pubkey();
|
||||||
let msg = "This is a test";
|
let msg = "This is a test";
|
||||||
let msg1 = "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!({
|
let req = json!({
|
||||||
"jsonrpc": "2.0",
|
"jsonrpc": "2.0",
|
||||||
|
Reference in New Issue
Block a user