Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: sigp/enr
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: v0.9.1
Choose a base ref
...
head repository: sigp/enr
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: master
Choose a head ref
Loading
Showing with 1,126 additions and 543 deletions.
  1. +66 −51 .github/workflows/build.yml
  2. +24 −1 .gitignore
  3. +18 −14 Cargo.toml
  4. +17 −21 README.md
  5. +65 −38 src/builder.rs
  6. +22 −7 src/error.rs
  7. +3 −5 src/keys/combined.rs
  8. +4 −4 src/keys/ed25519.rs
  9. +4 −4 src/keys/k256_key.rs
  10. +1 −1 src/keys/mod.rs
  11. +6 −8 src/keys/rust_secp256k1.rs
  12. +864 −383 src/lib.rs
  13. +30 −4 src/node_id.rs
  14. +2 −2 tests/ecdsa/rust_secp256k1.rs
117 changes: 66 additions & 51 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
@@ -7,66 +7,81 @@ on:
pull_request:

jobs:
cargo-fmt:
audit:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Get latest version of stable rust
run: rustup update stable
- name: Check formatting with cargofmt
run: cargo fmt -- --check
cargo-clippy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Get latest version of stable rust
run: rustup update stable
- name: Check for lint warnings
run: cargo clippy --all-features -- -D warnings
release-tests-ubuntu:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- uses: taiki-e/install-action@cargo-audit
- name:
Run cargo audit to identify known security vulnerabilities reported to the RustSec
Advisory Database
run: cargo audit

test:
name: test ${{ matrix.flags }}
runs-on: ubuntu-latest
needs: cargo-fmt
strategy:
fail-fast: false
matrix:
flags: ["--no-default-features", "", "--features ed25519", "--features rust-secp256k1"]
steps:
- uses: actions/checkout@v2
- name: Get latest version of stable rust
run: rustup update stable
- name: Run tests in release
run: cargo test --all --release --tests
release-tests-ubuntu-all-features:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
with:
cache-on-failure: true
- name: test
run: cargo test ${{ matrix.flags }}

feature-checks:
runs-on: ubuntu-latest
needs: cargo-fmt
timeout-minutes: 30
steps:
- uses: actions/checkout@v2
- name: Get latest version of stable rust
run: rustup update stable
- name: Run tests in release
run: cargo test --all --release --all-features
release-tests-ubuntu-ed25519:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- uses: taiki-e/install-action@cargo-hack
- uses: Swatinem/rust-cache@v2
with:
cache-on-failure: true
- name: cargo hack
run: cargo hack check --feature-powerset --depth 2

clippy:
runs-on: ubuntu-latest
needs: cargo-fmt
timeout-minutes: 30
steps:
- uses: actions/checkout@v2
- name: Get latest version of stable rust
run: rustup update stable
- name: Run tests in release
run: cargo test --all --release --features "ed25519" --tests
cargo-audit:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@master
with:
toolchain: stable
components: clippy
- uses: Swatinem/rust-cache@v2
with:
cache-on-failure: true
- run: cargo clippy --workspace --all-targets --all-features
env:
RUSTFLAGS: -Dwarnings

docs:
runs-on: ubuntu-latest
needs: cargo-fmt
timeout-minutes: 30
steps:
- uses: actions/checkout@v2
- name: Get latest version of stable rust
run: rustup update stable
- name: Get latest cargo audit
run: cargo install --force cargo-audit
- name: Run cargo audit to identify known security vulnerabilities reported to the RustSec Advisory Database
run: cargo audit
check-rustdoc-links:
name: Check rustdoc intra-doc links
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@nightly
- uses: Swatinem/rust-cache@v2
with:
cache-on-failure: true
- run: cargo doc --workspace --all-features --no-deps --document-private-items
env:
RUSTDOCFLAGS: "--cfg docsrs -D warnings"

fmt:
runs-on: ubuntu-latest
container:
image: rust
timeout-minutes: 30
steps:
- uses: actions/checkout@v2
- name: Check rustdoc links
run: RUSTDOCFLAGS="--deny broken_intra_doc_links" cargo doc --verbose --workspace --no-deps --document-private-items
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@nightly
with:
components: rustfmt
- run: cargo fmt --all --check
25 changes: 24 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,25 @@
# Generated by Cargo
# will have compiled files and executables
debug/
target/

# This project does not check in Cargo.lock
Cargo.lock
target

# These are backup files generated by rustfmt
**/*.rs.bk

# MSVC Windows builds of rustc generate these, which store debugging information
*.pdb

# Generated by Intellij-based IDEs.
.idea

# Generated by MacOS
.DS_Store

# VSCode
.vscode

# Rust bug report
rustc-ice-*
32 changes: 18 additions & 14 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
[package]
name = "enr"
authors = ["Age Manning <Age@AgeManning.com>"]
edition = "2018"
version = "0.9.1"
edition = "2021"
version = "0.13.0"
description = "Rust implementation of Ethereum Node Record (ENR) EIP778"
readme = "./README.md"
keywords = ["ethereum", "enr", "record", "EIP778", "node"]
@@ -12,29 +12,33 @@ license = "MIT"
exclude = [".gitignore", ".github/*"]

[dependencies]
base64 = "0.21.0"
alloy-rlp = "0.3.9"
base64 = "0.22"
bytes = "1"
hex = { version = "0.4.2" }
log = "0.4.8"
hex = "0.4"
log = "0.4"
rand = "0.8"
rlp = "0.5"
zeroize = "1.1.0"
zeroize = "1.8"
sha3 = "0.10"
k256 = { version = "0.13", features = ["ecdsa"], optional = true }
serde = { version = "1.0.110", features = ["derive"], optional = true }
ed25519-dalek = { version = "2.0.0", optional = true, features = ["rand_core"] }
secp256k1 = { version = "0.27", optional = true, default-features = false, features = [
serde = { version = "1.0", features = ["derive"], optional = true }
ed25519-dalek = { version = "2.1", optional = true, features = ["rand_core"] }
secp256k1 = { version = "0.30", optional = true, default-features = false, features = [
"global-context",
] }

[dev-dependencies]
secp256k1 = { features = ["rand-std"], version = "0.27" }
serde_json = { version = "1.0.95" }
alloy-rlp = { version = "0.3", features = ["derive"] }
secp256k1 = { version = "0.30", features = ["rand"] }
serde_json = "1.0"

[features]
default = ["serde", "k256"]
ed25519 = ["ed25519-dalek"]
rust-secp256k1 = ["secp256k1"]
serde = ["dep:serde"]
k256 = ["dep:k256"]
ed25519 = ["dep:ed25519-dalek"]
secp256k1 = ["rust-secp256k1"]
rust-secp256k1 = ["dep:secp256k1"]

[lib]
name = "enr"
38 changes: 17 additions & 21 deletions README.md
Original file line number Diff line number Diff line change
@@ -55,12 +55,10 @@ enr = { version = "*", features = ["serde", "ed25519", "rust-secp256k1"] }

## Examples

To build an ENR, an `EnrBuilder` is provided.

#### Building an ENR with the default `k256` key type

```rust
use enr::{EnrBuilder, k256};
use enr::{Enr, k256};
use std::net::Ipv4Addr;
use rand::thread_rng;

@@ -69,7 +67,7 @@ let mut rng = thread_rng();
let key = k256::ecdsa::SigningKey::random(&mut rng);

let ip = Ipv4Addr::new(192,168,0,1);
let enr = EnrBuilder::new("v4").ip4(ip).tcp4(8000).build(&key).unwrap();
let enr = Enr::builder().ip4(ip).tcp4(8000).build(&key).unwrap();

assert_eq!(enr.ip4(), Some("192.168.0.1".parse().unwrap()));
assert_eq!(enr.id(), Some("v4".into()));
@@ -78,10 +76,10 @@ assert_eq!(enr.id(), Some("v4".into()));
#### Building an ENR with the `CombinedKey` type (support for multiple signing algorithms).

Note the `ed25519` feature flag must be set. This makes use of the
`EnrBuilder` struct.
`builder::Builder` struct.

```rust
use enr::{EnrBuilder, CombinedKey};
use enr::{Enr, CombinedKey};
use std::net::Ipv4Addr;

// create a new secp256k1 key
@@ -91,7 +89,7 @@ let key = CombinedKey::generate_secp256k1();
let key = CombinedKey::generate_ed25519();

let ip = Ipv4Addr::new(192,168,0,1);
let enr = EnrBuilder::new("v4").ip4(ip).tcp4(8000).build(&key).unwrap();
let enr = Enr::builder().ip4(ip).tcp4(8000).build(&key).unwrap();

assert_eq!(enr.ip4(), Some("192.168.0.1".parse().unwrap()));
assert_eq!(enr.id(), Some("v4".into()));
@@ -103,7 +101,7 @@ ENR fields can be added and modified using the getters/setters on `Enr`. A custo
can be added using `insert` and retrieved with `get`.

```rust
use enr::{EnrBuilder, k256::ecdsa::SigningKey, Enr};
use enr::{k256::ecdsa::SigningKey, Enr};
use std::net::Ipv4Addr;
use rand::thread_rng;

@@ -115,11 +113,11 @@ let mut rng = thread_rng();
let key = SigningKey::random(&mut rng);

let ip = Ipv4Addr::new(192,168,0,1);
let mut enr = EnrBuilder::new("v4").ip4(ip).tcp4(8000).build(&key).unwrap();
let mut enr = Enr::builder().ip4(ip).tcp4(8000).build(&key).unwrap();

enr.set_tcp4(8001, &key);
// set a custom key
enr.insert("custom_key", &vec![0,0,1], &key);
enr.insert("custom_key", &[0,0,1], &key);

// encode to base64
let base_64_string = enr.to_base64();
@@ -130,39 +128,37 @@ let decoded_enr: DefaultEnr = base_64_string.parse().unwrap();
assert_eq!(decoded_enr.ip4(), Some("192.168.0.1".parse().unwrap()));
assert_eq!(decoded_enr.id(), Some("v4".into()));
assert_eq!(decoded_enr.tcp4(), Some(8001));
assert_eq!(decoded_enr.get("custom_key"), Some(vec![0,0,1].as_slice()));
assert_eq!(decoded_enr.get("custom_key").as_ref().map(AsRef::as_ref), Some(vec![0,0,1]).as_deref());
```

#### Encoding/Decoding ENR's of various key types

```rust
use enr::{EnrBuilder, k256::ecdsa::SigningKey, Enr, ed25519_dalek::Keypair, CombinedKey};
use enr::{ed25519_dalek as ed25519, k256::ecdsa, CombinedKey, Enr};
use std::net::Ipv4Addr;
use rand::thread_rng;
use rand::Rng;

// generate a random secp256k1 key
let mut rng = thread_rng();
let key = SigningKey::random(&mut rng);
let ip = Ipv4Addr::new(192,168,0,1);
let enr_secp256k1 = EnrBuilder::new("v4").ip4(ip).tcp4(8000).build(&key).unwrap();
let key = ecdsa::SigningKey::random(&mut rng);
let ip = Ipv4Addr::new(192, 168, 0, 1);
let enr_secp256k1 = Enr::builder().ip4(ip).tcp4(8000).build(&key).unwrap();

// encode to base64
let base64_string_secp256k1 = enr_secp256k1.to_base64();

// generate a random ed25519 key
let mut rng = rand_07::thread_rng();
let key = Keypair::generate(&mut rng);
let enr_ed25519 = EnrBuilder::new("v4").ip4(ip).tcp4(8000).build(&key).unwrap();
let key = ed25519::SigningKey::generate(&mut rng);
let enr_ed25519 = Enr::builder().ip4(ip).tcp4(8000).build(&key).unwrap();

// encode to base64
let base64_string_ed25519 = enr_ed25519.to_base64();

// decode base64 strings of varying key types
// decode the secp256k1 with default Enr
let decoded_enr_secp256k1: Enr<k256::ecdsa::SigningKey> = base64_string_secp256k1.parse().unwrap();
let decoded_enr_secp256k1: Enr<ecdsa::SigningKey> = base64_string_secp256k1.parse().unwrap();
// decode ed25519 ENRs
let decoded_enr_ed25519: Enr<ed25519_dalek::Keypair> = base64_string_ed25519.parse().unwrap();
let decoded_enr_ed25519: Enr<ed25519::SigningKey> = base64_string_ed25519.parse().unwrap();

// use the combined key to be able to decode either
let decoded_enr: Enr<CombinedKey> = base64_string_secp256k1.parse().unwrap();
Loading