fuel-core icon indicating copy to clipboard operation
fuel-core copied to clipboard

Add the logic that allows rotation of the PoA key

Open xgreenx opened this issue 1 year ago • 1 comments

The PoA key is defined by the ChainConfig and currently supports only one value. We need to support the key's rotation. As an example, we could have a new variant with listed PoA key rotations.

pub enum ConsensusConfig {
    PoA {
        signing_key: Address,
    },
    RotatedPoA {
        /// The key of the map is the block height at which the rotation occurs.
        /// The value is the new signing key.
        rotations: BTreeMap<BlockHeight, Address>,
    },
}

xgreenx avatar May 18 '24 06:05 xgreenx

For the default_poa function for the RotatedPoA Variant the BTreeMap would be generated from this SecretKey::new_from_mnemonic_phrase_with_path(<PHRASE>, <PATH>) where PATH is offsetted by format!("m/44'/60'/0'/0/{}", nKeys) would be the correct approach to generate the keys right?

/// A default secret key to use for testing purposes only
pub fn default_consensus_dev_key() -> SecretKey {
    // Derived from:
    //  - Mnemonic phrase: "winner alley monkey elephant sun off boil hope toward boss bronze dish"
    //  - Path: "m/44'/60'/0'/0/0"
    // Equivalent to:
    //  `SecretKey::new_from_mnemonic_phrase_with_path(..)`
    let bytes: [u8; 32] = [
        0xfb, 0xe4, 0x91, 0x78, 0xda, 0xc2, 0xdf, 0x5f, 0xde, 0xa7, 0x4a, 0x11, 0xa9,
        0x0f, 0x99, 0x77, 0x62, 0x5f, 0xe0, 0x23, 0xcd, 0xf6, 0x41, 0x4b, 0xfd, 0x63,
        0x9d, 0x32, 0x7a, 0x2e, 0x9d, 0xdb,
    ];
    SecretKey::try_from(bytes.as_slice()).expect("valid key")
}

The primary PoA is generated from these PATHs and PHRASE

EDIT: I just realised these are dev_keys... So another likely approach could be is to hash the keys received from the Secret::default_consensus_dev_key() something like this (with a nonce counter or something) and then insert it into the BTree or AVL Tree...

impl SecretKey{
    // other methods ....

    pub fn rotate(&self, nonce: u32) -> Self {
        let mut hasher = Sha256::new();
        hasher.update(self.as_ref());
        hasher.update(&nonce.to_le_bytes());
        let result = hasher.finalize();
        let mut new_key = [0u8; Self::LEN];
        new_key.copy_from_slice(&result[0..Self::LEN]);
        SecretKey(Bytes32::from(new_key))
    }
}

dontdothatjoel avatar May 25 '24 10:05 dontdothatjoel