Skip to content

Commit 48e18ba

Browse files
committed
feat: upgrade to latest timelock library, add more docs, cleanup
1 parent 0f57a85 commit 48e18ba

File tree

7 files changed

+125
-49
lines changed

7 files changed

+125
-49
lines changed

Cargo.lock

+21-21
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

core/Cargo.toml

+4-4
Original file line numberDiff line numberDiff line change
@@ -21,14 +21,14 @@ targets = ["x86_64-unknown-linux-gnu"]
2121
[dependencies]
2222
totp-rs = { version = "5.5.1", default-features = false, optional = true }
2323
codec = { package = "parity-scale-codec", version = "3.6.12", features = ["derive"], default-features = false }
24-
tle = { package = "tle", default-features = false, git = "https://github.com/ideal-lab5/tle.git", branch = "feat/tle-monorepo"}
24+
timelock = { git = "https://github.com/ideal-lab5/tle.git", default-features = false }
2525
ckb-merkle-mountain-range = { version = "0.5.2", default-features = false }
2626
sha3 = { version = "0.10.8", default-features = false }
2727
serde = { version = "1.0.188", features = ["alloc", "derive"], default-features = false }
2828
ark-bls12-377 = { version = "0.4.0", default-features = false }
2929
ark-std = { version = "0.4.0", default-features = false }
3030
ark-serialize = { version = "0.4.0", default-features = false }
31-
w3f-bls = { version = "=0.1.3", default-features = false }
31+
w3f-bls = { version = "0.1.4", default-features = false }
3232
zeroize = { version = "1.8.1", default-features = false }
3333
ark-ec = { version = "0.4", default-features = false }
3434
ark-ff = { version = "0.4", default-features = false }
@@ -51,10 +51,10 @@ std = [
5151
"dleq_vrf/std",
5252
"w3f-bls/std",
5353
"serde/std",
54+
"ckb-merkle-mountain-range/std",
5455
"codec/std",
55-
"tle/std",
56+
"timelock/std",
5657
"sha3/std",
57-
"ckb-merkle-mountain-range/std",
5858
"zeroize/std",
5959
]
6060
no_std = []

core/README.md

+72-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,77 @@
11
# Murmur Core
22

3-
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.
3+
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).
4+
5+
## Usage
6+
7+
### Creation and Execution
8+
9+
#### Create a Murmur Store
10+
11+
``` rust
12+
use ark_serialize::CanonicalDeserialize;
13+
use ark_std::rand::SeedableRng;
14+
use rand_chacha::ChaCha20Rng;
15+
use rand_core::OsRng;
16+
use w3f_bls::{DoublePublicKeyScheme, KeypairVT, TinyBLS377};
17+
18+
// This simulates the production of a randomness beacon public key
19+
// In practice, this would be fetched from the beacon (e.g. as a hex string) and must be deseraialized
20+
let keypair = KeypairVT::<TinyBLS377>::generate(&mut rng);
21+
let double_public: DoublePublicKey<TinyBLS377> =
22+
DoublePublicKey(keypair.into_public_key_in_signature_group().0, keypair.public.0);
23+
24+
// The 'lifetime' of the Murmur wallet for the given session
25+
let block_schedule: &[BlockNumber] =
26+
&[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20];
27+
28+
// This is your 'secret' seed, a short password used while constructing OTP codes
29+
let seed = vec![1, 2, 3];
30+
31+
// The nonce functions similarly to nonce's for standard accounts, except instead of updating on a
32+
// "per transaction" basis, it only updates on a "per session" basis
33+
//
34+
let nonce = 0;
35+
36+
let murmur_store = MurmurStore::<EngineTinyBLS377>::new::<
37+
DummyIdBuilder,
38+
OsRng,
39+
ChaCha20Rng,
40+
>(seed.clone(), block_schedule.to_vec(), nonce, double_public, &mut rng)
41+
.unwrap();
42+
```
43+
#### Update a Murmur Store
44+
45+
Updating a Murmur store is done by calling the same new function as above and using the 'next' nonce in the
46+
47+
``` rust
48+
// update the nonce
49+
let nonce = 1;
50+
51+
let murmur_store = MurmurStore::<EngineTinyBLS377>::new::<
52+
DummyIdBuilder,
53+
OsRng,
54+
ChaCha20Rng,
55+
>(seed.clone(), block_schedule.to_vec(), nonce, double_public, &mut rng)
56+
.unwrap();
57+
```
58+
59+
#### Prepare Execution Parameters
60+
61+
``` rust
62+
```
63+
64+
### Verification
65+
66+
#### Verify Updates
67+
68+
``` rust
69+
```
70+
71+
#### Verify Execution Parameters
72+
73+
``` rust
74+
```
475

576
## Build
677

@@ -33,8 +104,6 @@ cargo test --features "client"
33104
## Future Work/Notes
34105

35106
- **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)
36-
- **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.
37-
38107
## Contributing
39108

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

core/src/murmur.rs

+22-9
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
* limitations under the License.
1515
*/
1616

17-
//! The murmur protocol implementation
17+
//! The Murmur protocol implementation
1818
use alloc::{collections::BTreeMap, vec, vec::Vec};
1919

2020
#[cfg(feature = "client")]
@@ -40,12 +40,12 @@ use codec::{Decode, Encode};
4040
use core::marker::PhantomData;
4141
use dleq_vrf::{EcVrfVerifier, PublicKey, SecretKey};
4242
use sha3::Digest;
43-
use tle::{
43+
use timelock::{
4444
ibe::fullident::Identity,
4545
stream_ciphers::{AESGCMStreamCipherProvider, AESOutput, StreamCipherProvider},
4646
tlock::*,
4747
};
48-
use w3f_bls::{DoublePublicKey, EngineBLS};
48+
use w3f_bls::DoublePublicKey;
4949

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

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

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

183+
// drop secret data
171184
witness.zeroize();
172185
challenge.zeroize();
173186
secret_key.zeroize();
@@ -403,8 +416,8 @@ pub mod verifier {
403416
/// Verify the correctness of execution parameters by checking that the Merkle proof, `Proof`,
404417
/// and hash `H` are valid. The function outputs true if both conditions are true:
405418
///
406-
/// 1. Proof.Verify(root, [(pos, Leaf(ciphertext))])
407-
/// 2. H == Sha256(otp || aux_data)
419+
/// 1. Proof.Verify(root, [(pos, Leaf(ciphertext))])
420+
/// 2. H == Sha256(otp || aux_data)
408421
////
409422
/// It outputs false otherwise.
410423
///
@@ -489,7 +502,7 @@ mod tests {
489502
pub struct DummyIdBuilder;
490503
impl IdentityBuilder<BlockNumber> for DummyIdBuilder {
491504
fn build_identity(at: BlockNumber) -> Identity {
492-
Identity::new(&[at as u8])
505+
Identity::new(b"", vec![vec![at as u8]])
493506
}
494507
}
495508

core/src/types.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ use ckb_merkle_mountain_range::{Merge, Result as MMRResult};
1919
use codec::{Decode, Encode};
2020
use sha3::Digest;
2121

22-
pub use tle::ibe::fullident::Identity;
22+
pub use timelock::ibe::fullident::Identity;
2323

2424
/// The type to represent a block number
2525
pub type BlockNumber = u32;

lib/README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ To generate a wallet valid for the next 1000 blocks, use:
3232
To send a balance transfer, use:
3333

3434
```shell
35-
./target/debug/murmur execute --name test --seed my_secret_key --to CuqfkE3QieYPAWPpwiygDufmyrKecDcVCF7PN1psaLEn8yr --amount 100_000_000
35+
./target/debug/murmur execute --name test --seed my_secret_key --to CuqfkE3QieYPAWPpwiygDufmyrKecDcVCF7PN1psaLEn8yr --amount 100000000
3636
```
3737

3838
## Test

lib/src/lib.rs

+4-10
Original file line numberDiff line numberDiff line change
@@ -116,17 +116,14 @@ pub fn prepare_execute(
116116
#[cfg(test)]
117117
mod tests {
118118
use super::*;
119-
use rand_core::{OsRng, SeedableRng};
120119

121120
#[test]
122121
pub fn it_can_create_an_mmr_store_and_call_data() {
123122
let seed = b"seed".to_vec();
124123
let block_schedule = vec![1, 2, 3, 4, 5, 6, 7];
125124
let double_public_bytes = murmur_test_utils::get_dummy_beacon_pubkey();
126-
let mut rng = ChaCha20Rng::from_rng(&mut OsRng).unwrap();
127125
let mmr_store =
128-
create(seed.clone(), 0, block_schedule.clone(), double_public_bytes.clone(), &mut rng)
129-
.unwrap();
126+
create(seed.clone(), 0, block_schedule.clone(), double_public_bytes.clone()).unwrap();
130127

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

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

153148
let when = 1;
154149

155-
let proxy_data =
156-
prepare_execute(seed.clone(), when, mmr_store.clone(), &balance_transfer_call).unwrap();
150+
let proxy_data = prepare_execute(seed, when, mmr_store, &balance_transfer_call).unwrap();
157151

158152
assert_eq!(proxy_data.position, 0);
159153
assert_eq!(proxy_data.hash.len(), 32);
160-
assert_eq!(proxy_data.ciphertext.len(), 266);
154+
assert_eq!(proxy_data.ciphertext.len(), 250);
161155
}
162156
}

0 commit comments

Comments
 (0)