feat(API): Add signing api to the node
Implementation ideas
Add API to sign an arbitrary bytes using node key and return it to the caller.
I feel like rather exposing the signature interface, the user should be able to specify the private key in the constructor (and even handle key management/storage themselves if they want).
related to https://github.com/celestiaorg/celestia-node/discussions/3022
As a start, we could add a method to the Node module like:
SignPayload(ctx context.Context, keyName string, payload []byte) ([]byte, error)
that would be hidden behind admin level permissions and would allow an API user to submit an arbitrary payload to be signed by the node's account key by the given keyName.
Thoughts?
I would add it behind state module
@Wondertan it's not really related to state access though, it's just related to using the node's keyring.
It's not node either, but in my head, it is closer to state, as this signing feature will use the same key as we use for transaction signing in state. Also, the state module is already a pile of miscellaneous vaguely related calls; the node, on the other hand, is stricter and more organized imo.
Also, would add the following method to the list:
VerifySignedPayload(ctx context.Context, publicKey state.AccAddress, payload []byte) (bool, error)
This method would take the given public key (passed as a state.AccAddress) and verify that the given payload was signed by that key.
Let’s make this part of cel-key instead of node api. We don’t need to have an ability to sign it within runtime.
Seems like some teams are requesting the signing bit to be a part of the node's API instead of a separate binary. What are everyone's thoughts on a simple Sign module that contains these two methods and potentially others related to signing later on? Instead of shoving it into node or state where they don't really belong.
Okay the final conclusion here then is the following:
We want an additional sign module (just like we have node and state modules). This sign module should have two endpoints to start:
// SignPayload takes the given payload, signs it with the key by the given keyName and returns it.
SignPayload(ctx context.Context, keyName string, payload []byte) ([]byte, error)
// VerifySignedPayload checks whether the given payload was signed by the given publicKey.
VerifySignedPayload(ctx context.Context, publicKey state.AccAddress, signedPayload []byte) (bool, error)
The sign module should be defined in the nodebuilder package (like all other modules). See the das module definition for a good example. The sign module's methods should be protected by admin level permissions, as is done in the node module's Info endpoint for example.
The most difficult component of this is figuring out how to plumb the components together via the dep injection library we use (uber/fx). For this component, the node team will be able to assist for any questions.
One more suggestion from me to call it not sign, but keyring or wallet. It ain't gonna stop at only two methods. I see this as foundation for further methods controlling the underlying keyring.
Agreed to the above ^
Seems like some teams are requesting the signing bit to be a part of the node's API instead of a separate binary
What teams are these and why do they want to use the node api to sign arbitrary bytes?
An endpoint would be preferable. Ideally the caller wouldn’t have to install a separate binary
cc @preston-evans98
What do we imagine blob submitters need to sign over other than PFBs and other Celestia state transactions. I just want to make sure we're focused on providing DA or Celestia specific functionality and not on necessarily becoming a generic wallet.
In our case, we need sequencers on the rollup to set config on the rollup. We can easily do that by linking a Celestia address to a rollup address - but in order to do that, we need to be able to sign a message with the Celestia key saying "I control this rollup address")
I see. Thanks for the context!
I agree that it should really be it's own module. To be clear, I was thinking that the key manager should be something independent from the light node and could be customised/provided by the developer (especially if they want to use it for other purposes). But I'm not strongly opinionated. We can just proxy through most of the keyring functionality
Notes from call:
- Is this useful to any other external teams?
- The
cel-keybinary can already sign bytes - Expands celestia-node's API surface area
- Does celestia-node binary do it's own key management? Currently uses Cosmos SDK keyring.
- This issue exposes the current key management and key usage over the celestia-node API.