Skip to content

Commit

Permalink
feat: upgrade to latest timelock library, add more docs, cleanup
Browse files Browse the repository at this point in the history
  • Loading branch information
driemworks committed Nov 21, 2024
1 parent 0f57a85 commit 48e18ba
Show file tree
Hide file tree
Showing 7 changed files with 125 additions and 49 deletions.
42 changes: 21 additions & 21 deletions Cargo.lock

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

8 changes: 4 additions & 4 deletions core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,14 @@ targets = ["x86_64-unknown-linux-gnu"]
[dependencies]
totp-rs = { version = "5.5.1", default-features = false, optional = true }
codec = { package = "parity-scale-codec", version = "3.6.12", features = ["derive"], default-features = false }
tle = { package = "tle", default-features = false, git = "https://github.com/ideal-lab5/tle.git", branch = "feat/tle-monorepo"}
timelock = { git = "https://github.com/ideal-lab5/tle.git", default-features = false }
ckb-merkle-mountain-range = { version = "0.5.2", default-features = false }
sha3 = { version = "0.10.8", default-features = false }
serde = { version = "1.0.188", features = ["alloc", "derive"], default-features = false }
ark-bls12-377 = { version = "0.4.0", default-features = false }
ark-std = { version = "0.4.0", default-features = false }
ark-serialize = { version = "0.4.0", default-features = false }
w3f-bls = { version = "=0.1.3", default-features = false }
w3f-bls = { version = "0.1.4", default-features = false }
zeroize = { version = "1.8.1", default-features = false }
ark-ec = { version = "0.4", default-features = false }
ark-ff = { version = "0.4", default-features = false }
Expand All @@ -51,10 +51,10 @@ std = [
"dleq_vrf/std",
"w3f-bls/std",
"serde/std",
"ckb-merkle-mountain-range/std",
"codec/std",
"tle/std",
"timelock/std",
"sha3/std",
"ckb-merkle-mountain-range/std",
"zeroize/std",
]
no_std = []
Expand Down
75 changes: 72 additions & 3 deletions core/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,77 @@
# Murmur Core

This library contains the core implementation of the murmur protocol. This implementation can support both BLS12-377 and BLS12-381, but is left curve-agnostic, only expecting that the beacon is produced by an ETF-PFG instance.
This library contains the core implementation of the murmur protocol. This implementation can support both BLS12-377 and BLS12-381, but is left curve-agnostic. This crate can support the randomness beacon produced by the [Ideal Network](https://idealabs.network) as well as [Drand](https://drand.love)'s Quicknet. In general, this library is intended to work with a blockchain whose runtime includes the corresponding [Murmur Pallet](https://github.com/ideal-lab5/idn-sdk/tree/main/pallets/murmur). More specifcially, it is intended to run against the [Ideal Network](https://idealabs.network). For examples of usage against a real network, refer to the [CLI](../lib/src/bin/murmur/main.rs).

## Usage

### Creation and Execution

#### Create a Murmur Store

``` rust
use ark_serialize::CanonicalDeserialize;
use ark_std::rand::SeedableRng;
use rand_chacha::ChaCha20Rng;
use rand_core::OsRng;
use w3f_bls::{DoublePublicKeyScheme, KeypairVT, TinyBLS377};

// This simulates the production of a randomness beacon public key
// In practice, this would be fetched from the beacon (e.g. as a hex string) and must be deseraialized
let keypair = KeypairVT::<TinyBLS377>::generate(&mut rng);
let double_public: DoublePublicKey<TinyBLS377> =
DoublePublicKey(keypair.into_public_key_in_signature_group().0, keypair.public.0);

// The 'lifetime' of the Murmur wallet for the given session
let block_schedule: &[BlockNumber] =
&[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20];

// This is your 'secret' seed, a short password used while constructing OTP codes
let seed = vec![1, 2, 3];

// The nonce functions similarly to nonce's for standard accounts, except instead of updating on a
// "per transaction" basis, it only updates on a "per session" basis
//
let nonce = 0;

let murmur_store = MurmurStore::<EngineTinyBLS377>::new::<
DummyIdBuilder,
OsRng,
ChaCha20Rng,
>(seed.clone(), block_schedule.to_vec(), nonce, double_public, &mut rng)
.unwrap();
```
#### Update a Murmur Store

Updating a Murmur store is done by calling the same new function as above and using the 'next' nonce in the

``` rust
// update the nonce
let nonce = 1;

let murmur_store = MurmurStore::<EngineTinyBLS377>::new::<
DummyIdBuilder,
OsRng,
ChaCha20Rng,
>(seed.clone(), block_schedule.to_vec(), nonce, double_public, &mut rng)
.unwrap();
```

#### Prepare Execution Parameters

``` rust
```

### Verification

#### Verify Updates

``` rust
```

#### Verify Execution Parameters

``` rust
```

## Build

Expand Down Expand Up @@ -33,8 +104,6 @@ cargo test --features "client"
## Future Work/Notes

- **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.
Expand Down
31 changes: 22 additions & 9 deletions core/src/murmur.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
* limitations under the License.
*/

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

#[cfg(feature = "client")]
Expand All @@ -40,12 +40,12 @@ use codec::{Decode, Encode};
use core::marker::PhantomData;
use dleq_vrf::{EcVrfVerifier, PublicKey, SecretKey};
use sha3::Digest;
use tle::{
use timelock::{
ibe::fullident::Identity,
stream_ciphers::{AESGCMStreamCipherProvider, AESOutput, StreamCipherProvider},
tlock::*,
};
use w3f_bls::{DoublePublicKey, EngineBLS};
use w3f_bls::DoublePublicKey;

/// The base Murmur protocol label
pub const MURMUR_PROTO: &[u8] = b"Murmur://";
Expand All @@ -63,6 +63,7 @@ pub enum Error {
ExecuteError,
/// An error occurred when creating a murmur wallet
MMRError,
/// Some data in the murmur store is corrupted
InconsistentStore,
/// No leaf could be identified in the MMR at the specified position
NoLeafFound,
Expand Down Expand Up @@ -92,7 +93,8 @@ pub trait ProtocolEngine {
/// The supported protocols
#[derive(Clone, serde::Serialize, serde::Deserialize, Encode, Decode)]
pub enum ProtocolId {
/// small signatures, SignatureGroup = G1 (48 bytes), PublicKeyGroup = G2 (96 bytes)
/// A curve config with small signatures and large pubkyes
/// SignatureGroup = G1 (48 bytes), PublicKeyGroup = G2 (96 bytes)
TinyBLS377,
}

Expand Down Expand Up @@ -127,12 +129,22 @@ pub struct MurmurStore<P: ProtocolEngine> {

#[cfg(feature = "client")]
impl<P: ProtocolEngine> MurmurStore<P> {
/// Create a new Murmur store
/// Create a new Murmur store.
///
/// This function allows for two separate RNGs to be specified. In general, the first RNG type R
/// should be created externally from this function and passed as an argument.
/// In practice, this should probably be the OsRng or something similar.
/// The second type of RNG, S, must be seedable from [u8;32]. This RNG is instantiated within
/// the function, where we seed a new RNG each time we encrypt a new OTP code using timelock
/// encryption.
///
/// * `seed`: An any-length seed (i.e. password)
/// * `block_schedule`: The blocks for which OTP codes will be generated
/// * `ephemeral_msk`: Any 32 bytes
/// * `nonce`: A value representing the 'number of times' the Murmur wallet has been created or updated.
/// Should be monotonically increasing with each subsequent call.
/// * `round_public_key`: The IDN beacon's public key
/// * `rng`: An instance of an CPRNG of type `R`
pub fn new<I: IdentityBuilder<BlockNumber>, R, S>(
mut seed: Vec<u8>,
block_schedule: Vec<BlockNumber>,
Expand Down Expand Up @@ -168,6 +180,7 @@ impl<P: ProtocolEngine> MurmurStore<P> {
let mut witness: [u8; 32] = transcript.clone().witness(rng).read_byte_array();
let totp = BOTPGenerator::new(witness.to_vec()).map_err(|_| Error::InvalidSeed)?;

// drop secret data
witness.zeroize();
challenge.zeroize();
secret_key.zeroize();
Expand Down Expand Up @@ -403,8 +416,8 @@ pub mod verifier {
/// Verify the correctness of execution parameters by checking that the Merkle proof, `Proof`,
/// and hash `H` are valid. The function outputs true if both conditions are true:
///
/// 1. Proof.Verify(root, [(pos, Leaf(ciphertext))])
/// 2. H == Sha256(otp || aux_data)
/// 1. Proof.Verify(root, [(pos, Leaf(ciphertext))])
/// 2. H == Sha256(otp || aux_data)
////
/// It outputs false otherwise.
///
Expand Down Expand Up @@ -489,7 +502,7 @@ mod tests {
pub struct DummyIdBuilder;
impl IdentityBuilder<BlockNumber> for DummyIdBuilder {
fn build_identity(at: BlockNumber) -> Identity {
Identity::new(&[at as u8])
Identity::new(b"", vec![vec![at as u8]])
}
}

Expand Down
2 changes: 1 addition & 1 deletion core/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ use ckb_merkle_mountain_range::{Merge, Result as MMRResult};
use codec::{Decode, Encode};
use sha3::Digest;

pub use tle::ibe::fullident::Identity;
pub use timelock::ibe::fullident::Identity;

/// The type to represent a block number
pub type BlockNumber = u32;
Expand Down
2 changes: 1 addition & 1 deletion lib/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ To generate a wallet valid for the next 1000 blocks, use:
To send a balance transfer, use:

```shell
./target/debug/murmur execute --name test --seed my_secret_key --to CuqfkE3QieYPAWPpwiygDufmyrKecDcVCF7PN1psaLEn8yr --amount 100_000_000
./target/debug/murmur execute --name test --seed my_secret_key --to CuqfkE3QieYPAWPpwiygDufmyrKecDcVCF7PN1psaLEn8yr --amount 100000000
```

## Test
Expand Down
14 changes: 4 additions & 10 deletions lib/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -116,17 +116,14 @@ pub fn prepare_execute(
#[cfg(test)]
mod tests {
use super::*;
use rand_core::{OsRng, SeedableRng};

#[test]
pub fn it_can_create_an_mmr_store_and_call_data() {
let seed = b"seed".to_vec();
let block_schedule = vec![1, 2, 3, 4, 5, 6, 7];
let double_public_bytes = murmur_test_utils::get_dummy_beacon_pubkey();
let mut rng = ChaCha20Rng::from_rng(&mut OsRng).unwrap();
let mmr_store =
create(seed.clone(), 0, block_schedule.clone(), double_public_bytes.clone(), &mut rng)
.unwrap();
create(seed.clone(), 0, block_schedule.clone(), double_public_bytes.clone()).unwrap();

assert_eq!(mmr_store.root.0.len(), 32);
assert_eq!(mmr_store.metadata.keys().len(), 7);
Expand All @@ -137,9 +134,7 @@ mod tests {
let seed = b"seed".to_vec();
let block_schedule = vec![1, 2, 3, 4, 5, 6, 7];
let double_public_bytes = murmur_test_utils::get_dummy_beacon_pubkey();
let mut rng = ChaCha20Rng::from_rng(&mut OsRng).unwrap();
let mmr_store =
create(seed.clone(), 0, block_schedule, double_public_bytes, &mut rng).unwrap();
let mmr_store = create(seed.clone(), 0, block_schedule, double_public_bytes).unwrap();

let bob = subxt_signer::sr25519::dev::bob().public_key();
let balance_transfer_call =
Expand All @@ -152,11 +147,10 @@ mod tests {

let when = 1;

let proxy_data =
prepare_execute(seed.clone(), when, mmr_store.clone(), &balance_transfer_call).unwrap();
let proxy_data = prepare_execute(seed, when, mmr_store, &balance_transfer_call).unwrap();

assert_eq!(proxy_data.position, 0);
assert_eq!(proxy_data.hash.len(), 32);
assert_eq!(proxy_data.ciphertext.len(), 266);
assert_eq!(proxy_data.ciphertext.len(), 250);
}
}

0 comments on commit 48e18ba

Please sign in to comment.