-
Notifications
You must be signed in to change notification settings - Fork 329
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
CIP-0022: Pool Operator Verification
- Loading branch information
1 parent
7913cf5
commit 0e850d0
Showing
1 changed file
with
99 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
--- | ||
CIP: 22 | ||
Title: Pool operator verification | ||
Authors: Andrew Westberg <[email protected]> | ||
Comments-URI: no comments yet | ||
Status: Draft | ||
Type: Informational | ||
Created: 2021-06-21 | ||
License: CC-BY-4.0 | ||
--- | ||
|
||
# Abstract | ||
|
||
This proposal describes a method allowing a stakepool operator to provide credentials to verify that they are the rightful manager for their stakepool. | ||
|
||
# Motivation | ||
|
||
Many websites such pooltool.io, adapools.org, and others need to allow pool operators special access to modify the way their pool appears on the website. SPOCRA and other organizations also have a need to allow voting on proposals and ensure that each vote cast is from a valid pool operator. Today, these sites and organizations all use different techniques for validating pool operators. | ||
|
||
pooltool.io - Validates operators by receiving 1 ada spent from the pool's registered rewards account | ||
|
||
adapools.org - Validates operators by requesting that the operator include a special generated value in their extended pool metadata json file. | ||
|
||
This proposal desires to simplify and streamline a single approach that all can reference in order to verify that a pool operator is who they say they are. | ||
|
||
Current Tools that have implemented it already or have plans to implement it: | ||
* [CNCLI](https://github.com/AndrewWestberg/cncli) | ||
* [JorManager](https://bitbucket.org/muamw10/jormanager/) | ||
|
||
# Specification | ||
|
||
In order to achieve the goals of this CIP, the pool operator needs to provide some credential or credentials to the validating party which cannot be spoofed. The VRF pool keys and VRF signature algorithm implemented in libsodium are chosen to build and provide this credential/signature. This signature can then be validated and the operator verified without ever exposing any of the pool's private key information. This technique is very similar to verifying that a block produced by another pool is valid. The only difference is that instead of validating the slot seed for a given pool, we're validating a pre-determined message hash. | ||
|
||
Code Example (Pool Operator side): | ||
``` | ||
// Node operational VRF-Verification-Key: pool.vrf.vkey | ||
//{ | ||
// "type": "VrfVerificationKey_PraosVRF", | ||
// "description": "VRF Verification Key", | ||
// "cborHex": "5820e0ff2371508ac339431b50af7d69cde0f120d952bb876806d3136f9a7fda4381" | ||
//} | ||
// | ||
// Node operational VRF-Signing-Key: pool.vrf.skey | ||
//{ | ||
// "type": "VrfSigningKey_PraosVRF", | ||
// "description": "VRF Signing Key", | ||
// "cborHex": "5840adb9c97bec60189aa90d01d113e3ef405f03477d82a94f81da926c90cd46a374e0ff2371508ac339431b50af7d69cde0f120d952bb876806d3136f9a7fda4381" | ||
//} | ||
// We assume the pool operator has access to the pool's vrf secret key | ||
val skeyCbor = "5840adb9c97bec60189aa90d01d113e3ef405f03477d82a94f81da926c90cd46a374e0ff2371508ac339431b50af7d69cde0f120d952bb876806d3136f9a7fda4381".hexToByteArray() | ||
val vrfSkey = (CborReader.createFromByteArray(skeyCbor).readDataItem() as CborByteString).byteArrayValue() | ||
val vkeyCbor = "5820e0ff2371508ac339431b50af7d69cde0f120d952bb876806d3136f9a7fda4381".hexToByteArray() | ||
val vrfVkey = (CborReader.createFromByteArray(vkeyCbor).readDataItem() as CborByteString).byteArrayValue() | ||
// Client side, sign the hash of a pre-determined message | ||
val message = "pooltool.io".toByteArray() | ||
val messageHash = SodiumLibrary.cryptoBlake2bHash(message, null) | ||
println("messageHash: ${messageHash.toHexString()}") | ||
val signature = SodiumLibrary.cryptoVrfProve(vrfSkey, messageHash) | ||
println("signature: ${signature.toHexString()}") | ||
``` | ||
|
||
Code Example (Validating server): | ||
``` | ||
// We assume that the client has sent us the pool_id, signature, and we know the public pool.vrf.vkey | ||
// We also know the pre-determined message that we've asked the client to sign. In this case "pooltool.io" | ||
val message = "pooltool.io".toByteArray() | ||
val messageHash = SodiumLibrary.cryptoBlake2bHash(message, null) | ||
// get the vkeyHash for a pool from the "query pool-params" cardano-cli command | ||
val vkeyHash = "f58bf0111f8e9b233c2dcbb72b5ad400330cf260c6fb556eb30cefd387e5364c".hexToByteArray() | ||
// Verify that the vkey the client supplied is the same as the one on-chain | ||
val vkeyHashVerify = SodiumLibrary.cryptoBlake2bHash(vrfVkey, null) | ||
assertThat(vkeyHash).isEqualTo(vkeyHashVerify) | ||
// Verify that the signature is a valid format. This will fail if the signature is mal-formed | ||
val signatureHash = SodiumLibrary.cryptoVrfProofToHash(signature) | ||
println("signatureHash: ${signatureHash.toHexString()}") | ||
// Verify that the signature matches | ||
val verification = SodiumLibrary.cryptoVrfVerify(vrfVkey, signature, messageHash) | ||
println("verification: ${verification.toHexString()}") | ||
assertThat(signatureHash).isEqualTo(verification) | ||
println("Verification SUCCESS!") | ||
``` | ||
|
||
# Rationale | ||
|
||
Implementing this simplies and commonizes the process for verifying that a pool operator is who they say they are in 3rd party systems. Having a common way of verify pool operators also allows simple integration into pool management tools. There is also some overlap with [CIP-006](https://github.com/cardano-foundation/CIPs/blob/master/CIP-0006/CIP-0006.md#extended-metadata---flexible-but-validable) and the `rawdata-sign` command although it chooses to generate a new key instead of utilizing the pool's existing vrf.skey to sign like this proposal. | ||
|
||
# Copyright | ||
|
||
This CIP is licensed under [CC-BY-4.0](https://creativecommons.org/licenses/by/4.0/legalcode) |