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

Adapt KES usage to new, non-pure, interface #558

Open
iquerejeta opened this issue Sep 15, 2022 · 6 comments
Open

Adapt KES usage to new, non-pure, interface #558

iquerejeta opened this issue Sep 15, 2022 · 6 comments
Assignees

Comments

@iquerejeta
Copy link

iquerejeta commented Sep 15, 2022

We are changing the way the KES keys are handled, to increase the guarantees that the key is not copied to disk and safely deleted by mlocking the secret data. These changes have modified the KES interface, which use to expose pure functions, to a non-pure interface.

The changes are being performed in IntersectMBO/cardano-base#255 and IntersectMBO/cardano-base#317.

To be able to work on this, the PRs mentioned above need to be merged.

@marshada
Copy link

marshada commented Nov 1, 2022

I'll discuss with Vitor first to assess priority. We should have someone assess the scope of work for this. Nick or Duncan likely needed but with other team member perhaps leading this as much as possible.

@dnadales
Copy link
Member

dnadales commented Nov 1, 2022

@nfrisby could we make an initial estimation of the size of this issue, that is useful input for @marshada

@nfrisby
Copy link
Contributor

nfrisby commented Nov 1, 2022

The use of KES keys is isolated within the block forging logic, which is relatively small and self-contained---much more so than UTxO HD. Moreover, that code is already (entirely?) monadified.

Upon inspecting the cardano-base PRs, I see some encouraging elements (such as MonadSodium, which we might need to include in eg our IOLike), but it's also not yet fully clear to me which parts of this KES interface the Consensus code directly relies on.


My due diligence notes:

The Consensus Layer receives a ProtocolInfo from the node.

data ProtocolInfo m b = ProtocolInfo { ..., pInfoBlockForging :: m [BlockForging m b] }

Each BlockForging (there's at most one, in production) contains stateful methods:

data BlockForging m blk = BlockForging {
      ...
    , updateForgeState :: ... -> m (ForgeStateUpdateInfo blk)
    , checkCanForge ::
           ...
        -> ForgeStateInfo blk  -- Proof that 'updateForgeState' did not fail
        -> Either (CannotForge blk) ()
    , forgeBlock :: ... -> m blk
    }

The KES keys are maintain by those methods; the key is part of the functions' closures. The functions in this interface are all already in m; this is why I'm optimistic the upstream monadification won't be particular invasive.

Though the node passes the BlockForging to the Consensus layer, our code also provides the functions the node uses to construct those BlockForging. This is where the ouroboros-consensus* code touches KES keys. For example:

praosSharedBlockForging ::
  forall m c era.
  ( ShelleyEraWithCrypto c (Praos c) era,
    IOLike m
  )
  => HotKey.HotKey c m
  -> (SlotNo -> Absolute.KESPeriod)
  -> ShelleyLeaderCredentials c
  -> TxLimits.Overrides (ShelleyBlock (Praos c) era)
  -> BlockForging m     (ShelleyBlock (Praos c) era)

The code uses the name HotKey for the interface it uses to touch the KES key. Note that its operations are again already in m.

data HotKey c m = HotKey {
      evolve     :: Absolute.KESPeriod -> m KESEvolutionInfo
    , ...
    , sign_      :: forall toSign. (SL.KESignable c toSign, HasCallStack)
                 => toSign -> m (SL.SignedKES c toSign)
    }

Ultimately, the hotkey is created from a "initial signing key", which the node supplies when it calls these helper functions we provide. (EG look for shelleyLeaderCredentialsInitSignKey.) I'm pretty sure that this work will make that key just be a handle to mlocked memory, but that's fine: it's just an input we pipe through and then pass to our invocations of the KES interface (which are all already in a monad).

The only KES function I see being used in a pure context is verifyKES. If I understand the upstream PRs correctly, this will still be pure.

@nfrisby
Copy link
Contributor

nfrisby commented Nov 1, 2022

Based on the above, I think "a few days" is at least a possibility. I'd be able to establish a lot more certainty if there's simply a cardano-base branch I could point the ouroboros-consensus code at and see where GHC compilation errors identify where the upstream interface changes need to be integrated.

There could be plenty I'm underestimating. EG I see new crypto types in the upstream PRs. I think those are ultimately backwards compatible with the crypto used through the implementation now, right? So I'm currently estimating that's not going to require much integration work (just changing a name, really). (IE we can use this new crypto type constructor for all the old eras?)

@iquerejeta
Copy link
Author

Great, thanks a lot for the estimates @nfrisby . After a discussion with @lehins, we've come to the conclusion of slightly changing the memory allocator, which may slightly affect the interface of KES. The non-pure interface will remain there, but we might need to pass around a context. @tdammers and @lehins will be working on it IntersectMBO/cardano-base#336. Once we have that ready, we can provide with a branch in cardano-base.

@tdammers
Copy link

Little update from my end: I have now integrated @lehins' pooled allocator, and I chose to do it in such a way that the KES API does not require any further changes.

@dnadales dnadales transferred this issue from IntersectMBO/ouroboros-network Nov 30, 2023
@jorisdral jorisdral moved this to 🏗 In progress in Consensus Team Backlog May 31, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Status: 🏗 In progress
Development

No branches or pull requests

6 participants