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

Centralized Signed Blobs #604

Closed
wants to merge 18 commits into from
Closed
Show file tree
Hide file tree
Changes from 3 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 Cargo.lock

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

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -292,7 +292,7 @@ rustix = "0.38.34"
paste = "1.0.15"
uuid = { version = "1.10.0", features = ["v4"] }
blake-3 = "1.4.0"
ecdsa = { version = "0.16.9", features = ["signing", "verifying", "der"] }
ecdsa = { version = "0.16.9", features = ["signing", "verifying", "der", "pem", "pkcs8"] }

# trying to pin diesel
# diesel = "=2.1.1"
Expand Down
1 change: 1 addition & 0 deletions protocol-units/bridge/contracts/lib/forge-std
Submodule forge-std added at 5a802d
1 change: 1 addition & 0 deletions protocol-units/bridge/contracts/lib/openzeppelin-contracts
Submodule openzeppelin-contracts added at 530179
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ where
pub fn new(
celestia_client: Arc<Client>,
celestia_namespace: Namespace,
known_signers_sec1_bytes: HashSet<Vec<u8>>,
known_signers_sec1_bytes: HashSet<String>,
) -> Self {
Self {
celestia: CelestiaVerifier::new(celestia_client, celestia_namespace),
Expand Down
11 changes: 6 additions & 5 deletions protocol-units/da/m1/light-node-verifier/src/signed/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,8 @@ where
FieldBytesSize<C>: ModulusSize,
{
pub inner_verifier: Verifier<C>,
pub known_signers_sec1_bytes: HashSet<Vec<u8>>,
/// The set of known signers in sec1 bytes hex format.
pub known_signers_sec1_bytes_hex: HashSet<String>,
}

impl<C> InKnownSignersVerifier<C>
Expand All @@ -78,8 +79,8 @@ where
AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C> + VerifyPrimitive<C>,
FieldBytesSize<C>: ModulusSize,
{
pub fn new(known_signers_sec1_bytes: HashSet<Vec<u8>>) -> Self {
Self { inner_verifier: Verifier::new(), known_signers_sec1_bytes }
pub fn new(known_signers_sec1_bytes_hex: HashSet<String>) -> Self {
Self { inner_verifier: Verifier::new(), known_signers_sec1_bytes_hex }
}
}

Expand All @@ -95,8 +96,8 @@ where
async fn verify(&self, blob: InnerBlob, height: u64) -> Result<Verified<InnerBlob>, Error> {
let inner_blob = self.inner_verifier.verify(blob, height).await?;

let signer = inner_blob.inner().signer();
if !self.known_signers_sec1_bytes.contains(signer) {
let signer = inner_blob.inner().signer_hex();
if !self.known_signers_sec1_bytes_hex.contains(&signer) {
return Err(Error::Validation("signer not in known signers".to_string()));
}

Expand Down
4 changes: 3 additions & 1 deletion protocol-units/da/m1/light-node/src/v1/passthrough.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,9 @@ where
let client = Arc::new(config.connect_celestia().await?);

let signing_key_str = config.da_signing_key();
let signing_key = SigningKey::from_bytes(signing_key_str.as_bytes().into())
let hex_bytes = hex::decode(signing_key_str)?;

let signing_key = SigningKey::from_bytes(hex_bytes.as_slice().try_into()?)
.map_err(|e| anyhow::anyhow!("Failed to create signing key: {}", e))?;

Ok(Self {
Expand Down
1 change: 1 addition & 0 deletions protocol-units/da/m1/util/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ zstd = { workspace = true }
bcs = { workspace = true }
ecdsa = { workspace = true, features = [ "signing", "verifying", "der"] }
k256 = { workspace = true }
rand = { version = "0.8.5" }

[dev-dependencies]
tempfile = { workspace = true }
Expand Down
23 changes: 0 additions & 23 deletions protocol-units/da/m1/util/src/config/common.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
use alloy::signers::local::PrivateKeySigner;
use celestia_types::nmt::Namespace;
/*use ecdsa::{
elliptic_curve::{
Expand All @@ -13,8 +12,6 @@ use celestia_types::nmt::Namespace;
SignatureSize,
};*/
use godfig::env_default;
use std::collections::HashSet;
use std::env;

// The default hostname for the Celestia RPC
env_default!(
Expand Down Expand Up @@ -140,23 +137,3 @@ pub fn default_celestia_bridge_replace_args() -> Vec<String> {

// Whether to use replace args for Celestia bridge
env_default!(default_m1_da_light_node_is_initial, "M1_DA_LIGHT_NODE_IS_INITIAL", bool, true);

/// The default da signing private key
pub fn default_da_signing_private_key() -> String {
let random_wallet = PrivateKeySigner::random();
let random_wallet_string = random_wallet.to_bytes().to_string();
env::var("DA_SIGNING_PRIVATE_KEY").unwrap_or(random_wallet_string)
}

pub fn default_da_signers_sec1_keys() -> HashSet<Vec<u8>> {
match std::env::var("DA_SIGNERS_SEC1_KEYS") {
Ok(val) => val.split(',').map(|s| s.as_bytes().to_vec()).collect(),
Err(_) => {
// always trust yourself
let mut set = HashSet::new();
let signer = default_da_signing_private_key();
set.insert(signer.as_bytes().to_vec());
set
}
}
}
91 changes: 82 additions & 9 deletions protocol-units/da/m1/util/src/config/local/m1_da_light_node.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,90 @@
use crate::config::common::{
default_celestia_rpc_connection_hostname, default_celestia_rpc_connection_port,
default_celestia_websocket_connection_hostname, default_celestia_websocket_connection_port,
default_da_signers_sec1_keys, default_da_signing_private_key,
default_m1_da_light_node_connection_hostname, default_m1_da_light_node_connection_port,
default_m1_da_light_node_listen_hostname, default_m1_da_light_node_listen_port,
};
use ecdsa::SigningKey;
use k256::Secp256k1;
use serde::{Deserialize, Serialize};
use std::collections::HashSet;

#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub struct DaSigners {
pub da_signing_private_key_hex: String,
pub da_signers_public_keys_hex: HashSet<String>,
}

/// The default da signing private key
pub fn default_da_signing_private_key() -> SigningKey<Secp256k1> {
match std::env::var("DA_SIGNING_PRIVATE_KEY") {
Ok(val) => {
// decode from hex to bytes 32
let hex_bytes = hex::decode(val).expect("Invalid hex string");

// todo: maybe remove the unwrap and catch for a random signing key
let signing_key_bytes: &[u8; 32] =
hex_bytes.as_slice().try_into().expect("Slice with incorrect length");
SigningKey::from_bytes(signing_key_bytes.into()).unwrap()
}
Err(_) => SigningKey::random(
// rand_core
&mut rand::rngs::OsRng,
),
}
}

pub fn default_da_signers_sec1_keys() -> HashSet<String> {
match std::env::var("DA_SIGNERS_SEC1_KEYS") {
Ok(val) => val.split(',').map(|s| s.to_string()).collect(),
Err(_) => HashSet::new(),
}
}

pub fn default_da_signers() -> DaSigners {
let da_signer = default_da_signing_private_key();

// always trust yourself
let mut trusted_signers = HashSet::new();
let sec1_hex = hex::encode(da_signer.verifying_key().to_sec1_bytes().to_vec());
trusted_signers.insert(sec1_hex);

// add the other specified signers
let additional_signers = default_da_signers_sec1_keys();
trusted_signers.extend(additional_signers);

DaSigners {
da_signing_private_key_hex: hex::encode(da_signer.to_bytes().as_slice()),
da_signers_public_keys_hex: trusted_signers,
}
}

#[cfg(test)]
pub mod signers_serialization_test {

use super::*;

#[test]
fn test_signing_key() -> Result<(), anyhow::Error> {
let signing_key = SigningKey::<Secp256k1>::random(
// rand_core
&mut rand::rngs::OsRng,
);

let signing_bytes = signing_key.to_bytes();

let signing_key_fixed_bytes: &[u8; 32] =
signing_bytes.as_slice().try_into().expect("Slice with incorrect length");

let from_bytes =
SigningKey::<Secp256k1>::from_bytes(&signing_key_fixed_bytes.clone().into())?;

assert_eq!(signing_key, from_bytes);

Ok(())
}
}

/// The inner configuration for the local Celestia Appd Runner
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub struct Config {
Expand Down Expand Up @@ -43,12 +120,9 @@ pub struct Config {
#[serde(default = "default_m1_da_light_node_connection_port")]
pub m1_da_light_node_connection_port: u16,

/// The private key for signing DA messages
#[serde(default = "default_da_signing_private_key")]
pub da_signing_private_key: String,

#[serde(default = "default_da_signers_sec1_keys")]
pub da_signers_sec1_keys: HashSet<Vec<u8>>,
/// The DA signers
#[serde(default = "default_da_signers")]
pub da_signers: DaSigners,
}

impl Default for Config {
Expand All @@ -63,8 +137,7 @@ impl Default for Config {
m1_da_light_node_listen_port: default_m1_da_light_node_listen_port(),
m1_da_light_node_connection_hostname: default_m1_da_light_node_connection_hostname(),
m1_da_light_node_connection_port: default_m1_da_light_node_connection_port(),
da_signing_private_key: default_da_signing_private_key(),
da_signers_sec1_keys: default_da_signers_sec1_keys(),
da_signers: default_da_signers(),
}
}
}
26 changes: 19 additions & 7 deletions protocol-units/da/m1/util/src/config/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -180,18 +180,30 @@ impl Config {
/// Gets the da signing key as a string
pub fn da_signing_key(&self) -> String {
match self {
Config::Local(local) => local.m1_da_light_node.da_signing_private_key.clone(),
Config::Arabica(local) => local.m1_da_light_node.da_signing_private_key.clone(),
Config::Mocha(local) => local.m1_da_light_node.da_signing_private_key.clone(),
Config::Local(local) => {
local.m1_da_light_node.da_signers.da_signing_private_key_hex.clone()
}
Config::Arabica(local) => {
local.m1_da_light_node.da_signers.da_signing_private_key_hex.clone()
}
Config::Mocha(local) => {
local.m1_da_light_node.da_signers.da_signing_private_key_hex.clone()
}
}
}

/// Gets the da signers sec1 keys
pub fn da_signers_sec1_keys(&self) -> HashSet<Vec<u8>> {
pub fn da_signers_sec1_keys(&self) -> HashSet<String> {
match self {
Config::Local(local) => local.m1_da_light_node.da_signers_sec1_keys.clone(),
Config::Arabica(local) => local.m1_da_light_node.da_signers_sec1_keys.clone(),
Config::Mocha(local) => local.m1_da_light_node.da_signers_sec1_keys.clone(),
Config::Local(local) => {
local.m1_da_light_node.da_signers.da_signers_public_keys_hex.clone()
}
Config::Arabica(local) => {
local.m1_da_light_node.da_signers.da_signers_public_keys_hex.clone()
}
Config::Mocha(local) => {
local.m1_da_light_node.da_signers.da_signers_public_keys_hex.clone()
}
}
}

Expand Down
9 changes: 6 additions & 3 deletions protocol-units/da/m1/util/src/inner_blob.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
use ecdsa::signature::digest::Digest;
use ecdsa::{
elliptic_curve::{
generic_array::ArrayLength,
Expand All @@ -9,7 +8,7 @@ use ecdsa::{
AffinePoint, CurveArithmetic, FieldBytesSize, PrimeCurve, Scalar,
},
hazmat::{DigestPrimitive, SignPrimitive, VerifyPrimitive},
signature::DigestVerifier,
signature::{digest::Digest, DigestVerifier},
SignatureSize, SigningKey, VerifyingKey,
};
use serde::{Deserialize, Serialize};
Expand All @@ -33,7 +32,7 @@ impl InnerSignedBlobV1Data {
C: PrimeCurve + CurveArithmetic + DigestPrimitive + PointCompression,
Scalar<C>: Invert<Output = CtOption<Scalar<C>>> + SignPrimitive<C>,
SignatureSize<C>: ArrayLength<u8>,
AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C>,
AffinePoint<C>: FromEncodedPoint<C> + ToEncodedPoint<C> + VerifyPrimitive<C>,
FieldBytesSize<C>: ModulusSize,
{
let mut hasher = C::Digest::new();
Expand Down Expand Up @@ -131,6 +130,10 @@ impl InnerBlob {
}
}

pub fn signer_hex(&self) -> String {
hex::encode(self.signer())
}

pub fn id(&self) -> &[u8] {
match self {
InnerBlob::SignedV1(inner) => inner.id.as_slice(),
Expand Down
2 changes: 1 addition & 1 deletion protocol-units/settlement/mcr/runner/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ async fn main() -> Result<(), anyhow::Error> {

// get the config file
let dot_movement = dot_movement::DotMovement::try_from_env()?;
let mut config_file = dot_movement.try_get_or_create_config_file().await?;
let config_file = dot_movement.try_get_or_create_config_file().await?;

// get a matching godfig object
let godfig: Godfig<Config, ConfigFile> =
Expand Down
Loading