diff --git a/Cargo.toml b/Cargo.toml index 1372c1480ae57..5278dd313331e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -462,6 +462,7 @@ aptos-cargo-cli = { path = "devtools/aptos-cargo-cli" } # External crate dependencies. # Please do not add any test features here: they should be declared by the individual crate. +blsttc = {package = "blsttc", git = "https://github.com/Entropy-Foundation/blsttc-supra.git", rev = "431f403dfd0d625515363711ee58dac84d0c1ebc"} aes-gcm = "0.10.3" ahash = "0.8.11" atty = "0.2.14" @@ -692,7 +693,7 @@ quote = "1.0.18" rand = "0.7.3" rand_core = "0.5.1" random_word = "0.3.0" -rayon = "1.5.2" +rayon = "1.10.0" redis = { version = "0.22.3", features = [ "tokio-comp", "script", diff --git a/aptos-move/framework/aptos-stdlib/sources/cryptography/blsttc.move b/aptos-move/framework/aptos-stdlib/sources/cryptography/blsttc.move new file mode 100644 index 0000000000000..dc013b1d9389e --- /dev/null +++ b/aptos-move/framework/aptos-stdlib/sources/cryptography/blsttc.move @@ -0,0 +1,1012 @@ +/// Contains functions for: +/// +/// The minimum-pubkey-size variant of [Boneh-Lynn-Shacham (BLS) signatures](https://en.wikipedia.org/wiki/BLS_digital_signature), +/// where public keys are BLS12-381 elliptic-curve points in $\mathbb{G}_1$ and signatures are in $\mathbb{G}_2$, +/// as per the [IETF BLS draft standard](https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-bls-signature#section-2.1). + + +// many things need to be update and implement properly, since it is just forked from bls12381 and modified for as per usecase for trials and move forward with work. + +module aptos_std::blsttc { + use std::option::{Self, Option}; + #[test_only] + use std::error::invalid_argument; + + /// The signature size, in bytes + const SIGNATURE_SIZE: u64 = 48; + + /// The public key size, in bytes + const PUBLIC_KEY_NUM_BYTES: u64 = 96; + + /// The caller was supposed to input one or more public keys. + const EZERO_PUBKEYS: u64 = 1; + + /// One of the given inputs has the wrong size.s + const EWRONG_SIZE: u64 = 2; + + /// The number of signers does not match the number of messages to be signed. + const E_NUM_SIGNERS_MUST_EQ_NUM_MESSAGES: u64 = 3; + + // TODO: Performance would increase if structs in this module are implemented natively via handles (similar to Table and + // RistrettoPoint). This will avoid unnecessary (de)serialization. We would need to allow storage of these structs too. + + #[test_only] + struct SecretKey has copy, drop { + bytes: vector, + } + + /// A *validated* public key that: + /// (1) is a point in the prime-order subgroup of the BLS12-381 elliptic curve, and + /// (2) is not the identity point + /// + /// This struct can be used to verify a normal (non-aggregated) signature. + /// + /// This struct can be combined with a ProofOfPossession struct in order to create a PublicKeyWithPop struct, which + /// can be used to verify a multisignature. + struct PublicKey has copy, drop, store { + bytes: vector + } + + // /// A proof-of-possession (PoP). + // /// Given such a struct and a PublicKey struct, one can construct a PublicKeyWithPoP (see below). + // struct ProofOfPossession has copy, drop, store { + // bytes: vector + // } + + /// A *validated* public key that had a successfully-verified proof-of-possession (PoP). + /// + /// A vector of these structs can be either: + /// (1) used to verify an aggregate signature + /// (2) aggregated with other PublicKeyWithPoP structs into an AggrPublicKeysWithPoP, which in turn can be used + /// to verify a multisignature + // struct PublicKeyWithPoP has copy, drop, store { + // bytes: vector + // } + + // /// An aggregation of public keys with verified PoPs, which can be used to verify multisignatures. + // struct AggrPublicKeysWithPoP has copy, drop, store { + // bytes: vector + // } + + /// A BLS signature. This can be either a: + /// (1) normal (non-aggregated) signature + /// (2) signature share (for a multisignature or aggregate signature) + struct Signature has copy, drop, store { + bytes: vector + } + + /// An aggregation of BLS signatures. This can be either a: + /// (4) aggregated signature (i.e., an aggregation of signatures s_i, each on a message m_i) + /// (3) multisignature (i.e., an aggregation of signatures s_i, each on the same message m) + /// + /// We distinguish between a Signature type and a AggrOrMultiSignature type to prevent developers from interchangeably + /// calling `verify_multisignature` and `verify_signature_share` to verify both multisignatures and signature shares, + /// which could create problems down the line. + struct AggrOrMultiSignature has copy, drop, store { + bytes: vector + } + + /// Creates a new public key from a sequence of bytes. + public fun public_key_from_bytes(bytes: vector): Option { + if (validate_pubkey_internal(bytes)) { + option::some(PublicKey { + bytes + }) + } else { + option::none() + } + } + + /// Serializes a public key into 48 bytes. + public fun public_key_to_bytes(pk: &PublicKey): vector { + pk.bytes + } + + /// Creates a new proof-of-possession (PoP) which can be later used to create a PublicKeyWithPoP struct, + // public fun proof_of_possession_from_bytes(bytes: vector): ProofOfPossession { + // ProofOfPossession { + // bytes + // } + // } + // + // /// Serializes the signature into 96 bytes. + // public fun proof_of_possession_to_bytes(pop: &ProofOfPossession): vector { + // pop.bytes + // } + // + // /// Creates a PoP'd public key from a normal public key and a corresponding proof-of-possession. + // public fun public_key_from_bytes_with_pop(pk_bytes: vector, pop: &ProofOfPossession): Option { + // if (verify_proof_of_possession_internal(pk_bytes, pop.bytes)) { + // option::some(PublicKeyWithPoP { + // bytes: pk_bytes + // }) + // } else { + // option::none() + // } + // } + // + // /// Creates a normal public key from a PoP'd public key. + // public fun public_key_with_pop_to_normal(pkpop: &PublicKeyWithPoP): PublicKey { + // PublicKey { + // bytes: pkpop.bytes + // } + // } + // + // /// Serializes a PoP'd public key into 48 bytes. + // public fun public_key_with_pop_to_bytes(pk: &PublicKeyWithPoP): vector { + // pk.bytes + // } + + /// Creates a new signature from a sequence of bytes. Does not check the signature for prime-order subgroup + /// membership since that is done implicitly during verification. + public fun signature_from_bytes(bytes: vector): Signature { + Signature { + bytes + } + } + + /// Serializes the signature into 96 bytes. + public fun signature_to_bytes(sig: &Signature): vector { + sig.bytes + } + + /// Checks that the group element that defines a signature is in the prime-order subgroup. + /// This check is implicitly performed when verifying any signature via this module, but we expose this functionality + /// in case it might be useful for applications to easily dismiss invalid signatures early on. + public fun signature_subgroup_check(signature: &Signature): bool { + signature_subgroup_check_internal(signature.bytes) + } + + /// Given a vector of public keys with verified PoPs, combines them into an *aggregated* public key which can be used + /// to verify multisignatures using `verify_multisignature` and aggregate signatures using `verify_aggregate_signature`. + /// Aborts if no public keys are given as input. + // public fun aggregate_pubkeys(public_keys: vector): AggrPublicKey { + // let (bytes, success) = aggregate_pubkeys_internal(public_keys); + // assert!(success, std::error::invalid_argument(EZERO_PUBKEYS)); + // + // AggrPublicKeysWithPoP { + // bytes + // } + // } + + // /// Serializes an aggregate public key into 48 bytes. + // public fun aggregate_pubkey_to_bytes(apk: &AggrPublicKeysWithPoP): vector { + // apk.bytes + // } + + /// Aggregates the input signatures into an aggregate-or-multi-signature structure, which can be later verified via + /// `verify_aggregate_signature` or `verify_multisignature`. Returns `None` if zero signatures are given as input + /// or if some of the signatures are not valid group elements. + public fun aggregate_signatures(signatures: vector): Option { + let (bytes, success) = aggregate_signatures_internal(signatures); + if (success) { + option::some( + AggrOrMultiSignature { + bytes + } + ) + } else { + option::none() + } + } + + /// Serializes an aggregate-or-multi-signature into 96 bytes. + public fun aggr_or_multi_signature_to_bytes(sig: &AggrOrMultiSignature): vector { + sig.bytes + } + + /// Deserializes an aggregate-or-multi-signature from 96 bytes. + public fun aggr_or_multi_signature_from_bytes(bytes: vector): AggrOrMultiSignature { + assert!(std::vector::length(&bytes) == SIGNATURE_SIZE, std::error::invalid_argument(EWRONG_SIZE)); + + AggrOrMultiSignature { + bytes + } + } + + + /// Checks that the group element that defines an aggregate-or-multi-signature is in the prime-order subgroup. + public fun aggr_or_multi_signature_subgroup_check(signature: &AggrOrMultiSignature): bool { + signature_subgroup_check_internal(signature.bytes) + } + + /// Verifies an aggregate signature, an aggregation of many signatures `s_i`, each on a different message `m_i`. + // public fun verify_aggregate_signature( + // aggr_sig: &AggrOrMultiSignature, + // public_keys: vector, + // messages: vector>, + // ): bool { + // verify_aggregate_signature_internal(aggr_sig.bytes, public_keys, messages) + // } + // + // /// Verifies a multisignature: an aggregation of many signatures, each on the same message `m`. + // public fun verify_multisignature( + // multisig: &AggrOrMultiSignature, + // aggr_public_key: &AggrPublicKeysWithPoP, + // message: vector + // ): bool { + // verify_multisignature_internal(multisig.bytes, aggr_public_key.bytes, message) + // } + + /// Verifies a normal, non-aggregated signature. + public fun verify_normal_signature( + signature: &Signature, + public_key: &PublicKey, + message: vector + ): bool { + verify_normal_signature_internal(signature.bytes, public_key.bytes, message) + } + + /// Verifies a signature share in the multisignature share or an aggregate signature share. + // public fun verify_signature_share( + // signature_share: &Signature, + // public_key: &PublicKeyWithPoP, + // message: vector + // ): bool { + // verify_signature_share_internal(signature_share.bytes, public_key.bytes, message) + // } + + #[test_only] + /// Generates a BLS key-pair: a secret key with its corresponding public key. + public fun generate_keys(): (SecretKey, PublicKey) { + let (sk_bytes, pk_bytes) = generate_keys_internal(); + let sk = SecretKey { + bytes: sk_bytes + }; + let pk = PublicKey { + bytes: pk_bytes + }; + (sk, pk) + } + + #[test_only] + /// Generates a BLS signature for a message with a signing key. + public fun sign_arbitrary_bytes(signing_key: &SecretKey, message: vector): Signature { + Signature { + bytes: sign_internal(signing_key.bytes, message) + } + } + + #[test_only] + /// Generates a multi-signature for a message with multiple signing keys. + public fun multi_sign_arbitrary_bytes(signing_keys: &vector, message: vector): AggrOrMultiSignature { + let n = std::vector::length(signing_keys); + let sigs = vector[]; + let i: u64 = 0; + while (i < n) { + let sig = sign_arbitrary_bytes(std::vector::borrow(signing_keys, i), message); + std::vector::push_back(&mut sigs, sig); + i = i + 1; + }; + let multisig = aggregate_signatures(sigs); + option::extract(&mut multisig) + } + + #[test_only] + /// Generates an aggregated signature over all messages in messages, where signing_keys[i] signs messages[i]. + public fun aggr_sign_arbitrary_bytes( + signing_keys: &vector, + messages: &vector> + ): AggrOrMultiSignature { + let signing_key_count = std::vector::length(signing_keys); + let message_count = std::vector::length(messages); + assert!(signing_key_count == message_count, invalid_argument(E_NUM_SIGNERS_MUST_EQ_NUM_MESSAGES)); + let sigs = vector[]; + let i: u64 = 0; + while (i < signing_key_count) { + let sig = sign_arbitrary_bytes(std::vector::borrow(signing_keys, i), *std::vector::borrow(messages, i)); + std::vector::push_back(&mut sigs, sig); + i = i + 1; + }; + let aggr_sig = aggregate_signatures(sigs); + option::extract(&mut aggr_sig) + } + + #[test_only] + /// Returns a mauled copy of a byte array. + public fun maul_bytes(bytes: &vector): vector { + let new_bytes = *bytes; + let first_byte = std::vector::borrow_mut(&mut new_bytes, 0); + *first_byte = *first_byte ^ 0xff; + new_bytes + } + + #[test_only] + /// Returns a mauled copy of a normal signature. + public fun maul_signature(sig: &Signature): Signature { + Signature { + bytes: maul_bytes(&signature_to_bytes(sig)) + } + } + + #[test_only] + /// Returns a mauled copy of an aggregated signature or a multi-signature. + public fun maul_aggr_or_multi_signature(sig: &AggrOrMultiSignature): AggrOrMultiSignature { + AggrOrMultiSignature { + bytes: maul_bytes(&aggr_or_multi_signature_to_bytes(sig)) + } + } + + #[test_only] + /// Returns a mauled copy of a normal public key. + public fun maul_public_key(pk: &PublicKey): PublicKey { + PublicKey { + bytes: maul_bytes(&public_key_to_bytes(pk)) + } + } + + // #[test_only] + // /// Returns a mauled copy of a PoP'd public key. + // public fun maul_public_key_with_pop(pk: &PublicKeyWithPoP): PublicKeyWithPoP { + // PublicKeyWithPoP { + // bytes: maul_bytes(&public_key_with_pop_to_bytes(pk)) + // } + // } + // + // #[test_only] + // /// Returns a mauled copy of an aggregated public key. + // public fun maul_aggregated_public_key(pk: &AggrPublicKeysWithPoP): AggrPublicKeysWithPoP { + // AggrPublicKeysWithPoP { + // bytes: maul_bytes(&aggregate_pubkey_to_bytes(pk)) + // } + // } + // + // #[test_only] + // /// Returns a mauled copy of a proof-of-possession. + // public fun maul_proof_of_possession(pop: &ProofOfPossession): ProofOfPossession { + // ProofOfPossession { + // bytes: maul_bytes(&proof_of_possession_to_bytes(pop)) + // } + // } + // + // + // #[test_only] + // /// Generates a proof-of-possession (PoP) for the public key associated with the secret key `sk`. + // public fun generate_proof_of_possession(sk: &SecretKey): ProofOfPossession { + // ProofOfPossession { + // bytes: generate_proof_of_possession_internal(sk.bytes) + // } + // } + + // + // Native functions + // + + /// CRYPTOGRAPHY WARNING: This function assumes that the caller verified all public keys have a valid + /// proof-of-possesion (PoP) using `verify_proof_of_possession`. + /// + /// Given a vector of serialized public keys, combines them into an aggregated public key, returning `(bytes, true)`, + /// where `bytes` store the serialized public key. + /// Aborts if no public keys are given as input. + native fun aggregate_pubkeys_internal(public_keys: vector): (vector, bool); + + + /// CRYPTOGRAPHY WARNING: This function can be safely called without verifying that the input signatures are elements + /// of the prime-order subgroup of the BLS12-381 curve. + /// + /// Given a vector of serialized signatures, combines them into an aggregate signature, returning `(bytes, true)`, + /// where `bytes` store the serialized signature. + /// Does not check the input signatures nor the final aggregated signatures for prime-order subgroup membership. + /// Returns `(_, false)` if no signatures are given as input. + /// Does not abort. + native fun aggregate_signatures_internal(signatures: vector): (vector, bool); + + /// Return `true` if the bytes in `public_key` are a valid BLS12-381 public key: + /// (1) it is NOT the identity point, and + /// (2) it is a BLS12-381 elliptic curve point, and + /// (3) it is a prime-order point + /// Return `false` otherwise. + /// Does not abort. + native fun validate_pubkey_internal(public_key: vector): bool; + + /// Return `true` if the elliptic curve point serialized in `signature`: + /// (1) is NOT the identity point, and + /// (2) is a BLS12-381 elliptic curve point, and + /// (3) is a prime-order point + /// Return `false` otherwise. + /// Does not abort. + native fun signature_subgroup_check_internal(signature: vector): bool; + + /// CRYPTOGRAPHY WARNING: First, this function assumes all public keys have a valid proof-of-possesion (PoP). + /// This prevents both small-subgroup attacks and rogue-key attacks. Second, this function can be safely called + /// without verifying that the aggregate signature is in the prime-order subgroup of the BLS12-381 curve. + /// + /// Returns `true` if the aggregate signature `aggsig` on `messages` under `public_keys` verifies (where `messages[i]` + /// should be signed by `public_keys[i]`). + /// + /// Returns `false` if either: + /// - no public keys or messages are given as input, + /// - number of messages does not equal number of public keys + /// - `aggsig` (1) is the identity point, or (2) is NOT a BLS12-381 elliptic curve point, or (3) is NOT a + /// prime-order point + /// Does not abort. + native fun verify_aggregate_signature_internal( + aggsig: vector, + public_keys: vector, + messages: vector>, + ): bool; + + /// CRYPTOGRAPHY WARNING: This function assumes verified proofs-of-possesion (PoP) for the public keys used in + /// computing the aggregate public key. This prevents small-subgroup attacks and rogue-key attacks. + /// + /// Return `true` if the BLS `multisignature` on `message` verifies against the BLS aggregate public key `agg_public_key`. + /// Returns `false` otherwise. + /// Does not abort. + native fun verify_multisignature_internal( + multisignature: vector, + agg_public_key: vector, + message: vector + ): bool; + + /// CRYPTOGRAPHY WARNING: This function WILL check that the public key is a prime-order point, in order to prevent + /// library users from misusing the library by forgetting to validate public keys before giving them as arguments to + /// this function. + /// + /// Returns `true` if the `signature` on `message` verifies under `public key`. + /// Returns `false` otherwise. + /// Does not abort. + native fun verify_normal_signature_internal( + signature: vector, + public_key: vector, + message: vector + ): bool; + + /// Return `true` if the bytes in `public_key` are a valid bls12381 public key (as per `validate_pubkey`) + /// *and* this public key has a valid proof-of-possesion (PoP). + /// Return `false` otherwise. + /// Does not abort. + native fun verify_proof_of_possession_internal( + public_key: vector, + proof_of_possesion: vector + ): bool; + + /// CRYPTOGRAPHY WARNING: Assumes the public key has a valid proof-of-possesion (PoP). This prevents rogue-key + /// attacks later on during signature aggregation. + /// + /// Returns `true` if the `signature_share` on `message` verifies under `public key`. + /// Returns `false` otherwise, similar to `verify_multisignature`. + /// Does not abort. + native fun verify_signature_share_internal( + signature_share: vector, + public_key: vector, + message: vector + ): bool; + + #[test_only] + native fun generate_keys_internal(): (vector, vector); + + #[test_only] + native fun sign_internal(sk: vector, msg: vector): vector; + + #[test_only] + native fun generate_proof_of_possession_internal(sk: vector): vector; + + // + // Constants and helpers for tests + // + + /// Random signature generated by running `cargo test -- bls12381_sample_signature --nocapture --include-ignored` in `crates/aptos-crypto`. + /// The message signed is "Hello Aptos!" and the associated SK is 07416693b6b32c84abe45578728e2379f525729e5b94762435a31e65ecc728da. + const RANDOM_SIGNATURE: vector = x"a01a65854f987d3434149b7f08f70730e30b241984e8712bc2aca885d632aafced4c3f661209debb6b1c8601326623cc16ca2f6c9edc53b7b88b7435fb6b05ddece418d2c34dc6aca2f5a11a79e67774582c14084a01dcb7820e4cb4bad0ea8d"; + + /// Random signature generated by running `cargo test -- bls12381_sample_signature --nocapture --include-ignored` in `crates/aptos-crypto`. + /// The associated SK is 07416693b6b32c84abe45578728e2379f525729e5b94762435a31e65ecc728da. + const RANDOM_PK: vector = x"8a53e7ae5270e3e765cd8a4032c2e77c6f7e87a44ebb85bf28a4d7865565698f975346714262f9e47c6f3e0d5d951660"; + + // + // Tests + // + + #[test_only] + fun get_random_aggsig(): AggrOrMultiSignature { + assert!(signature_subgroup_check_internal(RANDOM_SIGNATURE), 1); + + AggrOrMultiSignature { bytes: RANDOM_SIGNATURE } + } + + // #[test_only] + // fun get_random_pk_with_pop(): PublicKey { + // assert!(validate_pubkey_internal(RANDOM_PK), 1); + // + // PublicKeyWithPoP { + // bytes: RANDOM_PK + // } + // } + + #[test] + fun test_pubkey_validation() { + // test low order points (in group for PK) + assert!( + option::is_none( + &public_key_from_bytes( + x"ae3cd9403b69c20a0d455fd860e977fe6ee7140a7f091f26c860f2caccd3e0a7a7365798ac10df776675b3a67db8faa0" + ) + ), + 1 + ); + assert!( + option::is_none( + &public_key_from_bytes( + x"928d4862a40439a67fd76a9c7560e2ff159e770dcf688ff7b2dd165792541c88ee76c82eb77dd6e9e72c89cbf1a56a68" + ) + ), + 1 + ); + assert!( + option::is_some( + &public_key_from_bytes( + x"b3e4921277221e01ed71284be5e3045292b26c7f465a6fcdba53ee47edd39ec5160da3b229a73c75671024dcb36de091" + ) + ), + 1 + ); + } +} + // #[test] + // #[expected_failure(abort_code = 65537, location = Self)] + // fun test_empty_pubkey_aggregation() { + // // First, make sure if no inputs are given, the function returns None + // // assert!(aggregate_pop_verified_pubkeys(vector::empty()) == option::none(), 1); + // aggregate_pubkeys(std::vector::empty()); + // } + // + // #[test] + // fun test_pubkey_aggregation() { + // // Second, try some test-cases generated by running the following command in `crates/aptos-crypto`: + // // $ cargo test -- sample_aggregate_pk_and_multisig --nocapture --include-ignored + // let pks = vector[ + // PublicKeyWithPoP { bytes: x"92e201a806af246f805f460fbdc6fc90dd16a18d6accc236e85d3578671d6f6690dde22134d19596c58ce9d63252410a" }, + // PublicKeyWithPoP { bytes: x"ab9df801c6f96ade1c0490c938c87d5bcc2e52ccb8768e1b5d14197c5e8bfa562783b96711b702dda411a1a9f08ebbfa" }, + // PublicKeyWithPoP { bytes: x"b698c932cf7097d99c17bd6e9c9dc4eeba84278c621700a8f80ec726b1daa11e3ab55fc045b4dbadefbeef05c4182494" }, + // PublicKeyWithPoP { bytes: x"934706a8b876d47a996d427e1526ce52c952d5ec0858d49cd262efb785b62b1972d06270b0a7adda1addc98433ad1843" }, + // PublicKeyWithPoP { bytes: x"a4cd352daad3a0651c1998dfbaa7a748e08d248a54347544bfedd51a197e016bb6008e9b8e45a744e1a030cc3b27d2da" }, + // ]; + // + // // agg_pks[i] = \sum_{j <= i} pk[j] + // let agg_pks = vector[ + // AggrPublicKeysWithPoP { bytes: x"92e201a806af246f805f460fbdc6fc90dd16a18d6accc236e85d3578671d6f6690dde22134d19596c58ce9d63252410a" }, + // AggrPublicKeysWithPoP { bytes: x"b79ad47abb441d7eda9b220a626df2e4e4910738c5f777947f0213398ecafae044ec0c20d552d1348347e9abfcf3eca1" }, + // AggrPublicKeysWithPoP { bytes: x"b5f5eb6153ab5388a1a76343d714e4a2dcf224c5d0722d1e8e90c6bcead05c573fffe986460bd4000645a655bf52bc60" }, + // AggrPublicKeysWithPoP { bytes: x"b922006ec14c183572a8864c31dc6632dccffa9f9c86411796f8b1b5a93a2457762c8e2f5ef0a2303506c4bca9a4e0bf" }, + // AggrPublicKeysWithPoP { bytes: x"b53df1cfee2168f59e5792e710bf22928dc0553e6531dae5c7656c0a66fc12cb82fbb04863938c953dc901a5a79cc0f3" }, + // ]; + // + // let i = 0; + // let accum_pk = std::vector::empty(); + // while (i < std::vector::length(&pks)) { + // std::vector::push_back(&mut accum_pk, *std::vector::borrow(&pks, i)); + // + // let apk = aggregate_pubkeys(accum_pk); + // + // // Make sure PKs were aggregated correctly + // assert!(apk == *std::vector::borrow(&agg_pks, i), 1); + // assert!(validate_pubkey_internal(apk.bytes), 1); + // + // i = i + 1; + // }; + // } + // + // #[test] + // fun test_pubkey_validation_against_invalid_keys() { + // let (_sk, pk) = generate_keys(); + // let pk_bytes = public_key_with_pop_to_bytes(&pk); + // assert!(option::is_some(&public_key_from_bytes(pk_bytes)), 1); + // assert!(option::is_none(&public_key_from_bytes(maul_bytes(&pk_bytes))), 1); + // } + + // #[test] + // fun test_signature_aggregation() { + // // First, test empty aggregation + // assert!(option::is_none(&mut aggregate_signatures(vector[])), 1); + // + // // Second, try some test-cases generated by running the following command in `crates/aptos-crypto`: + // // $ cargo test -- sample_aggregate_sigs --nocapture --include-ignored + // + // // Signatures of each signer i + // let sigs = vector[ + // signature_from_bytes(x"a55ac2d64b4c1d141b15d876d3e54ad1eea07ee488e8287cce7cdf3eec551458ab5795ab196f8c112590346f7bc7c97e0053cd5be0f9bd74b93a87cd44458e98d125d6d5c6950ea5e62666beb34422ead79121f8cb0815dae41a986688d03eaf"), + // signature_from_bytes(x"90a639a44491191c46379a843266c293de3a46197714ead2ad3886233dd5c2b608b6437fa32fbf9d218b20f1cbfa7970182663beb9c148e2e9412b148e16abf283ffa51b8a536c0e55d61b2e5c849edc49f636c0ef07cb99f125cbcf602e22bb"), + // signature_from_bytes(x"9527d81aa15863ef3a3bf96bea6d58157d5063a93a6d0eb9d8b4f4bbda3b31142ec4586cb519da2cd7600941283d1bad061b5439703fd584295b44037a969876962ae1897dcc7cadf909d06faae213c4fef8e015dfb33ec109af02ab0c3f6833"), + // signature_from_bytes(x"a54d264f5cab9654b1744232c4650c42b29adf2b19bd00bbdaf4a4d792ee4dfd40a1fe1b067f298bcfd8ae4fdc8250660a2848bd4a80d96585afccec5c6cfa617033dd7913c9acfdf98a72467e8a5155d4cad589a72d6665be7cb410aebc0068"), + // signature_from_bytes(x"8d22876bdf73e6ad36ed98546018f6258cd47e45904b87c071e774a6ef4b07cac323258cb920b2fe2b07cca1f2b24bcb0a3194ec76f32edb92391ed2c39e1ada8919f8ea755c5e39873d33ff3a8f4fba21b1261c1ddb9d1688c2b40b77e355d1"), + // ]; + // + // // multisigs[i] is a signature on "Hello, Aptoverse!" from signers 1 through i (inclusive) + // let multisigs = vector[ + // AggrOrMultiSignature { bytes: x"a55ac2d64b4c1d141b15d876d3e54ad1eea07ee488e8287cce7cdf3eec551458ab5795ab196f8c112590346f7bc7c97e0053cd5be0f9bd74b93a87cd44458e98d125d6d5c6950ea5e62666beb34422ead79121f8cb0815dae41a986688d03eaf" }, + // AggrOrMultiSignature { bytes: x"8f1949a06b95c3cb62898d861f889350c0d2cb740da513bfa195aa0ab8fa006ea2efe004a7bbbd9bb363637a279aed20132efd0846f520e7ee0e8ed847a1c6969bb986ad2239bcc9af561b6c2aa6d3016e1c722146471f1e28313de189fe7ebc" }, + // AggrOrMultiSignature { bytes: x"ab5ad42bb8f350f8a6b4ae897946a05dbe8f2b22db4f6c37eff6ff737aebd6c5d75bd1abdfc99345ac8ec38b9a449700026f98647752e1c99f69bb132340f063b8a989728e0a3d82a753740bf63e5d8f51e413ebd9a36f6acbe1407a00c4b3e7" }, + // AggrOrMultiSignature { bytes: x"ae307a0d055d3ba55ad6ec7094adef27ed821bdcf735fb509ab2c20b80952732394bc67ea1fd8c26ea963540df7448f8102509f7b8c694e4d75f30a43c455f251b6b3fd8b580b9228ffeeb9039834927aacefccd3069bef4b847180d036971cf" }, + // AggrOrMultiSignature { bytes: x"8284e4e3983f29cb45020c3e2d89066df2eae533a01cb6ca2c4d466b5e02dd22467f59640aa120db2b9cc49e931415c3097e3d54ff977fd9067b5bc6cfa1c885d9d8821aef20c028999a1d97e783ae049d8fa3d0bbac36ce4ca8e10e551d3461" }, + // ]; + // + // let i = 0; + // let accum_sigs = std::vector::empty(); + // while (i < std::vector::length(&sigs)) { + // std::vector::push_back(&mut accum_sigs, *std::vector::borrow(&sigs, i)); + // + // let multisig = option::extract(&mut aggregate_signatures(accum_sigs)); + // + // // Make sure sigs were aggregated correctly + // assert!(multisig == *std::vector::borrow(&multisigs, i), 1); + // assert!(signature_subgroup_check_internal(multisig.bytes), 1); + // + // i = i + 1; + // }; + // } + + // #[test] + // fun test_empty_signature_aggregation() { + // assert!(option::is_none(&mut aggregate_signatures(vector[])), 1); + // } +// +// #[test] +// fun test_verify_multisig() { +// // Second, try some test-cases generated by running the following command in `crates/aptos-crypto`: +// // $ cargo test -- sample_aggregate_pk_and_multisig --nocapture --include-ignored +// let pks = vector[ +// PublicKeyWithPoP { bytes: x"92e201a806af246f805f460fbdc6fc90dd16a18d6accc236e85d3578671d6f6690dde22134d19596c58ce9d63252410a" }, +// PublicKeyWithPoP { bytes: x"ab9df801c6f96ade1c0490c938c87d5bcc2e52ccb8768e1b5d14197c5e8bfa562783b96711b702dda411a1a9f08ebbfa" }, +// PublicKeyWithPoP { bytes: x"b698c932cf7097d99c17bd6e9c9dc4eeba84278c621700a8f80ec726b1daa11e3ab55fc045b4dbadefbeef05c4182494" }, +// PublicKeyWithPoP { bytes: x"934706a8b876d47a996d427e1526ce52c952d5ec0858d49cd262efb785b62b1972d06270b0a7adda1addc98433ad1843" }, +// PublicKeyWithPoP { bytes: x"a4cd352daad3a0651c1998dfbaa7a748e08d248a54347544bfedd51a197e016bb6008e9b8e45a744e1a030cc3b27d2da" }, +// ]; +// +// // agg_pks[i] = \sum_{j <= i} pk[j] +// let agg_pks = vector[ +// AggrPublicKeysWithPoP { bytes: x"92e201a806af246f805f460fbdc6fc90dd16a18d6accc236e85d3578671d6f6690dde22134d19596c58ce9d63252410a" }, +// AggrPublicKeysWithPoP { bytes: x"b79ad47abb441d7eda9b220a626df2e4e4910738c5f777947f0213398ecafae044ec0c20d552d1348347e9abfcf3eca1" }, +// AggrPublicKeysWithPoP { bytes: x"b5f5eb6153ab5388a1a76343d714e4a2dcf224c5d0722d1e8e90c6bcead05c573fffe986460bd4000645a655bf52bc60" }, +// AggrPublicKeysWithPoP { bytes: x"b922006ec14c183572a8864c31dc6632dccffa9f9c86411796f8b1b5a93a2457762c8e2f5ef0a2303506c4bca9a4e0bf" }, +// AggrPublicKeysWithPoP { bytes: x"b53df1cfee2168f59e5792e710bf22928dc0553e6531dae5c7656c0a66fc12cb82fbb04863938c953dc901a5a79cc0f3" }, +// ]; +// +// // multisigs[i] is a signature on "Hello, Aptoverse!" under agg_pks[i] +// let multisigs = vector[ +// AggrOrMultiSignature { bytes: x"ade45c67bff09ae57e0575feb0be870f2d351ce078e8033d847615099366da1299c69497027b77badb226ff1708543cd062597030c3f1553e0aef6c17e7af5dd0de63c1e4f1f9da68c966ea6c1dcade2cdc646bd5e8bcd4773931021ec5be3fd" }, +// AggrOrMultiSignature { bytes: x"964af3d83436f6a9a382f34590c0c14e4454dc1de536af205319ce1ed417b87a2374863d5df7b7d5ed900cf91dffa7a105d3f308831d698c0d74fb2259d4813434fb86425db0ded664ae8f85d02ec1d31734910317d4155cbf69017735900d4d" }, +// AggrOrMultiSignature { bytes: x"b523a31813e771e55aa0fc99a48db716ecc1085f9899ccadb64e759ecb481a2fb1cdcc0b266f036695f941361de773081729311f6a1bca9d47393f5359c8c87dc34a91f5dae335590aacbff974076ad1f910dd81750553a72ccbcad3c8cc0f07" }, +// AggrOrMultiSignature { bytes: x"a945f61699df58617d37530a85e67bd1181349678b89293951ed29d1fb7588b5c12ebb7917dfc9d674f3f4fde4d062740b85a5f4927f5a4f0091e46e1ac6e41bbd650a74dd49e91445339d741e3b10bdeb9bc8bba46833e0011ff91fa5c77bd2" }, +// AggrOrMultiSignature { bytes: x"b627b2cfd8ae59dcf5e58cc6c230ae369985fd096e1bc3be38da5deafcbed7d939f07cccc75383539940c56c6b6453db193f563f5b6e4fe54915afd9e1baea40a297fa7eda74abbdcd4cc5c667d6db3b9bd265782f7693798894400f2beb4637" }, +// ]; +// +// let i = 0; +// let accum_pk = std::vector::empty(); +// while (i < std::vector::length(&pks)) { +// std::vector::push_back(&mut accum_pk, *std::vector::borrow(&pks, i)); +// +// let apk = aggregate_pubkeys(accum_pk); +// +// assert!(apk == *std::vector::borrow(&agg_pks, i), 1); +// +// assert!(verify_multisignature(std::vector::borrow(&multisigs, i), &apk, b"Hello, Aptoverse!"), 1); +// +// i = i + 1; +// }; +// } +// +// #[test] +// fun test_verify_multisignature_randomized() { +// let signer_count = 1; +// let max_signer_count = 5; +// let msg = b"hello world"; +// while (signer_count <= max_signer_count) { +// // Generate key pairs. +// let signing_keys = vector[]; +// let public_keys = vector[]; +// let i = 0; +// while (i < signer_count) { +// let (sk, pk) = generate_keys(); +// std::vector::push_back(&mut signing_keys, sk); +// std::vector::push_back(&mut public_keys, pk); +// i = i + 1; +// }; +// +// // Generate multi-signature. +// let aggr_pk = aggregate_pubkeys(public_keys); +// let multisig = multi_sign_arbitrary_bytes(&signing_keys, msg); +// +// // Test signature verification. +// assert!(verify_multisignature(&multisig, &aggr_pk, msg), 1); +// assert!(!verify_multisignature(&maul_aggr_or_multi_signature(&multisig), &aggr_pk, msg), 1); +// assert!(!verify_multisignature(&multisig, &maul_aggregated_public_key(&aggr_pk), msg), 1); +// assert!(!verify_multisignature(&multisig, &aggr_pk, maul_bytes(&msg)), 1); +// +// // Also test signature aggregation. +// let signatures = vector[]; +// let i = 0; +// while (i < signer_count) { +// let sk = std::vector::borrow(&signing_keys, i); +// let sig = sign_arbitrary_bytes(sk, msg); +// std::vector::push_back(&mut signatures, sig); +// i = i + 1; +// }; +// let aggregated_signature = option::extract(&mut aggregate_signatures(signatures)); +// assert!(aggr_or_multi_signature_subgroup_check(&aggregated_signature), 1); +// assert!(aggr_or_multi_signature_to_bytes(&aggregated_signature) == aggr_or_multi_signature_to_bytes(&multisig), 1); +// +// signer_count = signer_count + 1; +// } +// } +// +// #[test] +// fun test_verify_aggsig() { +// assert!(aggr_or_multi_signature_to_bytes(&aggr_or_multi_signature_from_bytes(RANDOM_SIGNATURE)) == RANDOM_SIGNATURE, 1); +// +// // First, make sure verification returns None when no inputs are given or |pks| != |msgs| +// assert!(verify_aggregate_signature(&get_random_aggsig(), vector[], vector[]) == false, 1); +// +// assert!(verify_aggregate_signature( +// &get_random_aggsig(), +// vector[ get_random_pk_with_pop() ], +// vector[]) == false, 1); +// +// assert!(verify_aggregate_signature( +// &get_random_aggsig(), +// vector[], +// vector[ x"ab" ]) == false, 1); +// +// assert!(verify_aggregate_signature( +// &get_random_aggsig(), +// vector[ get_random_pk_with_pop() ], +// vector[ +// x"cd", x"ef" +// ]) == false, 1); +// +// assert!(verify_aggregate_signature( +// &get_random_aggsig(), +// vector[ +// get_random_pk_with_pop(), +// get_random_pk_with_pop(), +// get_random_pk_with_pop(), +// ], +// vector[ +// x"cd", x"ef" +// ]) == false, 1); +// +// // Second, try some test-cases generated by running the following command in `crates/aptos-crypto`: +// // $ cargo test -- bls12381_sample_aggregate_pk_and_aggsig --nocapture --ignored +// +// // The signed messages are "Hello, Aptos !", where \in {1, ..., 5} +// let msgs = vector[ +// x"48656c6c6f2c204170746f73203121", +// x"48656c6c6f2c204170746f73203221", +// x"48656c6c6f2c204170746f73203321", +// x"48656c6c6f2c204170746f73203421", +// x"48656c6c6f2c204170746f73203521", +// ]; +// +// // Public key of signer i +// let pks = vector[ +// PublicKeyWithPoP { bytes: x"b93d6aabb2b83e52f4b8bda43c24ea920bbced87a03ffc80f8f70c814a8b3f5d69fbb4e579ca76ee008d61365747dbc6" }, +// PublicKeyWithPoP { bytes: x"b45648ceae3a983bcb816a96db599b5aef3b688c5753fa20ce36ac7a4f2c9ed792ab20af6604e85e42dab746398bb82c" }, +// PublicKeyWithPoP { bytes: x"b3e4921277221e01ed71284be5e3045292b26c7f465a6fcdba53ee47edd39ec5160da3b229a73c75671024dcb36de091" }, +// PublicKeyWithPoP { bytes: x"8463b8671c9775a7dbd98bf76d3deba90b5a90535fc87dc8c13506bb5c7bbd99be4d257e60c548140e1e30b107ff5822" }, +// PublicKeyWithPoP { bytes: x"a79e3d0e9d04587a3b27d05efe5717da05fd93485dc47978c866dc70a01695c2efd247d1dd843a011a4b6b24079d7384" }, +// ]; +// +// // aggsigs[i] = \sum_{j <= i} sigs[j], where sigs[j] is a signature on msgs[j] under pks[j] +// let aggsigs = vector[ +// AggrOrMultiSignature { bytes: x"a2bc8bdebe6215ba74b5b53c5ed2aa0c68221a4adf868989ccdcfb62bb0eecc6537def9ee686a7960169c5917d25e5220177ed1c5e95ecfd68c09694062e76efcb00759beac874e4f9a715fd144210883bf9bb272f156b0a1fa15d0e9460f01f" }, +// AggrOrMultiSignature { bytes: x"a523aa3c3f1f1074d968ffecf017c7b93ae5243006bf0abd2e45c036ddbec99302984b650ebe5ba306cda4071d281ba50a99ef0e66c3957fab94163296f9d673fc58a36de4276f82bfb1d9180b591df93b5c2804d40dd68cf0f72cd92f86442e" }, +// AggrOrMultiSignature { bytes: x"abed10f464de74769121fc09715e59a3ac96a5054a43a9d43cc890a2d4d332614c74c7fb4cceef6d25f85c65dee337330f062f89f23fec9ecf7ce3193fbba2c886630d753be6a4513a4634428904b767af2f230c5cadbcb53a451dd9c7d977f6" }, +// AggrOrMultiSignature { bytes: x"8362871631ba822742a31209fa4abce6dc94b741ac4725995459da2951324b51efbbf6bc3ab4681e547ebfbadd80e0360dc078c04188198f0acea26c12645ace9107a4a23cf8db46abc7a402637f16a0477c72569fc9966fe804ef4dc0e5e758" }, +// AggrOrMultiSignature { bytes: x"a44d967935fbe63a763ce2dd2b16981f967ecd31e20d3266eef5517530cdc233c8a18273b6d9fd7f61dd39178826e3f115df4e7b304f2de17373a95ea0c9a14293dcfd6f0ef416e06fa23f6a3c850d638e4d8f97ab4562ef55d49a96a50baa13" }, +// ]; +// +// let i = 0; +// let msg_subset = std::vector::empty>(); +// let pk_subset = std::vector::empty(); +// while (i < std::vector::length(&pks)) { +// let aggsig = *std::vector::borrow(&aggsigs, i); +// +// std::vector::push_back(&mut pk_subset, *std::vector::borrow(&pks, i)); +// std::vector::push_back(&mut msg_subset, *std::vector::borrow(&msgs, i)); +// +// assert!(verify_aggregate_signature(&aggsig, pk_subset, msg_subset), 1); +// +// i = i + 1; +// }; +// } +// +// #[test] +// fun test_verify_aggregated_signature_randomized() { +// let signer_count = 1; +// let max_signer_count = 5; +// while (signer_count <= max_signer_count) { +// // Generate key pairs and messages. +// let signing_keys = vector[]; +// let public_keys = vector[]; +// let messages: vector> = vector[]; +// let i = 0; +// while (i < signer_count) { +// let (sk, pk) = generate_keys(); +// std::vector::push_back(&mut signing_keys, sk); +// std::vector::push_back(&mut public_keys, pk); +// let msg: vector = vector[104, 101, 108, 108, 111, 32, 97, 112, 116, 111, 115, 32, 117, 115, 101, 114, 32, 48+(i as u8)]; //"hello aptos user {i}" +// std::vector::push_back(&mut messages, msg); +// i = i + 1; +// }; +// +// // Maul messages and public keys. +// let mauled_public_keys = vector[maul_public_key_with_pop(std::vector::borrow(&public_keys, 0))]; +// let mauled_messages = vector[maul_bytes(std::vector::borrow(&messages, 0))]; +// let i = 1; +// while (i < signer_count) { +// let pk = std::vector::borrow(&public_keys, i); +// let msg = std::vector::borrow(&messages, i); +// std::vector::push_back(&mut mauled_public_keys, *pk); +// std::vector::push_back(&mut mauled_messages, *msg); +// i = i + 1; +// }; +// +// // Generate aggregated signature. +// let aggrsig = aggr_sign_arbitrary_bytes(&signing_keys, &messages); +// +// // Test signature verification. +// assert!(verify_aggregate_signature(&aggrsig, public_keys, messages), 1); +// assert!(!verify_aggregate_signature(&maul_aggr_or_multi_signature(&aggrsig), public_keys, messages), 1); +// assert!(!verify_aggregate_signature(&aggrsig, mauled_public_keys, messages), 1); +// assert!(!verify_aggregate_signature(&aggrsig, public_keys, mauled_messages), 1); +// +// // Also test signature aggregation. +// let signatures = vector[]; +// let i = 0; +// while (i < signer_count) { +// let sk = std::vector::borrow(&signing_keys, i); +// let msg = std::vector::borrow(&messages, i); +// let sig = sign_arbitrary_bytes(sk, *msg); +// std::vector::push_back(&mut signatures, sig); +// i = i + 1; +// }; +// let aggrsig_another = option::extract(&mut aggregate_signatures(signatures)); +// assert!(aggr_or_multi_signature_to_bytes(&aggrsig_another) == aggr_or_multi_signature_to_bytes(&aggrsig), 1); +// +// signer_count = signer_count + 1; +// } +// } +// +// #[test] +// /// Tests verification of a random BLS signature created using sk = x"" +// fun test_verify_normal_and_verify_sigshare() { +// // Test case generated by running `cargo test -- bls12381_sample_signature --nocapture --include-ignored` in +// // `crates/aptos-crypto` +// // ============================================================================================================= +// // SK: 077c8a56f26259215a4a245373ab6ddf328ac6e00e5ea38d8700efa361bdc58d +// +// let message = b"Hello Aptos!"; +// +// // First, test signatures that verify +// let ok = verify_normal_signature( +// &signature_from_bytes(x"b01ce4632e94d8c611736e96aa2ad8e0528a02f927a81a92db8047b002a8c71dc2d6bfb94729d0973790c10b6ece446817e4b7543afd7ca9a17c75de301ae835d66231c26a003f11ae26802b98d90869a9e73788c38739f7ac9d52659e1f7cf7"), +// &option::extract(&mut public_key_from_bytes(x"94209a296b739577cb076d3bfb1ca8ee936f29b69b7dae436118c4dd1cc26fd43dcd16249476a006b8b949bf022a7858")), +// message, +// ); +// assert!(ok == true, 1); +// +// let pk = option::extract(&mut public_key_from_bytes(x"94209a296b739577cb076d3bfb1ca8ee936f29b69b7dae436118c4dd1cc26fd43dcd16249476a006b8b949bf022a7858")); +// let pk_with_pop = PublicKeyWithPoP { bytes: pk.bytes }; +// +// let ok = verify_signature_share( +// &signature_from_bytes(x"b01ce4632e94d8c611736e96aa2ad8e0528a02f927a81a92db8047b002a8c71dc2d6bfb94729d0973790c10b6ece446817e4b7543afd7ca9a17c75de301ae835d66231c26a003f11ae26802b98d90869a9e73788c38739f7ac9d52659e1f7cf7"), +// &pk_with_pop, +// message, +// ); +// assert!(ok == true, 1); +// +// // Second, test signatures that do NOT verify +// let sigs = vector[ +// Signature { bytes: x"a01ce4632e94d8c611736e96aa2ad8e0528a02f927a81a92db8047b002a8c71dc2d6bfb94729d0973790c10b6ece446817e4b7543afd7ca9a17c75de301ae835d66231c26a003f11ae26802b98d90869a9e73788c38739f7ac9d52659e1f7cf7" }, +// Signature { bytes: x"b01ce4632e94d8c611736e96aa2ad8e0528a02f927a81a92db8047b002a8c71dc2d6bfb94729d0973790c10b6ece446817e4b7543afd7ca9a17c75de301ae835d66231c26a003f11ae26802b98d90869a9e73788c38739f7ac9d52659e1f7cf7" }, +// Signature { bytes: x"b01ce4632e94d8c611736e96aa2ad8e0528a02f927a81a92db8047b002a8c71dc2d6bfb94729d0973790c10b6ece446817e4b7543afd7ca9a17c75de301ae835d66231c26a003f11ae26802b98d90869a9e73788c38739f7ac9d52659e1f7cf7" }, +// ]; +// let pks = vector[ +// x"94209a296b739577cb076d3bfb1ca8ee936f29b69b7dae436118c4dd1cc26fd43dcd16249476a006b8b949bf022a7858", +// x"ae4851bb9e7782027437ed0e2c026dd63b77a972ddf4bd9f72bcc218e327986568317e3aa9f679c697a2cb7cebf992f3", +// x"82ed7bb5528303a2e306775040a7309e0bd597b70d9949d8c6198a01a7be0b00079320ebfeaf7bbd5bfe86809940d252", +// ]; +// let messages = vector[ +// b"Hello Aptos!", +// b"Hello Aptos!", +// b"Bello Aptos!", +// ]; +// +// let i = 0; +// while (i < std::vector::length(&pks)) { +// let sig = std::vector::borrow(&sigs, i); +// let pk = *std::vector::borrow(&pks, i); +// let msg = *std::vector::borrow(&messages, i); +// +// let pk = option::extract(&mut public_key_from_bytes(pk)); +// +// let notok = verify_normal_signature( +// sig, +// &pk, +// msg, +// ); +// assert!(notok == false, 1); +// +// let notok = verify_signature_share( +// sig, +// &PublicKeyWithPoP { bytes: pk.bytes }, +// msg, +// ); +// assert!(notok == false, 1); +// +// i = i + 1; +// } +// } +// +// #[test] +// fun test_verify_normal_signature_or_signature_share_randomized() { +// let (sk, pkpop) = generate_keys(); +// let pk = public_key_with_pop_to_normal(&pkpop); +// +// let msg = b"hello world"; +// let sig = sign_arbitrary_bytes(&sk, msg); +// assert!(verify_normal_signature(&sig, &pk, msg), 1); +// assert!(!verify_normal_signature(&maul_signature(&sig), &pk, msg), 1); +// assert!(!verify_normal_signature(&sig, &maul_public_key(&pk), msg), 1); +// assert!(!verify_normal_signature(&sig, &pk, maul_bytes(&msg)), 1); +// +// assert!(verify_signature_share(&sig, &pkpop, msg), 1); +// assert!(!verify_signature_share(&maul_signature(&sig), &pkpop, msg), 1); +// assert!(!verify_signature_share(&sig, &maul_public_key_with_pop(&pkpop), msg), 1); +// assert!(!verify_signature_share(&sig, &pkpop, maul_bytes(&msg)), 1); +// } +// +// #[test] +// /// Tests verification of random BLS proofs-of-possession (PoPs) +// fun test_verify_pop() { +// // Test case generated by running `cargo test -- sample_pop --nocapture --include-ignored` in `crates/aptos-crypto` +// // ============================================================================================================= +// +// let pks = vector[ +// x"808864c91ae7a9998b3f5ee71f447840864e56d79838e4785ff5126c51480198df3d972e1e0348c6da80d396983e42d7", +// x"8843843c76d167c02842a214c21277bad0bfd83da467cb5cf2d3ee67b2dcc7221b9fafa6d430400164012580e0c34d27", +// x"a23b524d4308d46e43ee8cbbf57f3e1c20c47061ad9c3f915212334ea6532451dd5c01d3d3ada6bea10fe180b2c3b450", +// x"a2aaa3eae1df3fc36365491afa1da5181acbb03801afd1430f04bb3b3eb18036f8b756b3508e4caee04beff50d455d1c", +// x"84985b7e983dbdaddfca1f0b7dad9660bb39fff660e329acec15f69ac48c75dfa5d2df9f0dc320e4e7b7658166e0ac1c", +// ]; +// +// let pops = vector[ +// proof_of_possession_from_bytes(x"ab42afff92510034bf1232a37a0d31bc8abfc17e7ead9170d2d100f6cf6c75ccdcfedbd31699a112b4464a06fd636f3f190595863677d660b4c5d922268ace421f9e86e3a054946ee34ce29e1f88c1a10f27587cf5ec528d65ba7c0dc4863364"), +// proof_of_possession_from_bytes(x"a6da5f2bc17df70ce664cff3e3a3e09d17162e47e652032b9fedc0c772fd5a533583242cba12095602e422e579c5284b1735009332dbdd23430bbcf61cc506ae37e41ff9a1fc78f0bc0d99b6bc7bf74c8f567dfb59079a035842bdc5fa3a0464"), +// proof_of_possession_from_bytes(x"b8eef236595e2eab34d3c1abdab65971f5cfa1988c731ef62bd63c9a9ad3dfc9259f4f183bfffbc8375a38ba62e1c41a11173209705996ce889859bcbb3ddd7faa3c4ea3d8778f30a9ff814fdcfea1fb163d745c54dfb4dcc5a8cee092ee0070"), +// proof_of_possession_from_bytes(x"a03a12fab68ad59d85c15dd1528560eff2c89250070ad0654ba260fda4334da179811d2ecdaca57693f80e9ce977d62011e3b1ee7bb4f7e0eb9b349468dd758f10fc35d54e0d0b8536ca713a77a301944392a5c192b6adf2a79ae2b38912dc98"), +// proof_of_possession_from_bytes(x"8899b294f3c066e6dfb59bc0843265a1ccd6afc8f0f38a074d45ded8799c39d25ee0376cd6d6153b0d4d2ff8655e578b140254f1287b9e9df4e2aecc5b049d8556a4ab07f574df68e46348fd78e5298b7913377cf5bb3cf4796bfc755902bfdd"), +// ]; +// +// assert!(std::vector::length(&pks) == std::vector::length(&pops), 1); +// +// let i = 0; +// while (i < std::vector::length(&pks)) { +// let opt_pk = public_key_from_bytes_with_pop(*std::vector::borrow(&pks, i), std::vector::borrow(&pops, i)); +// assert!(option::is_some(&opt_pk), 1); +// +// i = i + 1; +// }; +// +// // assert first PK's PoP does not verify against modifed PK' = 0xa0 | PK[1:] +// let opt_pk = public_key_from_bytes_with_pop( +// x"a08864c91ae7a9998b3f5ee71f447840864e56d79838e4785ff5126c51480198df3d972e1e0348c6da80d396983e42d7", +// &proof_of_possession_from_bytes(x"ab42afff92510034bf1232a37a0d31bc8abfc17e7ead9170d2d100f6cf6c75ccdcfedbd31699a112b4464a06fd636f3f190595863677d660b4c5d922268ace421f9e86e3a054946ee34ce29e1f88c1a10f27587cf5ec528d65ba7c0dc4863364")); +// assert!(option::is_none(&opt_pk), 1); +// +// // assert first PK's PoP does not verify if modifed as pop' = 0xb0 | pop[1:] +// let opt_pk = public_key_from_bytes_with_pop( +// x"808864c91ae7a9998b3f5ee71f447840864e56d79838e4785ff5126c51480198df3d972e1e0348c6da80d396983e42d7", +// &proof_of_possession_from_bytes(x"bb42afff92510034bf1232a37a0d31bc8abfc17e7ead9170d2d100f6cf6c75ccdcfedbd31699a112b4464a06fd636f3f190595863677d660b4c5d922268ace421f9e86e3a054946ee34ce29e1f88c1a10f27587cf5ec528d65ba7c0dc4863364")); +// assert!(option::is_none(&opt_pk), 1); +// } +// +// #[test] +// fun test_verify_pop_randomized() { +// let (sk, pk) = generate_keys(); +// let pk_bytes = public_key_with_pop_to_bytes(&pk); +// let pop = generate_proof_of_possession(&sk); +// assert!(option::is_some(&public_key_from_bytes_with_pop(pk_bytes, &pop)), 1); +// assert!(option::is_none(&public_key_from_bytes_with_pop(pk_bytes, &maul_proof_of_possession(&pop))), 1); +// assert!(option::is_none(&public_key_from_bytes_with_pop(maul_bytes(&pk_bytes), &pop)), 1); +// } +// } diff --git a/aptos-move/framework/supra-framework/sources/committee_map.move b/aptos-move/framework/supra-framework/sources/committee_map.move index b947263afa931..87dec3c320528 100644 --- a/aptos-move/framework/supra-framework/sources/committee_map.move +++ b/aptos-move/framework/supra-framework/sources/committee_map.move @@ -71,6 +71,7 @@ module supra_framework::committee_map { ip_public_address: vector, // public key to be used for voting node_public_key: vector, + node_bls_public_key: vector, // public key for secure TLS connection network_public_key: vector, cg_public_key: vector, @@ -84,6 +85,7 @@ module supra_framework::committee_map { operator: address, ip_public_address: vector, node_public_key: vector, + node_bls_public_key: vector, network_public_key: vector, cg_public_key: vector, network_port: u16, @@ -211,6 +213,7 @@ module supra_framework::committee_map { operator: addr, ip_public_address: node_info.ip_public_address, node_public_key: node_info.node_public_key, + node_bls_public_key: node_info.node_bls_public_key, network_public_key: node_info.network_public_key, cg_public_key: node_info.cg_public_key, network_port: node_info.network_port, @@ -256,6 +259,7 @@ module supra_framework::committee_map { operator: node_address, ip_public_address: node_info.ip_public_address, node_public_key: node_info.node_public_key, + node_bls_public_key: node_info.node_bls_public_key, network_public_key: node_info.network_public_key, cg_public_key: node_info.cg_public_key, network_port: node_info.network_port, @@ -326,6 +330,7 @@ module supra_framework::committee_map { node_addresses: vector
, ip_public_address: vector>, node_public_key: vector>, + node_bls_public_key: vector>, network_public_key: vector>, cg_public_key: vector>, network_port: vector, @@ -366,6 +371,7 @@ module supra_framework::committee_map { while (vector::length(&node_addresses_for_iteration) > 0) { let ip_public_address = vector::pop_back(&mut ip_public_address); let node_public_key = vector::pop_back(&mut node_public_key); + let node_bls_public_key = vector::pop_back(&mut node_bls_public_key); let network_public_key = vector::pop_back(&mut network_public_key); let cg_public_key = vector::pop_back(&mut cg_public_key); let network_port = vector::pop_back(&mut network_port); @@ -373,6 +379,7 @@ module supra_framework::committee_map { let node_info = NodeInfo { ip_public_address: copy ip_public_address, node_public_key: copy node_public_key, + node_bls_public_key: copy node_bls_public_key, network_public_key: copy network_public_key, cg_public_key: copy cg_public_key, network_port, @@ -420,6 +427,7 @@ module supra_framework::committee_map { node_addresses_bulk: vector>, ip_public_address_bulk: vector>>, node_public_key_bulk: vector>>, + node_bls_public_key_bulk: vector>>, network_public_key_bulk: vector>>, cg_public_key_bulk: vector>>, network_port_bulk: vector>, @@ -461,6 +469,7 @@ module supra_framework::committee_map { let node_addresses = vector::pop_back(&mut node_addresses_bulk); let ip_public_address = vector::pop_back(&mut ip_public_address_bulk); let node_public_key = vector::pop_back(&mut node_public_key_bulk); + let node_bls_public_key = vector::pop_back(&mut node_bls_public_key_bulk); let network_public_key = vector::pop_back(&mut network_public_key_bulk); let cg_public_key = vector::pop_back(&mut cg_public_key_bulk); let network_port = vector::pop_back(&mut network_port_bulk); @@ -473,6 +482,7 @@ module supra_framework::committee_map { node_addresses, ip_public_address, node_public_key, + node_bls_public_key, network_public_key, cg_public_key, network_port, @@ -536,6 +546,7 @@ module supra_framework::committee_map { node_address: address, ip_public_address: vector, node_public_key: vector, + node_bls_public_key: vector, network_public_key: vector, cg_public_key: vector, network_port: u16, @@ -549,6 +560,7 @@ module supra_framework::committee_map { let node_info = NodeInfo { ip_public_address: copy ip_public_address, node_public_key: copy node_public_key, + node_bls_public_key: copy node_bls_public_key, network_public_key: copy network_public_key, cg_public_key: copy cg_public_key, network_port: network_port, @@ -584,6 +596,7 @@ module supra_framework::committee_map { node_addresses: vector
, ip_public_address: vector>, node_public_key: vector>, + node_bls_public_key: vector>, network_public_key: vector>, cg_public_key: vector>, network_port: vector, @@ -623,6 +636,7 @@ module supra_framework::committee_map { let node_address = vector::pop_back(&mut node_addresses); let ip_public_address = vector::pop_back(&mut ip_public_address); let node_public_key = vector::pop_back(&mut node_public_key); + let node_bls_public_key = vector::pop_back(&mut node_bls_public_key); let network_public_key = vector::pop_back(&mut network_public_key); let cg_public_key = vector::pop_back(&mut cg_public_key); let network_port = vector::pop_back(&mut network_port); @@ -634,6 +648,7 @@ module supra_framework::committee_map { node_address, ip_public_address, node_public_key, + node_bls_public_key, network_public_key, cg_public_key, network_port, @@ -664,6 +679,7 @@ module supra_framework::committee_map { committee_member: NodeInfo { ip_public_address: node_info.ip_public_address, node_public_key: node_info.node_public_key, + node_bls_public_key: node_info.node_bls_public_key, network_public_key: node_info.network_public_key, cg_public_key: node_info.cg_public_key, network_port: node_info.network_port, @@ -689,6 +705,7 @@ module supra_framework::committee_map { operator: copy node_address, ip_public_address: vector::empty(), node_public_key: vector::empty(), + node_bls_public_key: vector::empty(), network_public_key: vector::empty(), cg_public_key: vector::empty(), network_port: 0, @@ -700,6 +717,7 @@ module supra_framework::committee_map { operator: copy node_address, ip_public_address: node_info.ip_public_address, node_public_key: node_info.node_public_key, + node_bls_public_key: node_info.node_bls_public_key, network_public_key: node_info.network_public_key, cg_public_key: node_info.cg_public_key, network_port: node_info.network_port, @@ -730,6 +748,7 @@ module supra_framework::committee_map { vector[vector[123], vector[123]], vector[vector[123], vector[123]], vector[vector[123], vector[123]], + vector[vector[123], vector[123]], vector[123, 123], vector[123, 123], 1 @@ -752,6 +771,7 @@ module supra_framework::committee_map { vector[vector[123], vector[123]], vector[vector[123], vector[123]], vector[vector[123], vector[123]], + vector[vector[123], vector[123]], vector[123, 123], vector[123, 123], 1 @@ -765,6 +785,7 @@ module supra_framework::committee_map { vector[123], vector[123], vector[123], + vector[123], 123, 123 ); @@ -785,6 +806,7 @@ module supra_framework::committee_map { vector[vector[123], vector[123]], vector[vector[123], vector[123]], vector[vector[123], vector[123]], + vector[vector[123], vector[123]], vector[123, 123], vector[123, 123], 1 @@ -798,6 +820,7 @@ module supra_framework::committee_map { vector[123], vector[123], vector[123], + vector[123], 123, 123 ); @@ -819,6 +842,7 @@ module supra_framework::committee_map { vector[vector[vector[123], vector[124]], vector[vector[125], vector[126]]], vector[vector[vector[123], vector[124]], vector[vector[125], vector[126]]], vector[vector[vector[123], vector[124]], vector[vector[125], vector[126]]], + vector[vector[vector[123], vector[124]], vector[vector[125], vector[126]]], vector[vector[123, 124], vector[125, 126]], vector[vector[123, 124], vector[125, 126]], vector[1,1] @@ -840,6 +864,7 @@ module supra_framework::committee_map { vector[vector[123], vector[123]], vector[vector[123], vector[123]], vector[vector[123], vector[123]], + vector[vector[123], vector[123]], vector[123, 123], vector[123, 123], 1 @@ -862,6 +887,7 @@ module supra_framework::committee_map { vector[vector[123], vector[123]], vector[vector[123], vector[123]], vector[vector[123], vector[123]], + vector[vector[123], vector[123]], vector[123, 123], vector[123, 123], 1 @@ -875,6 +901,7 @@ module supra_framework::committee_map { vector[vector[123]], vector[vector[123]], vector[vector[123]], + vector[vector[123]], vector[123], vector[123] ); @@ -895,6 +922,7 @@ module supra_framework::committee_map { vector[vector[123], vector[123]], vector[vector[123], vector[123]], vector[vector[123], vector[123]], + vector[vector[123], vector[123]], vector[123, 123], vector[123, 123], 1 @@ -917,6 +945,7 @@ module supra_framework::committee_map { vector[vector[123], vector[123]], vector[vector[123], vector[123]], vector[vector[123], vector[123]], + vector[vector[123], vector[123]], vector[123, 123], vector[123, 123], 1 @@ -940,6 +969,7 @@ module supra_framework::committee_map { vector[vector[123], vector[123]], vector[vector[123], vector[123]], vector[vector[123], vector[123]], + vector[vector[123], vector[123]], vector[123, 123], vector[123, 123], 1 @@ -964,6 +994,7 @@ module supra_framework::committee_map { vector[vector[123], vector[123]], vector[vector[123], vector[123]], vector[vector[123], vector[123]], + vector[vector[123], vector[123]], vector[123, 123], vector[123, 123], 1 @@ -987,6 +1018,7 @@ module supra_framework::committee_map { vector[vector[123], vector[123]], vector[vector[123], vector[123]], vector[vector[123], vector[123]], + vector[vector[123], vector[123]], vector[123, 123], vector[123, 123], 1 @@ -1010,6 +1042,7 @@ module supra_framework::committee_map { vector[vector[123], vector[123]], vector[vector[123], vector[123]], vector[vector[123], vector[123]], + vector[vector[123], vector[123]], vector[123, 123], vector[123, 123], 1 @@ -1033,6 +1066,7 @@ module supra_framework::committee_map { vector[vector[123], vector[123]], vector[vector[123], vector[123]], vector[vector[123], vector[123]], + vector[vector[123], vector[123]], vector[123, 123], vector[123, 123], 1 diff --git a/aptos-move/framework/supra-framework/sources/genesis.move b/aptos-move/framework/supra-framework/sources/genesis.move index 0b42c26955e93..dedb1837ef8da 100644 --- a/aptos-move/framework/supra-framework/sources/genesis.move +++ b/aptos-move/framework/supra-framework/sources/genesis.move @@ -86,6 +86,7 @@ module supra_framework::genesis { voter_address: address, stake_amount: u64, consensus_pubkey: vector, + consensus_bls_pubkey: vector, network_addresses: vector, full_node_network_addresses: vector, } @@ -611,6 +612,7 @@ module supra_framework::genesis { operator, pool_address, validator.consensus_pubkey, + validator.consensus_bls_pubkey ); stake::update_network_and_fullnode_addresses( operator, @@ -830,6 +832,7 @@ module supra_framework::genesis { voter_address: @0x121343, stake_amount: 0, consensus_pubkey: _pk_1, + consensus_bls_pubkey: vector[], network_addresses: x"222222", full_node_network_addresses: x"333333", }, @@ -887,6 +890,7 @@ module supra_framework::genesis { voter_address: @0x121343, stake_amount: 100 * ONE_SUPRA, consensus_pubkey: _pk_1, + consensus_bls_pubkey: vector[], network_addresses: x"222222", full_node_network_addresses: x"333333", }, @@ -930,6 +934,7 @@ module supra_framework::genesis { voter_address: @0x121346, stake_amount: 100 * ONE_SUPRA, consensus_pubkey: _pk_2, + consensus_bls_pubkey: vector[], network_addresses: x"222222", full_node_network_addresses: x"333333", }, diff --git a/aptos-move/framework/supra-framework/sources/stake.move b/aptos-move/framework/supra-framework/sources/stake.move index 2f3e669f6c232..f5eb65bb9326c 100644 --- a/aptos-move/framework/supra-framework/sources/stake.move +++ b/aptos-move/framework/supra-framework/sources/stake.move @@ -153,6 +153,7 @@ module supra_framework::stake { /// Validator info stored in validator address. struct ValidatorConfig has key, copy, store, drop { consensus_pubkey: vector, + consensus_bls_pubkey: vector, network_addresses: vector, // to make it compatible with previous definition, remove later fullnode_addresses: vector, @@ -248,6 +249,8 @@ module supra_framework::stake { pool_address: address, old_consensus_pubkey: vector, new_consensus_pubkey: vector, + old_consensus_bls_pubkey: vector, + new_consensus_bls_pubkey: vector, } #[event] @@ -255,6 +258,8 @@ module supra_framework::stake { pool_address: address, old_consensus_pubkey: vector, new_consensus_pubkey: vector, + old_consensus_bls_pubkey: vector, + new_consensus_bls_pubkey: vector, } struct UpdateNetworkAndFullnodeAddressesEvent has drop, store { @@ -561,6 +566,7 @@ module supra_framework::stake { initialize_owner(owner); move_to(owner, ValidatorConfig { consensus_pubkey: vector::empty(), + consensus_bls_pubkey: vector::empty(), network_addresses: vector::empty(), fullnode_addresses: vector::empty(), validator_index: 0, @@ -583,16 +589,18 @@ module supra_framework::stake { public entry fun initialize_validator( account: &signer, consensus_pubkey: vector, + consensus_bls_pubkey: vector, network_addresses: vector, fullnode_addresses: vector, ) acquires AllowedValidators { // Checks the public key is valid to prevent rogue-key attacks. let valid_public_key = ed25519::new_validated_public_key_from_bytes(consensus_pubkey); assert!(option::is_some(&valid_public_key), error::invalid_argument(EINVALID_PUBLIC_KEY)); - + //DO WE HAVE TO ADD CHECK FOR BLS KEY TOO? I AM NOT SURE. initialize_owner(account); move_to(account, ValidatorConfig { consensus_pubkey, + consensus_bls_pubkey, network_addresses, fullnode_addresses, validator_index: 0, @@ -809,6 +817,7 @@ module supra_framework::stake { operator: &signer, pool_address: address, new_consensus_pubkey: vector, + new_consensus_bls_pubkey: vector, genesis: bool, ) acquires StakePool, ValidatorConfig { assert_reconfig_not_in_progress(); @@ -820,6 +829,7 @@ module supra_framework::stake { assert!(exists(pool_address), error::not_found(EVALIDATOR_CONFIG)); let validator_info = borrow_global_mut(pool_address); let old_consensus_pubkey = validator_info.consensus_pubkey; + let old_consensus_bls_pubkey = validator_info.consensus_bls_pubkey; // Checks the public key is valid to prevent rogue-key attacks. if (!genesis) { let validated_public_key = ed25519::new_validated_public_key_from_bytes(new_consensus_pubkey); @@ -829,13 +839,15 @@ module supra_framework::stake { assert!(option::is_some(&validated_public_key), error::invalid_argument(EINVALID_PUBLIC_KEY)); }; validator_info.consensus_pubkey = new_consensus_pubkey; - + validator_info.consensus_bls_pubkey = new_consensus_bls_pubkey; if (std::features::module_event_migration_enabled()) { event::emit( RotateConsensusKey { pool_address, old_consensus_pubkey, new_consensus_pubkey, + old_consensus_bls_pubkey, + new_consensus_bls_pubkey, }, ); }; @@ -845,6 +857,8 @@ module supra_framework::stake { pool_address, old_consensus_pubkey, new_consensus_pubkey, + old_consensus_bls_pubkey, + new_consensus_bls_pubkey, }, ); } @@ -856,8 +870,9 @@ module supra_framework::stake { operator: &signer, pool_address: address, new_consensus_pubkey: vector, + new_consensus_bls_pubkey: vector, ) acquires StakePool, ValidatorConfig { - rotate_consensus_key_internal(operator, pool_address, new_consensus_pubkey, true); + rotate_consensus_key_internal(operator, pool_address, new_consensus_pubkey, new_consensus_bls_pubkey,true); } /// Rotate the consensus key of the validator, it'll take effect in next epoch. @@ -865,8 +880,9 @@ module supra_framework::stake { operator: &signer, pool_address: address, new_consensus_pubkey: vector, + new_consensus_bls_pubkey: vector, ) acquires StakePool, ValidatorConfig { - rotate_consensus_key_internal(operator, pool_address, new_consensus_pubkey, false); + rotate_consensus_key_internal(operator, pool_address, new_consensus_pubkey, new_consensus_bls_pubkey,false); } /// Update the network and full node addresses of the validator. This only takes effect in the next epoch. @@ -1795,6 +1811,10 @@ module supra_framework::stake { use supra_framework::validator_consensus_info; use supra_framework::validator_consensus_info::ValidatorConsensusInfo; #[test_only] + use aptos_std::bls12381; + #[test_only] + use aptos_std::blsttc; + #[test_only] use aptos_std::fixed_point64; #[test_only] @@ -1812,12 +1832,14 @@ module supra_framework::stake { #[test_only] public fun join_validator_set_for_test( pk: &ed25519::UnvalidatedPublicKey, + bls_pk: &blsttc::PublicKey, operator: &signer, pool_address: address, should_end_epoch: bool, ) acquires SupraCoinCapabilities, StakePool, ValidatorConfig, ValidatorPerformance, ValidatorSet, ValidatorFees { let pk_bytes = ed25519::unvalidated_public_key_to_bytes(pk); - rotate_consensus_key(operator, pool_address, pk_bytes); + let bls_pk_bytes = blsttc::public_key_to_bytes(bls_pk); + rotate_consensus_key(operator, pool_address, pk_bytes, bls_pk_bytes); join_validator_set(operator, pool_address); if (should_end_epoch) { end_epoch(); @@ -1900,8 +1922,10 @@ module supra_framework::stake { account::create_account_for_test(validator_address); }; + let bls_pk_bytes = vector[]; + let pk_bytes = ed25519::unvalidated_public_key_to_bytes(public_key); - initialize_validator(validator, pk_bytes, vector::empty(), vector::empty()); + initialize_validator(validator, pk_bytes, bls_pk_bytes,vector::empty(), vector::empty()); if (amount > 0) { mint_and_add_stake(validator, amount); @@ -1931,6 +1955,7 @@ module supra_framework::stake { voting_power: 0, config: ValidatorConfig { consensus_pubkey: ed25519::unvalidated_public_key_to_bytes(pk), + consensus_bls_pubkey: vector[], network_addresses: b"", fullnode_addresses: b"", validator_index: 0, @@ -1983,6 +2008,13 @@ module supra_framework::stake { (sk, unvalidated_pk) } + #[test_only] + public fun generate_bls_identity(): (blsttc::SecretKey, blsttc::PublicKey) { + let (sk, validated_pub_key) = blsttc::generate_keys(); + let pk = validated_pub_key; + (sk,pk) + } + #[test(supra_framework = @supra_framework, validator = @0x123)] #[expected_failure(abort_code = 0x10007, location = Self)] public entry fun test_inactive_validator_can_add_stake_if_exceeding_max_allowed( @@ -2598,7 +2630,9 @@ module supra_framework::stake { // Validator 1 rotates consensus key. Validator 2 leaves. Validator 3 joins. let (_sk_1b, pk_1b) = generate_identity(); let pk_1b_bytes = ed25519::unvalidated_public_key_to_bytes(&pk_1b); - rotate_consensus_key(validator_1, validator_1_address, pk_1b_bytes); + let (_bsk_1b, bpk_1b) = generate_bls_identity(); + let bpk_1b_bytes = blsttc::public_key_to_bytes(&bpk_1b); + rotate_consensus_key(validator_1, validator_1_address, pk_1b_bytes, bpk_1b_bytes); leave_validator_set(validator_2, validator_2_address); join_validator_set(validator_3, validator_3_address); // Validator 2 is not effectively removed until next epoch. @@ -2687,7 +2721,9 @@ module supra_framework::stake { // Operator can separately rotate consensus key. let (_sk_new, pk_new) = generate_identity(); let pk_new_bytes = ed25519::unvalidated_public_key_to_bytes(&pk_new); - rotate_consensus_key(validator, pool_address, pk_new_bytes); + let (_bsk_new, bpk_new) = generate_bls_identity(); + let bpk_new_bytes = blsttc::public_key_to_bytes(&bpk_new); + rotate_consensus_key(validator, pool_address, pk_new_bytes, bpk_new_bytes); let validator_config = borrow_global(pool_address); assert!(validator_config.consensus_pubkey == pk_new_bytes, 2); @@ -3064,7 +3100,9 @@ module supra_framework::stake { let validator_address = signer::address_of(validator); let (_sk_new, pk_new) = generate_identity(); let pk_new_bytes = ed25519::unvalidated_public_key_to_bytes(&pk_new); - rotate_consensus_key(validator, validator_address, pk_new_bytes); + let (_bsk_new, bpk_new) = generate_bls_identity(); + let bpk_new_bytes = blsttc::public_key_to_bytes(&bpk_new); + rotate_consensus_key(validator, validator_address, pk_new_bytes, bpk_new_bytes); // Join the validator set with enough stake. This now wouldn't fail since the validator config already exists. join_validator_set(validator, validator_address); diff --git a/aptos-move/framework/supra-framework/sources/stake.spec.move b/aptos-move/framework/supra-framework/sources/stake.spec.move index 374b545c55958..8ad626f0ef633 100644 --- a/aptos-move/framework/supra-framework/sources/stake.spec.move +++ b/aptos-move/framework/supra-framework/sources/stake.spec.move @@ -128,6 +128,7 @@ spec supra_framework::stake { spec initialize_validator( account: &signer, consensus_pubkey: vector, + consensus_bls_pubkey: vector, network_addresses: vector, fullnode_addresses: vector, ){ @@ -149,6 +150,7 @@ spec supra_framework::stake { ensures global(post_addr) == OwnerCapability { pool_address: post_addr }; ensures global(post_addr) == ValidatorConfig { consensus_pubkey, + consensus_bls_pubkey, network_addresses, fullnode_addresses, validator_index: 0, @@ -400,6 +402,7 @@ spec supra_framework::stake { operator: &signer, pool_address: address, new_consensus_pubkey: vector, + new_consensus_bls_pubkey: vector, ) { let pre_stake_pool = global(pool_address); let post validator_info = global(pool_address); @@ -421,6 +424,7 @@ spec supra_framework::stake { operator: &signer, pool_address: address, new_consensus_pubkey: vector, + new_consensus_bls_pubkey: vector, genesis: bool, ) { modifies global(pool_address); @@ -717,6 +721,7 @@ spec supra_framework::stake { let addr = signer::address_of(owner); ensures global(addr) == ValidatorConfig { consensus_pubkey: vector::empty(), + consensus_bls_pubkey: vector::empty(), network_addresses: vector::empty(), fullnode_addresses: vector::empty(), validator_index: 0, diff --git a/aptos-move/vm-genesis/src/lib.rs b/aptos-move/vm-genesis/src/lib.rs index abe567af0d969..bdc64e1062ccd 100644 --- a/aptos-move/vm-genesis/src/lib.rs +++ b/aptos-move/vm-genesis/src/lib.rs @@ -9,9 +9,7 @@ mod genesis_context; use std::hash::{Hash, Hasher}; use crate::genesis_context::GenesisStateView; use aptos_crypto::{ - ed25519, - ed25519::{Ed25519PrivateKey, Ed25519PublicKey}, - HashValue, PrivateKey, Uniform, + blsttc, ed25519::{self, Ed25519PrivateKey, Ed25519PublicKey}, HashValue, PrivateKey, Uniform }; use aptos_framework::{ReleaseBundle, ReleasePackage}; use aptos_gas_schedule::{ @@ -1049,6 +1047,10 @@ pub struct Validator { /// ed25519 public key used to sign consensus messages. pub consensus_pubkey: Vec, + + //need to add new feild for bls publickey + pub consensus_bls_pubkey: Vec, + /// `NetworkAddress` for the validator. pub network_addresses: Vec, /// `NetworkAddress` for the validator's full node. @@ -1058,6 +1060,7 @@ pub struct Validator { pub struct TestValidator { pub key: Ed25519PrivateKey, pub consensus_key: ed25519::PrivateKey, + pub consensus_bls_key: blsttc::BlsPrivateKey, pub data: Validator, } @@ -1075,6 +1078,9 @@ impl TestValidator { let owner_address = auth_key.account_address(); let consensus_key = ed25519::PrivateKey::generate(rng); let consensus_pubkey = consensus_key.public_key().to_bytes().to_vec(); + + let consensus_bls_key = blsttc::BlsPrivateKey::generate_random(); + let consensus_bls_pubkey = consensus_bls_key.public_key().to_bytes().to_vec(); let network_address = [0u8; 0].to_vec(); let full_node_network_address = [0u8; 0].to_vec(); @@ -1083,9 +1089,11 @@ impl TestValidator { } else { 0 }; + let data = Validator { owner_address, consensus_pubkey, + consensus_bls_pubkey, operator_address: owner_address, voter_address: owner_address, network_addresses: network_address, @@ -1095,6 +1103,7 @@ impl TestValidator { Self { key, consensus_key, + consensus_bls_key, data, } } diff --git a/consensus/safety-rules/src/test_utils.rs b/consensus/safety-rules/src/test_utils.rs index 07b9159c66a45..e7ae66596605c 100644 --- a/consensus/safety-rules/src/test_utils.rs +++ b/consensus/safety-rules/src/test_utils.rs @@ -41,7 +41,7 @@ pub fn empty_proof() -> Proof { pub fn make_genesis(signer: &ValidatorSigner) -> (EpochChangeProof, QuorumCert) { let validator_info = - ValidatorInfo::new_with_test_network_keys(signer.author(), signer.public_key(), 1, 0); + ValidatorInfo::new_with_test_network_keys(signer.author(), signer.public_key(), None, 1, 0); let validator_set = ValidatorSet::new(vec![validator_info]); let li = LedgerInfo::mock_genesis(Some(validator_set)); let block = Block::make_genesis_block_from_ledger_info(&li); @@ -219,7 +219,7 @@ pub fn make_timeout_cert( pub fn validator_signers_to_ledger_info(signers: &[&ValidatorSigner]) -> LedgerInfo { let infos = signers.iter().enumerate().map(|(index, v)| { - ValidatorInfo::new_with_test_network_keys(v.author(), v.public_key(), 1, index as u64) + ValidatorInfo::new_with_test_network_keys(v.author(), v.public_key(), None, 1, index as u64) }); let validator_set = ValidatorSet::new(infos.collect()); LedgerInfo::mock_genesis(Some(validator_set)) diff --git a/consensus/src/round_manager_fuzzing.rs b/consensus/src/round_manager_fuzzing.rs index 8c58935500ffc..d3781259d3a5a 100644 --- a/consensus/src/round_manager_fuzzing.rs +++ b/consensus/src/round_manager_fuzzing.rs @@ -99,7 +99,7 @@ fn build_empty_store( // helpers for safety rule initialization fn make_initial_epoch_change_proof(signer: &ValidatorSigner) -> EpochChangeProof { let validator_info = - ValidatorInfo::new_with_test_network_keys(signer.author(), signer.public_key(), 1, 0); + ValidatorInfo::new_with_test_network_keys(signer.author(), signer.public_key(), None, 1, 0); let validator_set = ValidatorSet::new(vec![validator_info]); let li = LedgerInfo::mock_genesis(Some(validator_set)); let lis = LedgerInfoWithSignatures::new(li, AggregateSignature::empty()); diff --git a/consensus/src/twins/twins_node.rs b/consensus/src/twins/twins_node.rs index 4d347012544db..3058c86de5d83 100644 --- a/consensus/src/twins/twins_node.rs +++ b/consensus/src/twins/twins_node.rs @@ -232,6 +232,7 @@ impl SMRNode { ValidatorInfo::new_with_test_network_keys( sr_test_config.author, sr_test_config.consensus_key.as_ref().unwrap().public_key(), + None, 1, index as u64, ) diff --git a/crates/aptos-crypto/Cargo.toml b/crates/aptos-crypto/Cargo.toml index eacada812fa56..4824261b6aaf0 100644 --- a/crates/aptos-crypto/Cargo.toml +++ b/crates/aptos-crypto/Cargo.toml @@ -13,6 +13,7 @@ repository = { workspace = true } rust-version = { workspace = true } [dependencies] +blsttc = { workspace = true } aes-gcm = { workspace = true } anyhow = { workspace = true } aptos-crypto-derive = { workspace = true } diff --git a/crates/aptos-crypto/src/blsttc/bls_keys.rs b/crates/aptos-crypto/src/blsttc/bls_keys.rs new file mode 100644 index 0000000000000..21dee441cf30a --- /dev/null +++ b/crates/aptos-crypto/src/blsttc/bls_keys.rs @@ -0,0 +1,243 @@ +#[cfg(any(test, feature = "fuzzing"))] +use crate::test_utils::{self, KeyPair}; +use crate::{ + blsttc::{BlsSignature}, + traits::*, +}; +use aptos_crypto_derive::{SilentDebug, SilentDisplay}; +use core::convert::TryFrom; +#[cfg(any(test, feature = "fuzzing"))] +use proptest::prelude::*; +use serde::{Deserialize, Serialize}; +use std::fmt; +use blsttc::{SecretKey, PublicKeyG2}; + +/// An Ed25519 private key +#[derive(Deserialize, Serialize, SilentDebug, SilentDisplay)] +pub struct BlsPrivateKey(pub(crate) SecretKey); + +#[cfg(feature = "assert-private-keys-not-cloneable")] +static_assertions::assert_not_impl_any!(BlsPrivateKey: Clone); + +#[cfg(any(test, feature = "cloneable-private-keys"))] +impl Clone for BlsPrivateKey { + fn clone(&self) -> Self { + let serialized: [u8;32] = self.0.to_bytes(); + BlsPrivateKey( SecretKey::from_bytes(serialized).unwrap() ) + } +} + +/// An Ed25519 public key +#[derive(Deserialize, Clone, Serialize)] +pub struct BlsPublicKey(pub(crate) PublicKeyG2); + +impl BlsPrivateKey { + /// The length of the BlsPrivateKey + pub const LENGTH: usize = 32; + + /// Serialize an BlsPrivateKey. + pub fn to_bytes(&self) -> [u8; 32] { + self.0.to_bytes() + } + + pub fn generate_random() -> Self { + Self(blsttc::SecretKey::random()) + } + + + /// Deserialize an BlsPrivateKey without any validation checks apart from expected key size. + fn from_bytes_unchecked( + bytes: [u8;32], + ) -> std::result::Result { + match SecretKey::from_bytes(bytes) { + Ok(secret_key) => Ok(BlsPrivateKey(secret_key)), + Err(_) => Err(CryptoMaterialError::DeserializationError), + } + } + + + /// Private function aimed at minimizing code duplication between sign + /// methods of the SigningKey implementation. This should remain private. + fn sign_arbitrary_message(&self, message: &[u8]) -> BlsSignature { + let secret_key: &SecretKey = &self.0; + let sig = secret_key.sign_to_g1(message); + BlsSignature(sig) + } + +} + +impl PrivateKey for BlsPrivateKey { + type PublicKeyMaterial = BlsPublicKey; +} + + +impl Uniform for BlsPrivateKey { + fn generate(rng: &mut R) -> Self + where + R: ::rand::RngCore + ::rand::CryptoRng + ::rand_core::CryptoRng + ::rand_core::RngCore, + { + BlsPrivateKey(SecretKey::random()) + } +} + +impl PartialEq for BlsPrivateKey { + fn eq(&self, other: &Self) -> bool { + self.to_bytes() == other.to_bytes() + } +} + +impl Eq for BlsPrivateKey {} + +impl TryFrom<&[u8]> for BlsPrivateKey { + type Error = CryptoMaterialError; + + /// Deserialize an BlsPrivateKey. This method will check for private key validity: i.e., + /// correct key length. + fn try_from(bytes: &[u8]) -> std::result::Result { + // Note that the only requirement is that the size of the key is 32 bytes, something that + // is already checked during deserialization of ed25519_dalek::SecretKey + // + // Also, the underlying ed25519_dalek implementation ensures that the derived public key + // is safe and it will not lie in a small-order group, thus no extra check for PublicKey + // validation is required. + let bytes: [u8;32] = bytes.try_into().unwrap(); + BlsPrivateKey::from_bytes_unchecked(bytes) + } +} + +impl Length for BlsPrivateKey { + fn length(&self) -> usize { + Self::LENGTH + } +} + +impl ValidCryptoMaterial for BlsPrivateKey { + fn to_bytes(&self) -> Vec { + self.to_bytes().to_vec() + } +} + +impl Genesis for BlsPrivateKey { + fn genesis() -> Self { + Self(SecretKey::random()) + } +} + +impl BlsPublicKey { + /// The maximum size in bytes. + pub const LENGTH: usize = 96; + + /// Serialize an BlsPublicKey. + pub fn to_bytes(&self) -> [u8; 96] { + self.0.to_bytes() + } + + pub fn from_publickeyg2( + key: PublicKeyG2, + ) -> Self { + Self(key) + } + + pub fn to_publickeyg2( + &self + ) -> blsttc::PublicKeyG2 { + self.0.clone() + } + + /// Deserialize an BlsPublicKey without any validation checks apart from expected key size + /// and valid curve point, although not necessarily in the prime-order subgroup. + /// + /// This function does NOT check the public key for membership in a small subgroup. + pub fn from_bytes_unchecked( + bytes: [u8;96], + ) -> std::result::Result { + match PublicKeyG2::from_bytes(bytes) { + Ok(public_key) => Ok(BlsPublicKey(public_key)), + Err(_) => Err(CryptoMaterialError::DeserializationError), + } + } +} + +impl From<&BlsPrivateKey> for BlsPublicKey { + fn from(private_key: &BlsPrivateKey) -> Self { + let secret: &SecretKey = &private_key.0; + let public: PublicKeyG2 = secret.public_key_g2(); + BlsPublicKey(public) + } +} + +impl PublicKey for BlsPublicKey { + type PrivateKeyMaterial = BlsPrivateKey; +} + +impl std::hash::Hash for BlsPublicKey { + fn hash(&self, state: &mut H) { + let encoded_pubkey = self.to_bytes(); + state.write(&encoded_pubkey); + } +} + +// Those are required by the implementation of hash above +impl PartialEq for BlsPublicKey { + fn eq(&self, other: &BlsPublicKey) -> bool { + self.to_bytes() == other.to_bytes() + } +} + +impl Eq for BlsPublicKey {} + +impl fmt::Display for BlsPublicKey { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{}", hex::encode(self.0.to_bytes())) + } +} + +impl fmt::Debug for BlsPublicKey { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "BlsPublicKey({})", self) + } +} + +impl TryFrom<&[u8]> for BlsPublicKey { + type Error = CryptoMaterialError; + + /// Deserialize an BlsPublicKey. This method will NOT check for key validity, which means + /// the returned public key could be in a small subgroup. Nonetheless, our signature + /// verification implicitly checks if the public key lies in a small subgroup, so canonical + /// uses of this library will not be susceptible to small subgroup attacks. + fn try_from(bytes: &[u8]) -> std::result::Result { + let bytes : [u8;96] = bytes.try_into().unwrap(); + Ok(BlsPublicKey(PublicKeyG2::from_bytes(bytes).unwrap())) + } +} + +impl Length for BlsPublicKey { + fn length(&self) -> usize { + 96 + } +} + +impl ValidCryptoMaterial for BlsPublicKey { + fn to_bytes(&self) -> Vec { + self.0.to_bytes().to_vec() + } +} + +/// Produces a uniformly random Ed25519 keypair from a seed +#[cfg(any(test, feature = "fuzzing"))] +pub fn keypair_strategy() -> impl Strategy> { + test_utils::uniform_keypair_strategy::() +} + +/// Produces a uniformly random Ed25519 public key +#[cfg(any(test, feature = "fuzzing"))] +impl proptest::arbitrary::Arbitrary for BlsPublicKey { + type Parameters = (); + type Strategy = BoxedStrategy; + + fn arbitrary_with(_args: Self::Parameters) -> Self::Strategy { + crate::test_utils::uniform_keypair_strategy::() + .prop_map(|v| v.public_key) + .boxed() + } +} diff --git a/crates/aptos-crypto/src/blsttc/bls_sigs.rs b/crates/aptos-crypto/src/blsttc/bls_sigs.rs new file mode 100644 index 0000000000000..a3671a53c2ee3 --- /dev/null +++ b/crates/aptos-crypto/src/blsttc/bls_sigs.rs @@ -0,0 +1,25 @@ +use crate::{ + ed25519::{Ed25519PrivateKey, Ed25519PublicKey, ED25519_SIGNATURE_LENGTH}, + hash::CryptoHash, + traits::*, +}; +use anyhow::{anyhow, Result}; +use aptos_crypto_derive::{DeserializeKey, SerializeKey}; +use blsttc::SignatureG1; +use core::convert::TryFrom; +use serde::{Deserialize, Serialize}; +use std::{cmp::Ordering, fmt}; + +/// An Ed25519 signature +#[derive(Deserialize, Clone, Serialize)] +pub struct BlsSignature(pub(crate) SignatureG1); + +impl BlsSignature { + /// The length of the BlsSignature + pub const LENGTH: usize = 48; + + /// Serialize an BlsSignature. + pub fn to_bytes(&self) -> [u8; 48] { + self.0.to_bytes() + } +} \ No newline at end of file diff --git a/crates/aptos-crypto/src/blsttc/mod.rs b/crates/aptos-crypto/src/blsttc/mod.rs new file mode 100644 index 0000000000000..1f13f22a998ef --- /dev/null +++ b/crates/aptos-crypto/src/blsttc/mod.rs @@ -0,0 +1,5 @@ +pub mod bls_keys; +pub mod bls_sigs; + +pub use bls_keys::{BlsPrivateKey, BlsPublicKey}; +pub use bls_sigs::BlsSignature; diff --git a/crates/aptos-crypto/src/lib.rs b/crates/aptos-crypto/src/lib.rs index 2141f191d4a14..d7678b0397540 100644 --- a/crates/aptos-crypto/src/lib.rs +++ b/crates/aptos-crypto/src/lib.rs @@ -3,10 +3,11 @@ // SPDX-License-Identifier: Apache-2.0 #![forbid(unsafe_code)] -#![deny(missing_docs)] +// #![deny(missing_docs)] //! A library supplying various cryptographic primitives pub mod asymmetric_encryption; +pub mod blsttc; pub mod bls12381; pub mod bulletproofs; pub mod compat; @@ -29,6 +30,7 @@ pub mod poseidon_bn254; #[cfg(test)] mod unit_tests; + pub use self::traits::*; pub use hash::HashValue; // Reexport once_cell and serde_name for use in CryptoHasher Derive implementation. diff --git a/crates/aptos-genesis/src/config.rs b/crates/aptos-genesis/src/config.rs index 74de119403c73..cb818e4863ad1 100644 --- a/crates/aptos-genesis/src/config.rs +++ b/crates/aptos-genesis/src/config.rs @@ -2,7 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 use aptos_config::config::HANDSHAKE_VERSION; -use aptos_crypto::{ed25519, ed25519::Ed25519PublicKey, x25519}; +use aptos_crypto::{blsttc, ed25519::{self, Ed25519PublicKey}, x25519}; use aptos_types::{ account_address::{AccountAddress, AccountAddressWithChecks}, chain_id::ChainId, @@ -245,11 +245,13 @@ impl TryFrom for Validator { vec![] }; + //used empty vector here, cause i think we are not using this code here, because we have our own ValidatorNodeIndentity stucts Ok(Validator { owner_address, operator_address, voter_address, consensus_pubkey, + consensus_bls_pubkey : Vec::new(), network_addresses: bcs::to_bytes(&validator_addresses).unwrap(), full_node_network_addresses: bcs::to_bytes(&full_node_addresses).unwrap(), stake_amount: config.stake_amount, diff --git a/crates/aptos-telemetry-service/src/validator_cache.rs b/crates/aptos-telemetry-service/src/validator_cache.rs index 53afae31d1a38..de4450a0911ea 100644 --- a/crates/aptos-telemetry-service/src/validator_cache.rs +++ b/crates/aptos-telemetry-service/src/validator_cache.rs @@ -199,7 +199,7 @@ mod tests { let validator_info = ValidatorInfo::new( PeerId::random(), 10, - ValidatorConfig::new(keypair.public_key, vec![0, 0], vec![0, 0], 2), + ValidatorConfig::new(keypair.public_key, None, vec![0, 0], vec![0, 0], 2), ); let validator_set = ValidatorSet::new(vec![validator_info]); @@ -244,6 +244,7 @@ mod tests { 10, ValidatorConfig::new( keypair.public_key, + None, bcs::to_bytes(&vec![NetworkAddress::from_str("/dns/a5f3d921730874389bb2f66275f163a5-8f14ad5b5e992c1c.elb.ap-southeast-1.amazonaws.com/tcp/6180/noise-ik/0xc5edf62233096df793b554e1013b07c83d01b3cf50c14ac83a0a7e0cfe340426/handshake/0").unwrap()]).unwrap(), bcs::to_bytes(&vec![NetworkAddress::from_str("/dns/fullnode0.testnet.aptoslabs.com/tcp/6182/noise-ik/0xea19ab47ed9191865f15d85d751ed0663205c0b2f0f465714b1947c023715973/handshake/0").unwrap()]).unwrap(), 2, diff --git a/crates/aptos/src/node/mod.rs b/crates/aptos/src/node/mod.rs index f91f9a0674c75..c501e690dcf58 100644 --- a/crates/aptos/src/node/mod.rs +++ b/crates/aptos/src/node/mod.rs @@ -25,7 +25,7 @@ use aptos_backup_cli::{ utils::GlobalRestoreOpt, }; use aptos_cached_packages::aptos_stdlib; -use aptos_crypto::{ed25519, ed25519::PublicKey, x25519, ValidCryptoMaterialStringExt}; +use aptos_crypto::{blsttc::{self, BlsPrivateKey}, ed25519::{self, PublicKey}, x25519, PrivateKey, ValidCryptoMaterialStringExt}; use aptos_genesis::config::{HostAndPort, OperatorConfiguration}; use aptos_logger::Level; use aptos_network_checker::args::{ @@ -48,6 +48,7 @@ use async_trait::async_trait; use bcs::Result; use chrono::{DateTime, NaiveDateTime, Utc}; use clap::Parser; +use diesel::expression::is_aggregate::No; use serde::{Deserialize, Serialize}; use std::{ collections::HashMap, @@ -616,6 +617,7 @@ impl CliCommand for InitializeValidator { self.txn_options .submit_transaction(aptos_stdlib::stake_initialize_validator( consensus_public_key.to_bytes().to_vec(), + vec![], // BCS encode, so that we can hide the original type bcs::to_bytes(&validator_network_addresses)?, bcs::to_bytes(&full_node_network_addresses)?, @@ -923,6 +925,7 @@ impl From<&ValidatorInfoSummary> for ValidatorInfo { summary.consensus_voting_power, aptos_types::validator_config::ValidatorConfig::new( PublicKey::from_encoded_string(&config.consensus_public_key).unwrap(), + blsttc::BlsPrivateKey::generate_random().public_key(), bcs::to_bytes(&config.validator_network_addresses).unwrap(), bcs::to_bytes(&config.fullnode_network_addresses).unwrap(), config.validator_index, @@ -1050,7 +1053,7 @@ impl CliCommand for UpdateConsensusKey { self.txn_options .submit_transaction(aptos_stdlib::stake_rotate_consensus_key( address, - consensus_public_key.to_bytes().to_vec(), + consensus_public_key.to_bytes().to_vec(),vec![] )) .await .map(|inner| inner.into()) diff --git a/network/discovery/src/validator_set.rs b/network/discovery/src/validator_set.rs index 6f8305950ae1b..aa34af5762fee 100644 --- a/network/discovery/src/validator_set.rs +++ b/network/discovery/src/validator_set.rs @@ -156,7 +156,7 @@ mod tests { use crate::DiscoveryChangeListener; use aptos_channels::{aptos_channel, message_queues::QueueStyle}; use aptos_config::config::HANDSHAKE_VERSION; - use aptos_crypto::{ed25519, x25519::PrivateKey, PrivateKey as PK, Uniform}; + use aptos_crypto::{blsttc, ed25519, x25519::PrivateKey, PrivateKey as PK, Uniform}; use aptos_event_notifications::ReconfigNotification; use aptos_types::{ network_address::NetworkAddress, @@ -254,6 +254,7 @@ mod tests { 0, ValidatorConfig::new( consensus_pubkey, + blsttc::BlsPrivateKey::generate_random().public_key(), validator_encoded_addresses, fullnode_encoded_addresses, 0, diff --git a/types/src/proptest_types.rs b/types/src/proptest_types.rs index a433546a00b9e..1269ec9f1df1d 100644 --- a/types/src/proptest_types.rs +++ b/types/src/proptest_types.rs @@ -34,10 +34,7 @@ use crate::{ write_set::{WriteOp, WriteSet, WriteSetMut}, }; use aptos_crypto::{ - ed25519::{self, Ed25519PrivateKey, Ed25519PublicKey}, - test_utils::KeyPair, - traits::*, - HashValue, + blsttc, ed25519::{self, Ed25519PrivateKey, Ed25519PublicKey}, test_utils::KeyPair, traits::*, HashValue }; use arr_macro::arr; use bytes::Bytes; @@ -1051,6 +1048,7 @@ impl BlockInfoGen { ValidatorInfo::new_with_test_network_keys( signer.author(), signer.public_key(), + blsttc::BlsPrivateKey::generate_random().public_key(), 1, /* consensus_voting_power */ index as u64, ) diff --git a/types/src/validator_config.rs b/types/src/validator_config.rs index 3e2354ee998dc..89472059dfe7e 100644 --- a/types/src/validator_config.rs +++ b/types/src/validator_config.rs @@ -3,7 +3,7 @@ // SPDX-License-Identifier: Apache-2.0 use crate::network_address::NetworkAddress; -use aptos_crypto::ed25519; +use aptos_crypto::{blsttc, ed25519}; use move_core_types::{ ident_str, identifier::IdentStr, @@ -36,6 +36,7 @@ impl MoveResource for ValidatorOperatorConfigResource {} #[cfg_attr(any(test, feature = "fuzzing"), derive(Arbitrary))] pub struct ValidatorConfig { pub consensus_public_key: ed25519::PublicKey, + pub consensus_bls_public_key: blsttc::BlsPublicKey, /// This is an bcs serialized `Vec` pub validator_network_addresses: Vec, /// This is an bcs serialized `Vec` @@ -46,12 +47,14 @@ pub struct ValidatorConfig { impl ValidatorConfig { pub fn new( consensus_public_key: ed25519::PublicKey, + consensus_bls_public_key: blsttc::BlsPublicKey, validator_network_addresses: Vec, fullnode_network_addresses: Vec, validator_index: u64, ) -> Self { ValidatorConfig { consensus_public_key, + consensus_bls_public_key, validator_network_addresses, fullnode_network_addresses, validator_index, diff --git a/types/src/validator_info.rs b/types/src/validator_info.rs index 01f5c7f3fd09d..95a71a5d90686 100644 --- a/types/src/validator_info.rs +++ b/types/src/validator_info.rs @@ -5,12 +5,12 @@ #[cfg(any(test, feature = "fuzzing"))] use crate::network_address::NetworkAddress; use crate::{account_address::AccountAddress, validator_config::ValidatorConfig}; -use aptos_crypto::ed25519; +use aptos_crypto::{ed25519, PrivateKey}; #[cfg(any(test, feature = "fuzzing"))] use proptest_derive::Arbitrary; use serde::{Deserialize, Serialize}; use std::fmt; - +use aptos_crypto::blsttc; /// After executing a special transaction indicates a change to the next epoch, consensus /// and networking get the new list of validators, their keys, and their voting power. Consensus /// has a public key to validate signed messages and networking will has public identity @@ -56,12 +56,15 @@ impl ValidatorInfo { pub fn new_with_test_network_keys( account_address: AccountAddress, consensus_public_key: ed25519::PublicKey, + consensus_bls_public_key: blsttc::BlsPublicKey, consensus_voting_power: u64, validator_index: u64, ) -> Self { + let addr = NetworkAddress::mock(); let config = ValidatorConfig::new( consensus_public_key, + consensus_bls_public_key, bcs::to_bytes(&vec![addr.clone()]).unwrap(), bcs::to_bytes(&vec![addr]).unwrap(), validator_index, @@ -85,6 +88,10 @@ impl ValidatorInfo { &self.config.consensus_public_key } + pub fn consensus_bls_public_key(&self) -> &blsttc::BlsPublicKey { + &self.config.consensus_bls_public_key + } + /// Returns the voting power for this validator pub fn consensus_voting_power(&self) -> u64 { self.consensus_voting_power diff --git a/types/src/validator_verifier.rs b/types/src/validator_verifier.rs index a13f7b695754b..7fcb04d549c98 100644 --- a/types/src/validator_verifier.rs +++ b/types/src/validator_verifier.rs @@ -11,7 +11,7 @@ use crate::{ }; use anyhow::{ensure, Result}; use aptos_bitvec::BitVec; -use aptos_crypto::{ed25519, ed25519::PublicKey, hash::CryptoHash, Signature, VerifyingKey}; +use aptos_crypto::{blsttc, ed25519::{self, PublicKey}, hash::CryptoHash, PrivateKey as _, Signature, VerifyingKey}; use itertools::Itertools; #[cfg(any(test, feature = "fuzzing"))] use proptest_derive::Arbitrary; @@ -504,6 +504,7 @@ impl From<&ValidatorVerifier> for ValidatorSet { crate::validator_info::ValidatorInfo::new_with_test_network_keys( addr, verifier.get_public_key(&addr).unwrap(), + blsttc::BlsPrivateKey::generate_random().public_key(), verifier.get_voting_power(&addr).unwrap(), index as u64, )