Skip to content

Commit 783f7ab

Browse files
committed
remove investtor_secret_key, add MasterSeed abstraction
1 parent 2bb20fd commit 783f7ab

2 files changed

Lines changed: 137 additions & 82 deletions

File tree

dart-bp/src/account_registration.rs

Lines changed: 136 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ use dock_crypto_utils::hashing_utils::hash_to_field;
3434
use dock_crypto_utils::msm::multiply_field_elems_with_same_group_elem;
3535
use dock_crypto_utils::randomized_mult_checker::RandomizedMultChecker;
3636
use dock_crypto_utils::transcript::{MerlinTranscript, Transcript};
37-
use polymesh_dart_common::{AssetId, NullifierSkGenCounter};
37+
use polymesh_dart_common::{AssetId, NullifierSkGenCounter, SkGenCounter};
3838
use rand_core::CryptoRngCore;
3939
use schnorr_pok::discrete_log::{
4040
PokDiscreteLog, PokDiscreteLogProtocol, PokPedersenCommitment, PokPedersenCommitmentProtocol,
@@ -43,7 +43,7 @@ use schnorr_pok::partial::{
4343
Partial1PokPedersenCommitment, PartialPokPedersenCommitment, PartialSchnorrResponse,
4444
};
4545
use schnorr_pok::{SchnorrChallengeContributor, SchnorrCommitment, SchnorrResponse};
46-
use zeroize::Zeroize;
46+
use zeroize::{Zeroize, ZeroizeOnDrop};
4747

4848
pub const PK_T_LABEL: &'static [u8; 4] = b"pk_t";
4949
pub const PK_T_GEN_LABEL: &'static [u8; 8] = b"pk_t_gen";
@@ -1470,42 +1470,63 @@ pub fn powers_of_base<F: PrimeField, const BASE_BITS: usize, const NUM_DIGITS: u
14701470
powers
14711471
}
14721472

1473-
/// Generate keypairs and fresh account state for investor from a seed
1474-
pub fn setup_investor<G: AffineRepr, D: FullDigest>(
1475-
seed: &[u8],
1476-
id: G::ScalarField, // User can hash its string ID onto the field
1477-
asset_id: AssetId,
1478-
counter: NullifierSkGenCounter,
1479-
j: G,
1480-
g: G,
1481-
poseidon_config: Poseidon2Params<G::ScalarField>,
1482-
) -> Result<(
1483-
(SigKey<G>, VerKey<G>),
1484-
(DecKey<G>, EncKey<G>),
1485-
AccountState<G>,
1486-
)> {
1487-
// For creating secret keys, use seed||asset_id
1488-
let mut extended_seed = seed.to_vec();
1489-
extended_seed.extend(asset_id.to_le_bytes().as_slice());
1490-
1491-
let sig_sk = hash_to_field::<G::ScalarField, D>(b"Signing key", &extended_seed);
1492-
let enc_sk = hash_to_field::<G::ScalarField, D>(b"Encryption key", &extended_seed);
1493-
1494-
// For creating commitment randomness, use seed||asset_id||counter
1495-
extended_seed.extend_from_slice(counter.to_le_bytes().as_slice());
1496-
let randomness = hash_to_field::<G::ScalarField, D>(b"Commitment randomness", &extended_seed);
1497-
1498-
let (sk, vk) = keygen_sig_given_sk(sig_sk, j);
1499-
let (dk, ek) = keygen_enc_given_sk(enc_sk, g);
1500-
let account = AccountState::new_given_randomness(
1501-
id,
1502-
sk.0,
1503-
asset_id,
1504-
counter,
1505-
randomness,
1506-
poseidon_config,
1507-
)?;
1508-
Ok(((sk, vk), (dk, ek), account))
1473+
const SEPARATOR: &[u8; 2] = b"//";
1474+
1475+
#[derive(Clone, Debug, CanonicalSerialize, CanonicalDeserialize, Zeroize, ZeroizeOnDrop)]
1476+
pub struct MasterSeed(Vec<u8>);
1477+
1478+
impl MasterSeed {
1479+
pub fn new(seed: Vec<u8>) -> Self {
1480+
Self(seed)
1481+
}
1482+
1483+
/// Doesn't include asset-id to allow accounts to share secret keys
1484+
pub fn derive_keys<G: AffineRepr, D: FullDigest>(
1485+
&self,
1486+
path: &[u8],
1487+
counter: SkGenCounter,
1488+
j: G,
1489+
g: G,
1490+
) -> ((SigKey<G>, VerKey<G>), (DecKey<G>, EncKey<G>)) {
1491+
// For creating secret keys, use `seed//path//counter`
1492+
let mut extended_seed = self.0.to_vec();
1493+
extended_seed.extend(SEPARATOR);
1494+
extended_seed.extend_from_slice(path);
1495+
extended_seed.extend(SEPARATOR);
1496+
extended_seed.extend(counter.to_le_bytes());
1497+
1498+
let sig_sk = hash_to_field::<G::ScalarField, D>(b"Signing key", &extended_seed);
1499+
let enc_sk = hash_to_field::<G::ScalarField, D>(b"Encryption key", &extended_seed);
1500+
1501+
let (sk, vk) = keygen_sig_given_sk(sig_sk, j);
1502+
let (dk, ek) = keygen_enc_given_sk(enc_sk, g);
1503+
1504+
extended_seed.zeroize();
1505+
((sk, vk), (dk, ek))
1506+
}
1507+
1508+
pub fn derive_account_randomness<G: AffineRepr, D: FullDigest>(
1509+
&self,
1510+
path: &[u8],
1511+
counter_s: SkGenCounter,
1512+
asset_id: AssetId,
1513+
counter: NullifierSkGenCounter,
1514+
) -> G::ScalarField {
1515+
// For creating randomness, use `seed//path//counter_s//asset_id//counter_n`
1516+
let mut extended_seed = self.0.to_vec();
1517+
extended_seed.extend(SEPARATOR);
1518+
extended_seed.extend_from_slice(path);
1519+
extended_seed.extend(SEPARATOR);
1520+
extended_seed.extend(counter_s.to_le_bytes());
1521+
extended_seed.extend(SEPARATOR);
1522+
extended_seed.extend(asset_id.to_le_bytes().as_slice());
1523+
extended_seed.extend(SEPARATOR);
1524+
extended_seed.extend(counter.to_le_bytes());
1525+
let randomness =
1526+
hash_to_field::<G::ScalarField, D>(b"Commitment randomness", &extended_seed);
1527+
extended_seed.zeroize();
1528+
randomness
1529+
}
15091530
}
15101531

15111532
#[cfg(test)]
@@ -1684,82 +1705,115 @@ pub mod tests {
16841705
}
16851706

16861707
#[test]
1687-
fn test_setup_investor() {
1708+
fn test_deterministic_key_and_randomness_generation() {
16881709
let mut rng = rand::thread_rng();
16891710

16901711
let id = Fr::rand(&mut rng);
16911712
let asset_id = 1;
1692-
let counter = 1;
1713+
let counter_s = 1;
1714+
let counter_n = 1;
16931715

1694-
let seed1 = b"test_seed";
1716+
let seed1 = MasterSeed::new(b"test_seed".to_vec());
1717+
1718+
let seed2 = MasterSeed::new(b"different_seed".to_vec());
16951719

16961720
let j = PallasA::rand(&mut rng);
16971721
let g = PallasA::rand(&mut rng);
1722+
16981723
let params = test_params_for_poseidon2();
16991724

1700-
let result1 = setup_investor::<PallasA, Blake2b512>(
1701-
seed1,
1702-
id,
1725+
let result1 = seed1.derive_keys::<PallasA, Blake2b512>(b"path", counter_s, j, g);
1726+
let result2 = seed1.derive_keys::<PallasA, Blake2b512>(b"path", counter_s, j, g);
1727+
assert_eq!(result1, result2);
1728+
1729+
// Same seed, different path
1730+
let result3 = seed1.derive_keys::<PallasA, Blake2b512>(b"path1", counter_s, j, g);
1731+
assert_ne!(result1, result3);
1732+
1733+
// Same seed, same path, different counter
1734+
let result4 = seed1.derive_keys::<PallasA, Blake2b512>(b"path", counter_s + 1, j, g);
1735+
assert_ne!(result1, result4);
1736+
1737+
// Different seed, same path and counter
1738+
let result5 = seed2.derive_keys::<PallasA, Blake2b512>(b"path", counter_s, j, g);
1739+
assert_ne!(result1, result5);
1740+
1741+
let rand1 = seed1.derive_account_randomness::<PallasA, Blake2b512>(
1742+
b"path", counter_s, asset_id, counter_n,
1743+
);
1744+
let rand2 = seed1.derive_account_randomness::<PallasA, Blake2b512>(
1745+
b"path", counter_s, asset_id, counter_n,
1746+
);
1747+
assert_eq!(rand1, rand2);
1748+
1749+
// Different counter
1750+
let rand3 = seed2.derive_account_randomness::<PallasA, Blake2b512>(
1751+
b"path",
1752+
counter_s,
17031753
asset_id,
1704-
counter,
1705-
j,
1706-
g,
1707-
params.clone(),
1708-
)
1709-
.unwrap();
1710-
let result2 = setup_investor::<PallasA, Blake2b512>(
1711-
seed1,
1754+
counter_n + 1,
1755+
);
1756+
assert_ne!(rand1, rand3);
1757+
1758+
let rand4 = seed2.derive_account_randomness::<PallasA, Blake2b512>(
1759+
b"path",
1760+
counter_s + 1,
1761+
asset_id,
1762+
counter_n,
1763+
);
1764+
assert_ne!(rand1, rand4);
1765+
1766+
let rand5 = seed1.derive_account_randomness::<PallasA, Blake2b512>(
1767+
b"path1", counter_s, asset_id, counter_n,
1768+
);
1769+
assert_ne!(rand1, rand5);
1770+
1771+
let sk1 = result1.0.0.0;
1772+
let sk2 = result3.0.0.0;
1773+
1774+
let account1 = AccountState::<PallasA>::new_given_randomness(
17121775
id,
1776+
sk1,
17131777
asset_id,
1714-
counter,
1715-
j,
1716-
g,
1778+
counter_n,
1779+
rand1,
17171780
params.clone(),
17181781
)
17191782
.unwrap();
1720-
assert_eq!(result1, result2);
1721-
1722-
let seed2 = b"different_seed";
1723-
let result3 = setup_investor::<PallasA, Blake2b512>(
1724-
seed2,
1783+
let account2 = AccountState::<PallasA>::new_given_randomness(
17251784
id,
1785+
sk1,
17261786
asset_id,
1727-
counter,
1728-
j,
1729-
g,
1787+
counter_n,
1788+
rand1,
17301789
params.clone(),
17311790
)
17321791
.unwrap();
1733-
assert_ne!(result1, result3);
1792+
assert_eq!(account1, account2);
17341793

1735-
// seed same but asset id different
1736-
let result4 = setup_investor::<PallasA, Blake2b512>(
1737-
seed1,
1794+
// Different randomness
1795+
let account3 = AccountState::<PallasA>::new_given_randomness(
17381796
id,
1739-
asset_id + 1,
1740-
counter,
1741-
j,
1742-
g,
1797+
sk1,
1798+
asset_id,
1799+
counter_n,
1800+
rand3,
17431801
params.clone(),
17441802
)
17451803
.unwrap();
1746-
assert_ne!(result1, result4);
1804+
assert_ne!(account1, account3);
17471805

1748-
// seed and asset id same but counter different
1749-
let result5 = setup_investor::<PallasA, Blake2b512>(
1750-
seed1,
1806+
// Same randomness, different sk
1807+
let account4 = AccountState::<PallasA>::new_given_randomness(
17511808
id,
1809+
sk2,
17521810
asset_id,
1753-
counter + 1,
1754-
j,
1755-
g,
1811+
counter_n,
1812+
rand1,
17561813
params.clone(),
17571814
)
17581815
.unwrap();
1759-
// Keys same but randomness different
1760-
assert_eq!(result1.0, result5.0);
1761-
assert_eq!(result1.1, result5.1);
1762-
assert_ne!(result1.2.randomness, result5.2.randomness);
1816+
assert_ne!(account1, account4);
17631817
}
17641818

17651819
#[test]

dart-common/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ pub type BlockNumber = u32;
88
pub type LegId = u8;
99
pub type MediatorId = u8;
1010

11+
pub type SkGenCounter = u16;
1112
pub type NullifierSkGenCounter = u16;
1213

1314
pub const BALANCE_BITS: u16 = 48;

0 commit comments

Comments
 (0)