Skip to content
This repository has been archived by the owner on Nov 15, 2023. It is now read-only.

Update to schnorrkel 0.8.0 #3267

Merged
merged 11 commits into from
Aug 7, 2019
25 changes: 11 additions & 14 deletions Cargo.lock

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

2 changes: 1 addition & 1 deletion core/consensus/babe/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ futures01 = { package = "futures", version = "0.1" }
futures-timer = "0.2.1"
parking_lot = "0.8.0"
log = "0.4.6"
schnorrkel = "0.1.1"
schnorrkel = { version = "0.8.4", features = ["preaudit_deprecated"] }
rand = "0.6.5"
merlin = "1.0.3"

Expand Down
2 changes: 1 addition & 1 deletion core/consensus/babe/primitives/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ sr-primitives = { path = "../../../sr-primitives", default-features = false }
primitives = { package = "substrate-primitives", path = "../../../primitives", default-features = false }
slots = { package = "substrate-consensus-slots", path = "../../slots", optional = true }
parity-codec = { version = "4.1.1", default-features = false }
schnorrkel = { version = "0.1.1", optional = true }
schnorrkel = { version = "0.8.4", features = ["preaudit_deprecated"], optional = true }

[features]
default = ["std"]
Expand Down
2 changes: 1 addition & 1 deletion core/consensus/babe/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -837,7 +837,7 @@ fn claim_slot(
let threshold = calculate_threshold(c, authorities, authority_index);

get_keypair(key)
.vrf_sign_n_check(transcript, |inout| check(inout, threshold))
.vrf_sign_after_check(transcript, |inout| check(inout, threshold))
.map(|s|(s, authority_index))
}

Expand Down
4 changes: 2 additions & 2 deletions core/primitives/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,10 @@ hash256-std-hasher = { version = "0.14.0", default-features = false }
ed25519-dalek = { version = "1.0.0-pre.1", optional = true }
base58 = { version = "0.1", optional = true }
blake2-rfc = { version = "0.2.18", optional = true }
schnorrkel = { version = "0.1.1", optional = true }
schnorrkel = { version = "0.8.4", features = ["preaudit_deprecated"], optional = true }
rand = { version = "0.6", optional = true }
sha2 = { version = "0.8", optional = true }
substrate-bip39 = { version = "0.2.2", optional = true }
substrate-bip39 = { version = "0.3.1", optional = true }
tiny-bip39 = { version = "0.6.1", optional = true }
hex = { version = "0.3", optional = true }
regex = { version = "1.1", optional = true }
Expand Down
66 changes: 43 additions & 23 deletions core/primitives/src/sr25519.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
// end::description[]

#[cfg(feature = "std")]
use schnorrkel::{signing_context, Keypair, SecretKey, MiniSecretKey, PublicKey,
use schnorrkel::{signing_context, ExpansionMode, Keypair, SecretKey, MiniSecretKey, PublicKey,
derive::{Derivation, ChainCode, CHAIN_CODE_LENGTH}
};
#[cfg(feature = "std")]
Expand Down Expand Up @@ -341,7 +341,7 @@ impl AsRef<Pair> for Pair {
#[cfg(feature = "std")]
impl From<MiniSecretKey> for Pair {
fn from(sec: MiniSecretKey) -> Pair {
Pair(sec.expand_to_keypair())
Pair(sec.expand_to_keypair(ExpansionMode::Ed25519))
}
}

Expand Down Expand Up @@ -376,7 +376,7 @@ impl AsRef<schnorrkel::Keypair> for Pair {
/// Derive a single hard junction.
#[cfg(feature = "std")]
fn derive_hard_junction(secret: &SecretKey, cc: &[u8; CHAIN_CODE_LENGTH]) -> SecretKey {
secret.hard_derive_mini_secret_key(Some(ChainCode(cc.clone())), b"").0.expand()
secret.hard_derive_mini_secret_key(Some(ChainCode(cc.clone())), b"").0.expand(ExpansionMode::Ed25519)
}

/// The raw secret seed, which can be used to recreate the `Pair`.
Expand Down Expand Up @@ -417,7 +417,7 @@ impl TraitPair for Pair {
Ok(Pair(
MiniSecretKey::from_bytes(seed)
.map_err(|_| SecretStringError::InvalidSeed)?
.expand_to_keypair()
.expand_to_keypair(ExpansionMode::Ed25519)
))
}
SECRET_KEY_LENGTH => {
Expand Down Expand Up @@ -476,28 +476,23 @@ impl TraitPair for Pair {

/// Verify a signature on a message. Returns true if the signature is good.
fn verify<P: AsRef<Self::Public>, M: AsRef<[u8]>>(sig: &Self::Signature, message: M, pubkey: P) -> bool {
let signature: schnorrkel::Signature = match schnorrkel::Signature::from_bytes(&sig.as_ref()) {
Ok(some_signature) => some_signature,
Err(_) => return false
};
// Match both schnorrkel 0.1.1 and 0.8.0+ signatures, supporting both wallets
// that have not been upgraded and those that have. To swap to 0.8.0 only,
// create `schnorrkel::Signature` and pass that into `verify_simple`
match PublicKey::from_bytes(pubkey.as_ref().as_slice()) {
Ok(pk) => pk.verify(
signing_context(SIGNING_CTX).bytes(message.as_ref()), &signature
),
Ok(pk) => pk.verify_simple_preaudit_deprecated(
SIGNING_CTX, message.as_ref(), &sig.as_ref(),
).is_ok(),
Err(_) => false,
}
}

/// Verify a signature on a message. Returns true if the signature is good.
fn verify_weak<P: AsRef<[u8]>, M: AsRef<[u8]>>(sig: &[u8], message: M, pubkey: P) -> bool {
let signature: schnorrkel::Signature = match schnorrkel::Signature::from_bytes(sig) {
Ok(some_signature) => some_signature,
Err(_) => return false
};
match PublicKey::from_bytes(pubkey.as_ref()) {
Ok(pk) => pk.verify(
signing_context(SIGNING_CTX).bytes(message.as_ref()), &signature
),
Ok(pk) => pk.verify_simple_preaudit_deprecated(
SIGNING_CTX, message.as_ref(), &sig,
).is_ok(),
Err(_) => false,
}
}
Expand All @@ -518,7 +513,7 @@ impl Pair {
let mini_key: MiniSecretKey = mini_secret_from_entropy(entropy, password.unwrap_or(""))
.expect("32 bytes can always build a key; qed");

let kp = mini_key.expand_to_keypair();
let kp = mini_key.expand_to_keypair(ExpansionMode::Ed25519);
(Pair(kp), mini_key.to_bytes())
}
}
Expand Down Expand Up @@ -618,6 +613,20 @@ mod test {
assert!(pair.public().derive(path.into_iter()).is_none());
}

#[test]
fn derive_soft_known_pair_should_work() {
let pair = Pair::from_string(&format!("{}/Alice", DEV_PHRASE), None).unwrap();
let expected = hex!("d6c71059dbbe9ad2b0ed3f289738b800836eb425544ce694825285b958ca755e");
assert_eq!(pair.public().to_raw_vec(), expected);
}

#[test]
fn derive_hard_known_pair_should_work() {
Copy link
Contributor

@jacogr jacogr Aug 1, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One thing to be aware of (which is biting me on the JS-side). When storing a keypair from 0.1.1 (i.e. the secretKey/publicKey or just the combined 96-bytes) and trying to import that via the new schnorrkel, well, it is not that happy.

For any minisecret it would seem the pair derivation yields the same publicKey, but the secretKey part of the generated bundle is not the same. As an example for the same values...

0.1.1 -

sk: 28b0ae221c6bb06856b287f60d7ea0d98552ea5a16db16956849aa371db3eb51fd190cce74df356432b410bd64682309d6dedb27c76845daf388557cbac3ca34
pk: 46ebddef8cd9bb167dc30878d7113b7e168e6f0646beffd77d69d39bad76b47a

0.8.3 -

sk: 05d65584630d16cd4af6d0bec10f34bb504a5dcb62dba2122d49f5a663763d0afd190cce74df356432b410bd64682309d6dedb27c76845daf388557cbac3ca34
pk: 46ebddef8cd9bb167dc30878d7113b7e168e6f0646beffd77d69d39bad76b47a

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is a way around this which is employed in the polkadot-js/wasm to remain compatible with pairs created/stored on exiting wallets. (Basically using the Keypair from_half_ed25519 and to_half_ed25519_bytes)

If required here, it should be available in 0.8.4 when that is published.

let pair = Pair::from_string(&format!("{}//Alice", DEV_PHRASE), None).unwrap();
let expected = hex!("d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d");
assert_eq!(pair.public().to_raw_vec(), expected);
}

#[test]
fn sr_test_vector_should_work() {
let pair = Pair::from_seed(&hex!(
Expand All @@ -635,6 +644,18 @@ mod test {
assert!(Pair::verify(&signature, &message[..], &public));
}

#[test]
fn verify_known_message_should_work() {
let public = Public::from_raw(hex!(
"b4bfa1f7a5166695eb75299fd1c4c03ea212871c342f2c5dfea0902b2c246918"
));
let signature = Signature::from_raw(hex!(
"5a9755f069939f45d96aaf125cf5ce7ba1db998686f87f2fb3cbdea922078741a73891ba265f70c31436e18a9acd14d189d73c12317ab6c313285cd938453202"
));
let message = b"Verifying that I am the owner of 5G9hQLdsKQswNPgB499DeA5PkFBbgkLPJWkkS6FAM6xGQ8xD. Hash: 221455a3\n";
assert!(Pair::verify(&signature, &message[..], &public));
}

#[test]
fn generated_pair_should_work() {
let (pair, _) = Pair::generate();
Expand All @@ -646,7 +667,6 @@ mod test {

#[test]
fn seeded_pair_should_work() {

let pair = Pair::from_seed(b"12345678901234567890123456789012");
let public = pair.public();
assert_eq!(
Expand Down Expand Up @@ -679,9 +699,9 @@ mod test {
&hex!("0000000000000000000000000000000000000000000000000000000000000000")
);
let public = pk.public();
let js_signature = Signature::from_raw(
hex!("28a854d54903e056f89581c691c1f7d2ff39f8f896c9e9c22475e60902cc2b3547199e0e91fa32902028f2ca2355e8cdd16cfe19ba5e8b658c94aa80f3b81a00")
);
let js_signature = Signature::from_raw(hex!(
"28a854d54903e056f89581c691c1f7d2ff39f8f896c9e9c22475e60902cc2b3547199e0e91fa32902028f2ca2355e8cdd16cfe19ba5e8b658c94aa80f3b81a00"
));
assert!(Pair::verify(&js_signature, b"SUBSTRATE", public));
}
}
4 changes: 2 additions & 2 deletions node/runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,8 +79,8 @@ pub const VERSION: RuntimeVersion = RuntimeVersion {
// and set impl_version to equal spec_version. If only runtime
// implementation changes and behavior does not, then leave spec_version as
// is and increment impl_version.
spec_version: 123,
impl_version: 125,
spec_version: 124,
impl_version: 124,
apis: RUNTIME_API_VERSIONS,
};

Expand Down
3 changes: 1 addition & 2 deletions subkey/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,7 @@ rand = "0.6"
clap = { version = "~2.32", features = ["yaml"] }
tiny-bip39 = "0.6.0"
rustc-hex = "2.0"
substrate-bip39 = "0.2.2"
schnorrkel = "0.1.1"
substrate-bip39 = "0.3.1"
hex = "0.3"
hex-literal = "0.2"
parity-codec = "4.1.1"
Expand Down