Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore(code/starknet): Change signature scheme from ECDSA to Ed25519 #871

Merged
merged 4 commits into from
Feb 21, 2025
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions code/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 2 additions & 5 deletions code/crates/network/test/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use core::fmt;
use std::time::{Duration, SystemTime, UNIX_EPOCH};

use libp2p_identity::{ecdsa, PeerId};
use libp2p_identity::PeerId;
use malachitebft_config::TransportProtocol;
use malachitebft_metrics::SharedRegistry;
use malachitebft_network::{
Expand Down Expand Up @@ -139,10 +139,7 @@ impl<const N: usize> Test<N> {
);
std::array::from_fn(|_| {
let privkey = PrivateKey::generate(&mut rng);
let pk_bytes = privkey.inner().to_bytes_be();
let secret_key = ecdsa::SecretKey::try_from_bytes(pk_bytes).unwrap();
let ecdsa_keypair = ecdsa::Keypair::from(secret_key);
Keypair::from(ecdsa_keypair)
Keypair::ed25519_from_bytes(privkey.inner().to_bytes()).unwrap()
})
}

Expand Down
6 changes: 5 additions & 1 deletion code/crates/signing-ed25519/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ impl Keypair for PrivateKey {
}
}

#[derive(Copy, Clone, Debug, PartialEq, Eq)]
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "serde", serde(transparent))]
pub struct PublicKey(
Expand All @@ -174,6 +174,10 @@ impl PublicKey {
self.0.as_bytes()
}

pub fn from_bytes(bytes: [u8; 32]) -> Self {
Self(ed25519_consensus::VerificationKey::try_from(bytes).unwrap())
}

pub fn verify(&self, msg: &[u8], signature: &Signature) -> Result<(), signature::Error> {
self.0
.verify(signature.inner(), msg)
Expand Down
21 changes: 16 additions & 5 deletions code/crates/starknet/host/src/codec.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use bytes::Bytes;
use malachitebft_app::streaming::StreamId;
use malachitebft_starknet_p2p_types::Signature;
use malachitebft_starknet_p2p_types::{Felt, FeltExt, Signature};
use prost::Message;

use malachitebft_codec::Codec;
Expand Down Expand Up @@ -350,7 +350,7 @@ pub fn decode_consensus_message(
proto: proto::Vote,
) -> Result<SignedConsensusMsg<MockContext>, ProtoError> {
let vote = Vote::from_proto(proto)?;
let signature = p2p::Signature::dummy();
let signature = p2p::Signature::test();

Ok(SignedConsensusMsg::Vote(SignedVote::new(vote, signature)))
}
Expand Down Expand Up @@ -418,6 +418,17 @@ where
}
}

pub fn encode_signature(_signature: &Signature) -> Result<proto::ConsensusSignature, ProtoError> {
Ok(proto::ConsensusSignature {
r: Some(Felt::ONE.to_proto()?),
s: Some(Felt::ONE.to_proto()?),
})
}

pub fn decode_signature(_signature: proto::ConsensusSignature) -> Result<Signature, ProtoError> {
Ok(Signature::test())
}

pub fn decode_aggregated_signature(
signature: proto::sync::AggregatedSignature,
) -> Result<AggregatedSignature<MockContext>, ProtoError> {
Expand All @@ -430,7 +441,7 @@ pub fn decode_aggregated_signature(
.ok_or_else(|| {
ProtoError::missing_field::<proto::sync::CommitSignature>("signature")
})
.and_then(p2p::Signature::from_proto)?;
.and_then(decode_signature)?;

let address = s
.validator_address
Expand All @@ -454,7 +465,7 @@ pub fn encode_aggregate_signature(
.iter()
.map(|s| {
let validator_address = s.address.to_proto()?;
let signature = s.signature.to_proto()?;
let signature = encode_signature(&s.signature)?;

Ok(proto::sync::CommitSignature {
validator_address: Some(validator_address),
Expand Down Expand Up @@ -601,7 +612,7 @@ pub(crate) fn encode_vote(vote: &SignedVote<MockContext>) -> Result<proto::Vote,
}

pub(crate) fn decode_vote(msg: proto::Vote) -> Option<SignedVote<MockContext>> {
let signature = Signature::dummy();
let signature = Signature::test();
let vote = Vote::from_proto(msg).ok()?;
Some(SignedVote::new(vote, signature))
}
8 changes: 5 additions & 3 deletions code/crates/starknet/host/src/host/starknet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ impl Host for StarknetHost {
height,
round,
self.address,
self.private_key,
self.private_key.clone(),
self.params,
deadline,
self.mempool.clone(),
Expand Down Expand Up @@ -151,7 +151,7 @@ impl Host for StarknetHost {

/// Sign a message hash
async fn sign(&self, message: Self::MessageHash) -> Self::Signature {
self.private_key.sign(&message.as_felt())
self.private_key.sign(message.as_bytes().as_slice())
}

/// Validates the signature field of a message. If None returns false.
Expand All @@ -161,7 +161,9 @@ impl Host for StarknetHost {
signature: &Self::Signature,
public_key: &Self::PublicKey,
) -> bool {
public_key.verify(&hash.as_felt(), signature)
public_key
.verify(hash.as_bytes().as_slice(), signature)
.is_ok()
}

/// Update the Context about which decision has been made. It is responsible for pinging any
Expand Down
14 changes: 5 additions & 9 deletions code/crates/starknet/host/src/node.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
use std::path::PathBuf;

use libp2p_identity::ecdsa;
use ractor::async_trait;
use rand::{CryptoRng, RngCore};
use serde::{Deserialize, Serialize};
Expand All @@ -12,7 +11,7 @@ use malachitebft_app::{Node, NodeHandle};
use malachitebft_config::Config;
use malachitebft_core_types::VotingPower;
use malachitebft_engine::node::NodeRef;
use malachitebft_starknet_p2p_types::EcdsaProvider;
use malachitebft_starknet_p2p_types::Ed25519Provider;

use crate::spawn::spawn_node_actor;
use crate::types::{Address, Height, MockContext, PrivateKey, PublicKey, Validator, ValidatorSet};
Expand Down Expand Up @@ -83,7 +82,7 @@ impl Node for StarknetNode {
type Context = MockContext;
type Genesis = Genesis;
type PrivateKeyFile = PrivateKeyFile;
type SigningProvider = EcdsaProvider;
type SigningProvider = Ed25519Provider;
type NodeHandle = Handle;

fn get_home_dir(&self) -> PathBuf {
Expand All @@ -106,10 +105,7 @@ impl Node for StarknetNode {
}

fn get_keypair(&self, pk: PrivateKey) -> Keypair {
let pk_bytes = pk.inner().to_bytes_be();
let secret_key = ecdsa::SecretKey::try_from_bytes(pk_bytes).unwrap();
let ecdsa_keypair = ecdsa::Keypair::from(secret_key);
Keypair::from(ecdsa_keypair)
Keypair::ed25519_from_bytes(pk.inner().to_bytes()).unwrap()
}

fn load_private_key(&self, file: Self::PrivateKeyFile) -> PrivateKey {
Expand All @@ -126,7 +122,7 @@ impl Node for StarknetNode {
}

fn get_signing_provider(&self, private_key: PrivateKey) -> Self::SigningProvider {
EcdsaProvider::new(private_key)
Self::SigningProvider::new(private_key)
}

fn load_genesis(&self) -> std::io::Result<Self::Genesis> {
Expand Down Expand Up @@ -213,7 +209,7 @@ fn test_starknet_node() {
file::save_priv_validator_key(
&node,
&node.private_key_file(),
&PrivateKeyFile::from(priv_keys[0]),
&PrivateKeyFile::from(priv_keys[0].clone()),
)
.unwrap();

Expand Down
23 changes: 13 additions & 10 deletions code/crates/starknet/host/src/spawn.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
use std::path::{Path, PathBuf};
use std::time::Duration;

use libp2p_identity::ecdsa;
use tokio::task::JoinHandle;
use tracing::warn;

Expand All @@ -18,7 +17,7 @@ use malachitebft_engine::util::events::TxEvent;
use malachitebft_engine::wal::{Wal, WalRef};
use malachitebft_metrics::{Metrics, SharedRegistry};
use malachitebft_network::Keypair;
use malachitebft_starknet_p2p_types::EcdsaProvider;
use malachitebft_starknet_p2p_types::Ed25519Provider;
use malachitebft_sync as sync;
use malachitebft_test_mempool::Config as MempoolNetworkConfig;

Expand Down Expand Up @@ -46,7 +45,7 @@ pub async fn spawn_node_actor(
let registry = SharedRegistry::global().with_moniker(cfg.moniker.as_str());
let metrics = Metrics::register(&registry);
let address = Address::from_public_key(private_key.public_key());
let signing_provider = EcdsaProvider::new(private_key);
let signing_provider = Ed25519Provider::new(private_key.clone());

// Spawn mempool and its gossip layer
let mempool_network = spawn_mempool_network_actor(&cfg, &private_key, &registry, &span).await;
Expand Down Expand Up @@ -156,7 +155,7 @@ async fn spawn_consensus_actor(
address: Address,
ctx: MockContext,
cfg: NodeConfig,
signing_provider: EcdsaProvider,
signing_provider: Ed25519Provider,
network: NetworkRef<MockContext>,
host: HostRef<MockContext>,
wal: WalRef<MockContext>,
Expand Down Expand Up @@ -256,11 +255,15 @@ async fn spawn_network_actor(
.unwrap()
}

fn make_keypair(private_key: &PrivateKey) -> Keypair {
let pk_bytes = private_key.inner().to_bytes_be();
let secret_key = ecdsa::SecretKey::try_from_bytes(pk_bytes).unwrap();
let ecdsa_keypair = ecdsa::Keypair::from(secret_key);
Keypair::from(ecdsa_keypair)
// fn make_keypair(private_key: &PrivateKey) -> Keypair {
// let pk_bytes = private_key.inner().to_bytes_be();
// let secret_key = ecdsa::SecretKey::try_from_bytes(pk_bytes).unwrap();
// let ecdsa_keypair = ecdsa::Keypair::from(secret_key);
// Keypair::from(ecdsa_keypair)
// }

fn make_keypair(pk: &PrivateKey) -> Keypair {
Keypair::ed25519_from_bytes(pk.inner().to_bytes()).unwrap()
}

async fn spawn_mempool_actor(
Expand Down Expand Up @@ -335,7 +338,7 @@ async fn spawn_host_actor(
mock_params,
mempool.clone(),
*address,
*private_key,
private_key.clone(),
initial_validator_set.clone(),
);

Expand Down
1 change: 1 addition & 0 deletions code/crates/starknet/p2p-types/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ publish = false
malachitebft-core-types.workspace = true
malachitebft-proto.workspace = true
malachitebft-starknet-p2p-proto.workspace = true
malachitebft-signing-ed25519 = { workspace = true, features = ["serde", "rand"] }

starknet-core.workspace = true
starknet-crypto.workspace = true
Expand Down
7 changes: 5 additions & 2 deletions code/crates/starknet/p2p-types/src/address.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,10 @@ impl Address {
impl fmt::Display for Address {
#[cfg_attr(coverage_nightly, coverage(off))]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.0.fmt(f)
for byte in self.0.as_bytes().iter() {
write!(f, "{:02X}", byte)?;
}
Ok(())
}
}

Expand Down Expand Up @@ -57,7 +60,7 @@ impl Protobuf for Address {

fn to_proto(&self) -> Result<Self::Proto, ProtoError> {
Ok(p2p_proto::Address {
elements: Bytes::copy_from_slice(&self.0.as_bytes()),
elements: Bytes::copy_from_slice(self.0.as_bytes().as_slice()),
})
}
}
6 changes: 4 additions & 2 deletions code/crates/starknet/p2p-types/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ use bytes::Bytes;

use malachitebft_core_types::{Context, NilOrVal, Round, ValidatorSet as _};

use crate::{Address, Ecdsa, Hash, Height, Proposal, ProposalPart, Validator, ValidatorSet, Vote};
use crate::{
Address, Ed25519, Hash, Height, Proposal, ProposalPart, Validator, ValidatorSet, Vote,
};

mod impls;

Expand All @@ -25,7 +27,7 @@ impl Context for MockContext {
type Value = Hash;
type Vote = Vote;
type Extension = Bytes;
type SigningScheme = Ecdsa;
type SigningScheme = Ed25519;

fn select_proposer<'a>(
&self,
Expand Down
4 changes: 2 additions & 2 deletions code/crates/starknet/p2p-types/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ mod context;
pub use context::MockContext;

mod felt;
pub use felt::Felt;
pub use felt::{Felt, FeltExt};

mod address;
pub use address::Address;
Expand Down Expand Up @@ -49,4 +49,4 @@ mod streaming;
pub use streaming::{StreamContent, StreamMessage};

mod signing;
pub use signing::{Ecdsa, EcdsaProvider, PrivateKey, PublicKey, Signature};
pub use signing::{Ed25519, Ed25519Provider, PrivateKey, PublicKey, Signature};
Loading
Loading