Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

For a same verifier (based on its BLS private key), the address in metadata and consensus could be different. #1511

Closed
yangby-cryptape opened this issue Oct 27, 2023 · 3 comments · Fixed by #1641
Assignees
Labels
d:confirmation Discussion required to confirm whether it's a bug question Further information is requested t:help Extra attention is needed

Comments

@yangby-cryptape
Copy link
Collaborator

yangby-cryptape commented Oct 27, 2023

Description

  • When initialize the chain data, metadata.verifier_list are loaded from the chain-spec.toml.

    Click for details.

    pub params: Metadata,

    pub verifier_list: Vec<ValidatorExtend>,

    pub struct ValidatorExtend {
    pub bls_pub_key: Hex,
    pub pub_key: Hex,
    pub address: H160,
    #[cfg_attr(feature = "hex-serialize", serde(serialize_with = "serialize_uint"))]
    pub propose_weight: u32,
    #[cfg_attr(feature = "hex-serialize", serde(serialize_with = "serialize_uint"))]
    pub vote_weight: u32,
    }

  • And it is written into storage directly.

    Click for details.

    let metadata_0 = spec.params.clone();

    axon/core/run/src/lib.rs

    Lines 444 to 450 in 363b49f

    let resp = execute_genesis_transactions(
    &partial_genesis,
    db_group,
    &spec.accounts,
    &[metadata_0, metadata_1],
    spec.genesis.generate_hardfork_info(),
    )?;

    system_contract::init(db_group.inner_db(), &mut backend, metadata_list, hardfork)?;

    init_metadata_and_hardfork(adapter, ret.0, metadata_list, hardfork)?;

    store.append_metadata(&metadata_list[0])?;
    store.append_metadata(&metadata_list[1])?;

  • But when initialize the crypto data for consensus, the pub_key is replaced and address is abandoned.

    axon/core/run/src/lib.rs

    Lines 363 to 372 in 363b49f

    let mut bls_pub_keys = HashMap::new();
    for validator_extend in validators.iter() {
    let address = validator_extend.pub_key.as_bytes();
    let hex_pubkey = validator_extend.bls_pub_key.as_bytes();
    let pub_key = BlsPublicKey::try_from(hex_pubkey.as_ref()).map_err(MainError::Crypto)?;
    bls_pub_keys.insert(address, pub_key);
    }
    let crypto = OverlordCrypto::new(bls_priv_key, bls_pub_keys, String::new());
    Ok(Arc::new(crypto))

    🤔 The following steps make me confused deeply.

    • Generate new address from original pub_key.
    • Generate new pub_key from original bls_pub_key.
    • Original address is abandoned.

    So, why users have to provide the addresses?

    p.s.: I checked, the logic is same as the logic before refactor axon commands line. (ref: previous version).

  • Back to the metadata contract, it uses the original address which is stored in storage.

    let handle = MetadataHandle::new(CURRENT_METADATA_ROOT.with(|r| *r.borrow()));
    if !exec_try!(
    handle.is_validator(block_number, sender),
    gas_limit,
    "[metadata] is validator"
    ) {

    pub fn is_validator(&self, block_number: u64, address: H160) -> ProtocolResult<bool> {
    let metadata = self.get_metadata_by_block_number(block_number)?;
    Ok(metadata.verifier_list.iter().any(|v| v.address == address))
    }

Question

  • What does it mean? Is is a bug?

  • If there is an address stored in metadata, but it could not be derived from its corresponding public key, what would happen?

@KaoImin
Copy link
Contributor

KaoImin commented Nov 3, 2023

axon/core/run/src/lib.rs

Lines 363 to 372 in 363b49f

let mut bls_pub_keys = HashMap::new();
for validator_extend in validators.iter() {
let address = validator_extend.pub_key.as_bytes();
let hex_pubkey = validator_extend.bls_pub_key.as_bytes();
let pub_key = BlsPublicKey::try_from(hex_pubkey.as_ref()).map_err(MainError::Crypto)?;
bls_pub_keys.insert(address, pub_key);
}
let crypto = OverlordCrypto::new(bls_priv_key, bls_pub_keys, String::new());
Ok(Arc::new(crypto))

The crux of this question is these code. As you can see, the bls_pub_keys variable is an argument of OverlordCrypto, and it is only used in OverlordCrypto.
/// The `private_key` is the blst private key of the node. The `addr_pubkey` is
/// a map to get the blst public key by the address. To be notice that the
/// address uses secp256k1 **public key** which is same as the `address` field
/// in `Node` struct. Use secp256k1 public key instead of address can reduce the
/// `keccak256` hash calculation at the end of each height. The reason why not
/// use address directly is that the `PeerId` is binding with public key not
/// address.
pub struct OverlordCrypto {
private_key: BlsPrivateKey,
addr_pubkey: RwLock<HashMap<Bytes, BlsPublicKey>>,
common_ref: String,
}
impl Crypto for OverlordCrypto {

OverlordCrypto is employed for signing and verifying consensus message signatures. Due to Axon's utilization of aggregated signatures, some messages don't require broadcasting; an unicast to a peer suffices. To facilitate this, the consensus module must include the peer's P2P address. The peer's public key is stored in the network instead of an address, thus a secp256k1 public key serves as the address in this context.

@yangby-cryptape
Copy link
Collaborator Author

yangby-cryptape commented Nov 3, 2023

Thanks for your comment.

Let's just simplify things.

[[params.verifier_list]]
bls_pub_key = "0xa26e3fe1cf51bd4822072c61bdc315ac32e3d3c2e2484bb92942666399e863b4bf56cf2926383cc706ffc15dfebc85c6"
pub_key = "0x031ddc35212b7fc7ff6685b17d91f77c972535aee5c7ae5684d3e72b986f08834b"
address = "0x8ab0cf264df99d83525e9e11c7e4db01558ae1b1"

net_privkey_file = "net.key"
bls_privkey_file = "bls.key"

As you said above, is the following description right?

- net_privkey_file -> params.verifier_list.address         # thus a secp256k1 public key serves as the address in this context.
- bls_privkey_file -> params.verifier_list.bls_pub_key
- What's `params.verifier_list.pub_key`?

Please copy and modify the above content, you can just use lines to point the relation, instead of complex description.

@Flouse Flouse added t:help Extra attention is needed question Further information is requested labels Nov 3, 2023
@yangby-cryptape
Copy link
Collaborator Author

As I know, each node have at most 2 private keys: one is secp256k1 key and one is bls key.

  • If I'm right, but each verifier has be configured 3 things -- bls_pub_key, pub_key and address -- so which 2 of them are related? And, are these 2 related things checked, before writing into metadata?

  • If I'm wrong, which is the 3rd private key?

@Flouse Flouse added d:confirmation Discussion required to confirm whether it's a bug and removed agenda labels Dec 11, 2023
@Flouse Flouse linked a pull request Dec 18, 2023 that will close this issue
3 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
d:confirmation Discussion required to confirm whether it's a bug question Further information is requested t:help Extra attention is needed
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants