Skip to content

Commit

Permalink
chore: merge main
Browse files Browse the repository at this point in the history
  • Loading branch information
driemworks committed Oct 24, 2024
2 parents 7fa47d9 + 49f9d1e commit 563c876
Show file tree
Hide file tree
Showing 21 changed files with 573 additions and 474 deletions.
19 changes: 11 additions & 8 deletions .github/workflows/rust.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,24 @@ name: Rust

on:
push:
branches: [ "main", "dev" ]
branches: ["main", "dev"]
pull_request:
branches: [ "main", "dev" ]
branches: ["main", "dev"]

env:
CARGO_TERM_COLOR: always

jobs:
build:

runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4
- name: Build
run: cargo build --verbose
- name: Run tests
run: cargo test --verbose
- uses: actions/checkout@v4
- name: Install Rust
run: rustup update stable
- name: Check formatting
run: cargo fmt -- --check
- name: Build
run: cargo build --verbose
- name: Run tests
run: cargo test --verbose
17 changes: 17 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Changelog

All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]

## [0.1.0] - 2023-10-14

### Added

- Initial implementation of the Murmur API.

[unreleased]: https://github.com/ideal-lab5/murmur/compare/v0.1.0...HEAD
[0.1.0]: https://github.com/ideal-lab5/murmur/releases/tag/v0.1.0
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.

3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,11 @@ resolver = "2"

[workspace.package]
edition = "2021"
authors = ["Ideal Labs <driemworks@idealabs.network>"]
authors = ["Ideal Labs <hello@idealabs.network>"]
repository = "https://github.com/ideal-lab5/murmur"
homepage = "https://idealabs.network"
license = "Apache-2.0"
description = "Murmur crates"

[workspace.lints.rust]
suspicious_double_ref_op = { level = "allow", priority = 2 }
Expand Down
32 changes: 24 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,23 +1,39 @@
# Murmur

Murmur is an air-gapped keyless crypto wallet protocol that runs on the [Ideal Network](). This repository contains the core implementation of the murmur protocol and a CLI to allow fully non-custodial usage of murmur wallets.
Murmur is an air-gapped keyless crypto wallet protocol that runs on the [Ideal Network](https://idealabs.network). This repository contains the core implementation of the murmur protocol and a CLI to allow fully non-custodial usage of murmur wallets.

The murmur protocol enables **keyless account abstraction** capabilities for any chain bridged to the Ideal Network (alternatively, we can do this with drand). wallet is a special pure proxy that can only be executed when presented with proof that the origin knows a correct time-based OTP code.
The murmur protocol enables **keyless account abstraction** capabilities for any chain bridged to the Ideal Network (alternatively, we can do this with drand). wallet is a special pure proxy that can only be executed when presented with proof that the origin knows a correct time-based OTP code.

It is based on the [Hours of Horus](https://eprint.iacr.org/2021/715) protocol, which leverages timelock encryption and a secure OTP code generator to construct a keyless wallet scheme. Our scheme improves on this construction in several ways.
It is based on the [Hours of Horus](https://eprint.iacr.org/2021/715) protocol, which leverages timelock encryption and a secure OTP code generator to construct a keyless wallet scheme. Our scheme improves on this construction in several ways.

- We leverage the Ideal Network to instantiate practical timelock encryption, allowing the HoH scheme to be realized in the first place.
- We use a Merkle mountain range in place of a Merkle tree, allowing for arbitrary numbers of OTP codes to be generated
- JIT execution: Rather than relying on a commit-reveal scheme in order to use the wallet, our scheme uses a 'just-in-time' approach leveraging the Ideal Network's on-chain randomness, which provides the decryption key (i.e. BLS signature) necessary to verify proofs.
- **Practical Timelock Encryption**: We leverage the Ideal Network to instantiate practical timelock encryption, allowing the HoH scheme to be realized in the first place.
- **Merkle Mountain Range**: We use a Merkle mountain range in place of a Merkle tree, allowing for arbitrary numbers of OTP codes to be generated
- **Just-in-Time Execution**: Rather than relying on a commit-reveal scheme in order to use the wallet, our scheme uses a 'just-in-time' approach leveraging the Ideal Network's on-chain randomness, which provides the decryption key (i.e. BLS signature) necessary to verify proofs.

## Build

```
To build the project, use the following command:

```shell
cargo build
```

## Testing

```
To run the tests, use the following command:

```shell
cargo test
```

## Contributing

Contributions are welcome! Please open an issue or submit a pull request.

## License

This project is licensed under the Apache-2.0. See the [LICENSE](LICENSE) file for details.

## Contact

For any inquiries, please contact [Ideal Labs](https://idealabs.network).
8 changes: 8 additions & 0 deletions core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,15 @@
name = "murmur-core"
version = "0.1.0"
edition = "2021"
description = "Murmur core"
documentation = "https://docs.rs/murmur-core"
readme = "README.md"
keywords = ["crypto", "wallet", "keyless"]
categories = ["development-tools", "cryptography"]
authors.workspace = true
license.workspace = true
repository.workspace = true
homepage.workspace = true

[lints]
workspace = true
Expand Down Expand Up @@ -34,6 +41,7 @@ ark-transcript = { git = "https://github.com/w3f/ring-vrf.git", default-features

[dev-dependencies]
rand_core = { version = "0.6.4", features = ["getrandom"], default-features = false }
hkdf = "0.12.4"

[features]
default = ["client"]
Expand Down
33 changes: 26 additions & 7 deletions core/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,26 +4,45 @@ This library contains the core implementation of the murmur protocol. This imple

## Build

``` shell
To build the library, use the following command:

```shell
cargo build
```

The OTP code generator is gated under the "client" feature, so build with:
``` shell
The OTP code generator is gated under the "client" feature. To build with this feature enabled, use:

```shell
cargo build --features "client"
```

## Test

``` shell
To run the tests, use the following command:

```shell
cargo test
```

The OTP code generator is gated under the "client" feature, so run tests with:
``` shell

```shell
cargo test --features "client"
```

## Future Work/Notes
- There is an 'otpauth' feature that can be enabled on the totp lib. It allows for the inclusion of an issuer and account_name. We can investigate usage of this in the future. https://github.com/constantoine/totp-rs/blob/da78569b0c233adbce126dbe0c35452340fd3929/src/lib.rs#L160
- Wallet Update logic: Each murmur wallet is ephemeral, since any MMR must be limited in size. We can use a zkp to prove knowledge of the seed in order to allow the wallet owner to update the wallet by providing a new MMR root.

- **OTPAuth Feature**: There is an 'otpauth' feature that can be enabled on the totp lib. It allows for the inclusion of an issuer and account_name. We can investigate usage of this in the future. [TOTP Library Reference](https://github.com/constantoine/totp-rs/blob/da78569b0c233adbce126dbe0c35452340fd3929/src/lib.rs#L160)
- **Wallet Update logic**: Each murmur wallet is ephemeral, since any MMR must be limited in size. We can use a zkp to prove knowledge of the seed in order to allow the wallet owner to update the wallet by providing a new MMR root.

## Contributing

Contributions are welcome! Please open an issue or submit a pull request.

## License

This project is licensed under the Apache-2.0. See the [LICENSE](../LICENSE) file for details.

## Contact

For any inquiries, please contact [Ideal Labs](https://idealabs.network).
1 change: 1 addition & 0 deletions core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#![cfg_attr(not(feature = "std"), no_std)]
//! the murmur core library
Expand Down
69 changes: 32 additions & 37 deletions core/src/murmur.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
*/

//! The murmur protocol implementation
//!
use alloc::{collections::BTreeMap, vec, vec::Vec};

#[cfg(feature = "client")]
Expand All @@ -38,6 +37,7 @@ use ckb_merkle_mountain_range::{
util::{MemMMR, MemStore},
MerkleProof,
};
use codec::{Decode, Encode};
use dleq_vrf::{EcVrfVerifier, PublicKey, SecretKey};
use etf_crypto_primitives::{
encryption::tlock::*,
Expand All @@ -54,7 +54,9 @@ pub const ALLOCATED_BUFFER_BYTES: usize = 32;
/// Error types for murmur wallet usage
#[derive(Debug, PartialEq)]
pub enum Error {
/// An error occurred when executing a call
ExecuteError,
/// An error occurred when creating a murmur wallet
MMRError,
InconsistentStore,
/// No leaf could be identified in the MMR at the specified position
Expand All @@ -73,7 +75,7 @@ pub enum Error {

/// The murmur store contains minimal data required to use a murmur wallet
#[cfg(feature = "client")]
#[derive(Clone, serde::Serialize, serde::Deserialize)]
#[derive(Clone, serde::Serialize, serde::Deserialize, Encode, Decode)]
pub struct MurmurStore {
/// The nonce of this murmur store
pub nonce: u64,
Expand Down Expand Up @@ -108,7 +110,8 @@ impl MurmurStore {
R: Rng + CryptoRng + SeedableRng<Seed = [u8; 32]> + Sized,
{
let mut witness = generate_witness(seed.clone(), rng);
let mut secret_key = SecretKey::<<E::SignatureGroup as CurveGroup>::Affine>::from_seed(&witness);
let mut secret_key =
SecretKey::<<E::SignatureGroup as CurveGroup>::Affine>::from_seed(&witness);
let pubkey = secret_key.as_publickey();
let mut pubkey_bytes = Vec::new();
pubkey.serialize_compressed(&mut pubkey_bytes).unwrap();
Expand All @@ -132,7 +135,7 @@ impl MurmurStore {
let mut mmr = MemMMR::<_, MergeLeaves>::new(0, store);

for &i in &block_schedule {
let otp_code = totp.generate(i);
let otp_code = totp.generate(i as u64);
let identity = I::build_identity(i);

let mut ephemeral_msk: [u8; 32] = transcript
Expand All @@ -142,6 +145,7 @@ impl MurmurStore {
.chain(&otp_code.as_bytes())
.challenge(b"ephemeral_msk")
.read_byte_array();

let ephem_rng = R::from_seed(ephemeral_msk);

let ct_bytes = timelock_encrypt::<E, R>(
Expand Down Expand Up @@ -210,7 +214,7 @@ impl MurmurStore {
seed.zeroize();
witness.zeroize();

let otp_code = botp.generate(when);
let otp_code = botp.generate(when as u64);

let mut hasher = sha3::Sha3_256::default();
Digest::update(&mut hasher, otp_code.as_bytes());
Expand Down Expand Up @@ -262,13 +266,13 @@ fn timelock_encrypt<E: EngineBLS, R: CryptoRng + Rng + Sized>(
message: &[u8],
rng: R,
) -> Result<Vec<u8>, Error> {
let ciphertext = tle::<E, R>(pk, ephemeral_msk, message, identity, rng)
.map_err(|_| Error::TlockFailed)?;
let mut ct_bytes = Vec::new();
ciphertext
.serialize_compressed(&mut ct_bytes)
.map_err(|_| Error::InvalidBufferSize)?;
Ok(ct_bytes)
let ciphertext =
tle::<E, R>(pk, ephemeral_msk, message, identity, rng).map_err(|_| Error::TlockFailed)?;
let mut ct_bytes = Vec::new();
ciphertext
.serialize_compressed(&mut ct_bytes)
.map_err(|_| Error::InvalidBufferSize)?;
Ok(ct_bytes)
}

/// Functions for verifying execution and update requests
Expand Down Expand Up @@ -366,22 +370,20 @@ mod tests {
pub const WHEN: BlockNumber = 10;
pub const OTP: &[u8] = b"823185";

pub struct DummyIdBuilder;
impl IdentityBuilder<BlockNumber> for DummyIdBuilder {
fn build_identity(at: BlockNumber) -> Identity {
Identity::new(&[at as u8])
}
}
pub struct DummyIdBuilder;
impl IdentityBuilder<BlockNumber> for DummyIdBuilder {
fn build_identity(at: BlockNumber) -> Identity {
Identity::new(&[at as u8])
}
}

#[cfg(feature = "client")]
#[test]
pub fn it_can_generate_mmr_data_store() {
let mut rng = ChaCha20Rng::seed_from_u64(0);
let keypair = w3f_bls::KeypairVT::<TinyBLS377>::generate(&mut rng);
let double_public: DoublePublicKey<TinyBLS377> = DoublePublicKey(
keypair.into_public_key_in_signature_group().0,
keypair.public.0,
);
#[cfg(feature = "client")]
#[test]
pub fn it_can_generate_mmr_data_store() {
let mut rng = ChaCha20Rng::seed_from_u64(0);
let keypair = w3f_bls::KeypairVT::<TinyBLS377>::generate(&mut rng);
let double_public: DoublePublicKey<TinyBLS377> =
DoublePublicKey(keypair.into_public_key_in_signature_group().0, keypair.public.0);

let seed = vec![1, 2, 3];

Expand Down Expand Up @@ -430,11 +432,6 @@ mod tests {
)
.unwrap();

// sanity check
assert!(proof
.verify(root.clone(), vec![(pos, Leaf(ciphertext.clone()))])
.unwrap());

assert!(verifier::verify_execute(
root,
proof,
Expand All @@ -457,7 +454,6 @@ mod tests {
);

let seed = vec![1, 2, 3];
let aux_data = vec![2, 3, 4, 5];

let murmur_store = MurmurStore::new::<TinyBLS377, DummyIdBuilder, ChaCha20Rng>(
seed.clone(),
Expand All @@ -467,10 +463,9 @@ mod tests {
&mut rng,
).unwrap();

// the block number when this would execute
let when = 1000;
let aux_data = vec![2, 3, 4, 5];

match murmur_store.execute(seed.clone(), when, aux_data.clone(), &mut rng) {
match murmur_store.execute(seed.clone(), 10000, aux_data.clone(), &mut rng) {
Ok(_) => panic!("There should be an error"),
Err(e) => assert_eq!(e, Error::NoCiphertextFound),
}
Expand Down Expand Up @@ -553,7 +548,7 @@ mod tests {
&mut rng,
).unwrap();

let aux_data = vec![2, 3, 4, 5];
let aux_data = vec![2, 3, 13, 3];

// the block number when this would execute
let root = murmur_store.root.clone();
Expand Down
Loading

0 comments on commit 563c876

Please sign in to comment.